1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.plugin.feed

File XWikiFeedFetcher.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart0.png
83% of files have more coverage

Code metrics

36
99
12
2
301
202
38
0.38
8.25
6
3.17

Classes

Class Line # Actions
XWikiFeedFetcher 47 99 0% 38 147
0.00%
XWikiFeedFetcher.CredentialSupplier 297 0 - 0 0
-1.0 -
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.plugin.feed;
21   
22    import java.io.IOException;
23    import java.io.InputStream;
24    import java.net.HttpURLConnection;
25    import java.net.MalformedURLException;
26    import java.net.URL;
27    import java.util.zip.GZIPInputStream;
28   
29    import org.apache.commons.httpclient.Credentials;
30    import org.apache.commons.httpclient.Header;
31    import org.apache.commons.httpclient.HttpClient;
32    import org.apache.commons.httpclient.HttpMethod;
33    import org.apache.commons.httpclient.UsernamePasswordCredentials;
34    import org.apache.commons.httpclient.auth.AuthScope;
35    import org.apache.commons.httpclient.methods.GetMethod;
36   
37    import com.sun.syndication.feed.synd.SyndFeed;
38    import com.sun.syndication.fetcher.FetcherEvent;
39    import com.sun.syndication.fetcher.FetcherException;
40    import com.sun.syndication.fetcher.impl.AbstractFeedFetcher;
41    import com.sun.syndication.fetcher.impl.FeedFetcherCache;
42    import com.sun.syndication.fetcher.impl.SyndFeedInfo;
43    import com.sun.syndication.io.FeedException;
44    import com.sun.syndication.io.SyndFeedInput;
45    import com.sun.syndication.io.XmlReader;
46   
 
47    public class XWikiFeedFetcher extends AbstractFeedFetcher
48    {
49    private FeedFetcherCache feedInfoCache;
50   
51    private CredentialSupplier credentialSupplier;
52   
 
53  0 toggle public XWikiFeedFetcher()
54    {
55  0 super();
56    }
57   
58    /**
59    * @param cache
60    */
 
61  0 toggle public XWikiFeedFetcher(FeedFetcherCache cache)
62    {
63  0 this();
64  0 setFeedInfoCache(cache);
65    }
66   
 
67  0 toggle public XWikiFeedFetcher(FeedFetcherCache cache, CredentialSupplier credentialSupplier)
68    {
69  0 this(cache);
70  0 setCredentialSupplier(credentialSupplier);
71    }
72   
73    /**
74    * @return the feedInfoCache.
75    */
 
76  0 toggle public synchronized FeedFetcherCache getFeedInfoCache()
77    {
78  0 return feedInfoCache;
79    }
80   
81    /**
82    * @param feedInfoCache the feedInfoCache to set
83    */
 
84  0 toggle public synchronized void setFeedInfoCache(FeedFetcherCache feedInfoCache)
85    {
86  0 this.feedInfoCache = feedInfoCache;
87    }
88   
89    /**
90    * @return Returns the credentialSupplier.
91    */
 
92  0 toggle public synchronized CredentialSupplier getCredentialSupplier()
93    {
94  0 return credentialSupplier;
95    }
96   
97    /**
98    * @param credentialSupplier The credentialSupplier to set.
99    */
 
100  0 toggle public synchronized void setCredentialSupplier(CredentialSupplier credentialSupplier)
101    {
102  0 this.credentialSupplier = credentialSupplier;
103    }
104   
 
105  0 toggle @Override
106    public SyndFeed retrieveFeed(URL feedUrl)
107    throws IllegalArgumentException, IOException, FeedException, FetcherException
108    {
109  0 return retrieveFeed(feedUrl, 0);
110    }
111   
112    /**
113    * @see com.sun.syndication.fetcher.FeedFetcher#retrieveFeed(java.net.URL)
114    */
 
115  0 toggle public SyndFeed retrieveFeed(URL feedUrl, int timeout)
116    throws IllegalArgumentException, IOException, FeedException, FetcherException
117    {
118  0 if (feedUrl == null) {
119  0 throw new IllegalArgumentException("null is not a valid URL");
120    }
121  0 HttpClient client = new HttpClient();
122  0 if (timeout != 0) {
123  0 client.getParams().setSoTimeout(timeout);
124  0 client.getParams().setParameter("http.connection.timeout", timeout);
125    }
126   
127  0 System.setProperty("http.useragent", getUserAgent());
128  0 client.getParams().setParameter("httpclient.useragent", getUserAgent());
129   
130  0 String proxyHost = System.getProperty("http.proxyHost");
131  0 String proxyPort = System.getProperty("http.proxyPort");
132  0 if ((proxyHost != null) && (!proxyHost.equals(""))) {
133  0 int port = 3128;
134  0 if ((proxyPort != null) && (!proxyPort.equals(""))) {
135  0 port = Integer.parseInt(proxyPort);
136    }
137  0 client.getHostConfiguration().setProxy(proxyHost, port);
138    }
139   
140  0 String proxyUser = System.getProperty("http.proxyUser");
141  0 if ((proxyUser != null) && (!proxyUser.equals(""))) {
142  0 String proxyPassword = System.getProperty("http.proxyPassword");
143  0 Credentials defaultcreds = new UsernamePasswordCredentials(proxyUser, proxyPassword);
144  0 client.getState().setProxyCredentials(AuthScope.ANY, defaultcreds);
145    }
146   
147  0 String urlStr = feedUrl.toString();
148  0 FeedFetcherCache cache = getFeedInfoCache();
149  0 if (cache != null) {
150    // retrieve feed
151  0 HttpMethod method = new GetMethod(urlStr);
152  0 method.addRequestHeader("Accept-Encoding", "gzip");
153  0 try {
154  0 if (isUsingDeltaEncoding()) {
155  0 method.setRequestHeader("A-IM", "feed");
156    }
157   
158    // get the feed info from the cache
159    // Note that syndFeedInfo will be null if it is not in the cache
160  0 SyndFeedInfo syndFeedInfo = cache.getFeedInfo(feedUrl);
161  0 if (syndFeedInfo != null) {
162  0 method.setRequestHeader("If-None-Match", syndFeedInfo.getETag());
163   
164  0 if (syndFeedInfo.getLastModified() instanceof String) {
165  0 method.setRequestHeader("If-Modified-Since", (String) syndFeedInfo.getLastModified());
166    }
167    }
168   
169  0 method.setFollowRedirects(true);
170   
171  0 int statusCode = client.executeMethod(method);
172  0 fireEvent(FetcherEvent.EVENT_TYPE_FEED_POLLED, urlStr);
173  0 handleErrorCodes(statusCode);
174   
175  0 SyndFeed feed = getFeed(syndFeedInfo, urlStr, method, statusCode);
176   
177  0 syndFeedInfo = buildSyndFeedInfo(feedUrl, urlStr, method, feed, statusCode);
178   
179  0 cache.setFeedInfo(new URL(urlStr), syndFeedInfo);
180   
181    // the feed may have been modified to pick up cached values
182    // (eg - for delta encoding)
183  0 feed = syndFeedInfo.getSyndFeed();
184   
185  0 return feed;
186    } finally {
187  0 method.releaseConnection();
188    }
189    } else {
190    // cache is not in use
191  0 HttpMethod method = new GetMethod(urlStr);
192  0 try {
193  0 method.setFollowRedirects(true);
194   
195  0 int statusCode = client.executeMethod(method);
196  0 fireEvent(FetcherEvent.EVENT_TYPE_FEED_POLLED, urlStr);
197  0 handleErrorCodes(statusCode);
198   
199  0 return getFeed(null, urlStr, method, statusCode);
200    } finally {
201  0 method.releaseConnection();
202    }
203    }
204    }
205   
206    /**
207    * @param feedUrl
208    * @param urlStr
209    * @param method
210    * @param feed
211    * @return
212    * @throws MalformedURLException
213    */
 
214  0 toggle private SyndFeedInfo buildSyndFeedInfo(URL feedUrl, String urlStr, HttpMethod method, SyndFeed feed, int statusCode)
215    throws MalformedURLException
216    {
217  0 SyndFeedInfo syndFeedInfo;
218  0 syndFeedInfo = new SyndFeedInfo();
219   
220    // this may be different to feedURL because of 3XX redirects
221  0 syndFeedInfo.setUrl(new URL(urlStr));
222  0 syndFeedInfo.setId(feedUrl.toString());
223   
224  0 Header imHeader = method.getResponseHeader("IM");
225  0 if (imHeader != null && imHeader.getValue().indexOf("feed") >= 0 && isUsingDeltaEncoding()) {
226  0 FeedFetcherCache cache = getFeedInfoCache();
227  0 if (cache != null && statusCode == 226) {
228    // client is setup to use http delta encoding and the server supports it and has returned a delta
229    // encoded response.
230    // This response only includes new items
231  0 SyndFeedInfo cachedInfo = cache.getFeedInfo(feedUrl);
232  0 if (cachedInfo != null) {
233  0 SyndFeed cachedFeed = cachedInfo.getSyndFeed();
234   
235    // set the new feed to be the orginal feed plus the new items
236  0 feed = combineFeeds(cachedFeed, feed);
237    }
238    }
239    }
240   
241  0 Header lastModifiedHeader = method.getResponseHeader("Last-Modified");
242  0 if (lastModifiedHeader != null) {
243  0 syndFeedInfo.setLastModified(lastModifiedHeader.getValue());
244    }
245   
246  0 Header eTagHeader = method.getResponseHeader("ETag");
247  0 if (eTagHeader != null) {
248  0 syndFeedInfo.setETag(eTagHeader.getValue());
249    }
250   
251  0 syndFeedInfo.setSyndFeed(feed);
252   
253  0 return syndFeedInfo;
254    }
255   
 
256  0 toggle private static SyndFeed retrieveFeed(String urlStr, HttpMethod method)
257    throws IOException, FeedException
258    {
259   
260  0 InputStream stream = null;
261  0 if ((method.getResponseHeader("Content-Encoding") != null) &&
262    ("gzip".equalsIgnoreCase(method.getResponseHeader("Content-Encoding").getValue())))
263    {
264  0 stream = new GZIPInputStream(method.getResponseBodyAsStream());
265    } else {
266  0 stream = method.getResponseBodyAsStream();
267    }
268  0 try {
269  0 XmlReader reader = null;
270  0 if (method.getResponseHeader("Content-Type") != null) {
271  0 reader = new XmlReader(stream, method.getResponseHeader("Content-Type").getValue(), true);
272    } else {
273  0 reader = new XmlReader(stream, true);
274    }
275  0 return new SyndFeedInput().build(reader);
276    } finally {
277  0 if (stream != null) {
278  0 stream.close();
279    }
280    }
281    }
282   
 
283  0 toggle private SyndFeed getFeed(SyndFeedInfo syndFeedInfo, String urlStr, HttpMethod method, int statusCode)
284    throws IOException, FeedException
285    {
286   
287  0 if (statusCode == HttpURLConnection.HTTP_NOT_MODIFIED && syndFeedInfo != null) {
288  0 fireEvent(FetcherEvent.EVENT_TYPE_FEED_UNCHANGED, urlStr);
289  0 return syndFeedInfo.getSyndFeed();
290    }
291   
292  0 SyndFeed feed = retrieveFeed(urlStr, method);
293  0 fireEvent(FetcherEvent.EVENT_TYPE_FEED_RETRIEVED, urlStr, feed);
294  0 return feed;
295    }
296   
 
297    public interface CredentialSupplier
298    {
299    public Credentials getCredentials(String realm, String host);
300    }
301    }