View Javadoc

1   /*
2    * Copyright 2004 Sun Microsystems, Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  
18  package com.sun.syndication.fetcher.impl;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.net.URLConnection;
23  import java.util.Collections;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.Properties;
27  import java.util.Set;
28  
29  import com.sun.syndication.feed.synd.SyndFeed;
30  import com.sun.syndication.fetcher.FeedFetcher;
31  import com.sun.syndication.fetcher.FetcherEvent;
32  import com.sun.syndication.fetcher.FetcherException;
33  import com.sun.syndication.fetcher.FetcherListener;
34  
35  
36  public abstract class AbstractFeedFetcher implements FeedFetcher {
37  	private Set fetcherEventListeners;
38  	private String userAgent;
39  	private boolean usingDeltaEncoding;	
40      
41  	public AbstractFeedFetcher() {
42  		fetcherEventListeners = Collections.synchronizedSet(new HashSet());
43  		String fetcherVersion = "UNKNOWN";
44  		
45  		Properties props = new Properties(System.getProperties());
46  		String resourceName = "fetcher.properties";
47  		
48  		try {
49  			InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(resourceName);
50  			if (inputStream == null) {
51  			    inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName);
52  			}			
53  			if (inputStream != null) {
54  				props.load(inputStream);
55  				System.getProperties().putAll(props);
56  				inputStream.close();
57  			} else {
58  				System.err.println("Could not find " + resourceName + " on classpath");
59  			}
60  		} catch (IOException e) {
61  			// do nothing - we don't want to fail just because we could not find the version
62  			System.err.println("Error reading " + resourceName + " from classpath: " + e.getMessage());
63  		}		
64  		
65  		
66  		userAgent =  DEFAULT_USER_AGENT + " Ver: " + System.getProperty("rome.fetcher.version", "UNKNOWN");
67  	}
68  
69  	/***
70  	 * @return the User-Agent currently being sent to servers
71  	 */
72  	public String getUserAgent() {
73  		return userAgent;
74  	}
75  
76  	/***
77  	 * @param string The User-Agent to sent to servers
78  	 */
79  	public void setUserAgent(String string) {
80  		userAgent = string;
81  	}
82  
83  	/***
84  	 * @param eventType The event type to fire
85  	 * @param connection the current connection
86  	 */
87  	protected void fireEvent(String eventType, URLConnection connection) {
88  		fireEvent(eventType, connection.toString());
89  	}
90  
91  	/***
92  	 * @param eventType The event type to fire
93  	 * @param urlStr the current url as a string
94  	 */
95  	protected void fireEvent(String eventType, String urlStr) {
96  		FetcherEvent fetcherEvent = new FetcherEvent(this, urlStr, eventType);
97  		synchronized(fetcherEventListeners) {
98  			Iterator iter = fetcherEventListeners.iterator();
99  			while ( iter.hasNext()) {
100 				FetcherListener fetcherEventListener = (FetcherListener) iter.next();
101 				fetcherEventListener.fetcherEvent(fetcherEvent);							
102 			}					
103 		}
104 	}	
105 	
106 	/***
107 	 * @see com.sun.syndication.fetcher.FeedFetcher#addFetcherEventListener(com.sun.syndication.fetcher.FetcherListener)
108 	 */
109 	public void addFetcherEventListener(FetcherListener listener) {
110 		if (listener != null) {
111 			fetcherEventListeners.add(listener);		
112 		}	
113 		
114 	}
115 
116 	/***
117 	 * @see com.sun.syndication.fetcher.FeedFetcher#removeFetcherPolledListener(com.sun.syndication.fetcher.FetcherListener)
118 	 */
119 	public void removeFetcherPolledListener(FetcherListener listener) {
120 		if (listener != null) {
121 			fetcherEventListeners.remove(listener);		
122 		}		
123 	}
124 
125     /***
126      * @return Returns the useDeltaEncoding.
127      */
128     public boolean isUsingDeltaEncoding() {
129         return usingDeltaEncoding;
130     }
131     /***
132      * @param useDeltaEncoding The useDeltaEncoding to set.
133      */
134     public void setUsingDeltaEncoding(boolean useDeltaEncoding) {
135         this.usingDeltaEncoding = useDeltaEncoding;
136     }		
137 	
138 	/***
139 	 * <p>Handles HTTP error codes.</p>
140 	 *
141 	 * @param responseCode the HTTP response code
142 	 * @throws FetcherException if response code is in the range 400 to 599 inclusive
143 	 */
144 	protected void handleErrorCodes(int responseCode) throws FetcherException {
145 		// Handle 2xx codes as OK, so ignore them here
146 		// 3xx codes are handled by the HttpURLConnection class
147 	    if (responseCode == 403) {
148 	        // Authentication is required
149 	        throwAuthenticationError(responseCode);
150 	    } else if (responseCode >= 400 && responseCode < 500) {
151 			throw4XXError(responseCode);
152 		} else if (responseCode >= 500 && responseCode < 600) {
153 			throw new FetcherException(responseCode, "The server encounted an error. HTTP Response code was:" + responseCode);
154 		}
155 	}
156 	
157 	protected void throw4XXError(int responseCode) throws FetcherException {
158 		throw new FetcherException(responseCode, "The requested resource could not be found. HTTP Response code was:" + responseCode);
159 	}
160 
161 	protected void throwAuthenticationError(int responseCode) throws FetcherException {
162 		throw new FetcherException(responseCode, "Authentication required for that resource. HTTP Response code was:" + responseCode);
163 	}
164 	
165 	/***
166 	 * <p>Combine the entries in two feeds into a single feed.</p>
167 	 * 
168 	 * <p>The returned feed will have the same data as the newFeed parameter, with 
169 	 * the entries from originalFeed appended to the end of its entries.</p>
170 	 * 
171 	 * @param originalFeed
172 	 * @param newFeed
173 	 * @return
174 	 */
175 	public static SyndFeed combineFeeds(SyndFeed originalFeed, SyndFeed newFeed) {
176 	    SyndFeed result;
177         try {
178             result = (SyndFeed) newFeed.clone();
179             
180             result.getEntries().addAll(result.getEntries().size(), originalFeed.getEntries());
181             
182             return result;
183         } catch (CloneNotSupportedException e) {
184             IllegalArgumentException iae = new IllegalArgumentException("Cannot clone feed");
185             iae.initCause(e);
186             throw iae;
187         }        
188 	}
189 	
190 }