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  package com.sun.syndication.fetcher.impl;
18  
19  import java.net.URL;
20  
21  import junit.framework.TestCase;
22  
23  import org.mortbay.http.BasicAuthenticator;
24  import org.mortbay.http.HashUserRealm;
25  import org.mortbay.http.HttpContext;
26  import org.mortbay.http.HttpServer;
27  import org.mortbay.http.SecurityConstraint;
28  import org.mortbay.http.SocketListener;
29  import org.mortbay.http.UserRealm;
30  import org.mortbay.http.handler.SecurityHandler;
31  import org.mortbay.jetty.servlet.ServletHandler;
32  
33  import com.sun.syndication.feed.synd.SyndEntry;
34  import com.sun.syndication.feed.synd.SyndFeed;
35  import com.sun.syndication.fetcher.FeedFetcher;
36  import com.sun.syndication.fetcher.FetcherEvent;
37  import com.sun.syndication.fetcher.FetcherException;
38  import com.sun.syndication.fetcher.FetcherListener;
39  
40  /***
41   * @author nl
42   */
43  public abstract class AbstractJettyTest extends TestCase {
44  
45  	private HttpServer server;
46  	
47  	/***
48  	 * @param s
49  	 */
50  	public AbstractJettyTest(String s) {
51  		super(s);
52  	}
53  
54  	protected HttpServer getServer() {
55  		return server;
56  	}
57  
58  	protected abstract FeedFetcher getFeedFetcher();
59  	
60  	protected abstract FeedFetcher getFeedFetcher(FeedFetcherCache cache);
61  	
62  	/***
63  	 * @see junit.framework.TestCase#setUp()
64  	 */
65  	protected void setUp() throws Exception {
66  		setupServer();
67  	
68  		HttpContext context = createContext();
69  		
70  		ServletHandler servlets = createServletHandler();
71  		context.addHandler(servlets);
72  		
73  		server.addContext(context);		
74  		
75  		server.start();
76  	}
77  
78  	/***
79       * @throws InterruptedException
80       */
81      private void setupServer() throws InterruptedException {
82          // Create the server
83  		if (server != null) {
84  			server.stop();
85  			server = null;
86  		}
87  		server = new HttpServer();
88  	
89  		// Create a port listener
90  		SocketListener listener=new SocketListener();
91  		listener.setPort(8080);
92  		server.addListener(listener);
93      }
94  
95      /***
96       * @return
97       */
98      private ServletHandler createServletHandler() {
99          ServletHandler servlets = new ServletHandler();
100 		servlets.addServlet("FetcherTestServlet","/FetcherTestServlet/*","com.sun.syndication.fetcher.impl.FetcherTestServlet");
101         return servlets;
102     }
103 
104     /***
105      * @return
106      */
107     private HttpContext createContext() {
108         HttpContext context = new HttpContext();
109 		context.setContextPath("/rome/*");
110         return context;
111     }
112 
113     /***
114 	 * @see junit.framework.TestCase#tearDown()
115 	 */
116 	protected void tearDown() throws Exception {
117 		if (server != null) {
118 			server.stop();
119 			server.destroy();
120 			server = null;
121 		}
122 	}
123 
124 	class FetcherEventListenerImpl implements FetcherListener {
125 		boolean polled = false;
126 		boolean retrieved = false;
127 		boolean unchanged = false;
128 
129 		public void reset() {
130 			polled = false;
131 			retrieved = false;
132 			unchanged = false;
133 		}
134 
135 		/***
136 		 * @see com.sun.syndication.fetcher.FetcherListener#fetcherEvent(com.sun.syndication.fetcher.FetcherEvent)
137 		 */
138 		public void fetcherEvent(FetcherEvent event) {
139 			String eventType = event.getEventType();
140 			if (FetcherEvent.EVENT_TYPE_FEED_POLLED.equals(eventType)) {
141 				System.err.println("\tEVENT: Feed Polled. URL = " + event.getUrlString());
142 				polled = true;
143 			} else if (FetcherEvent.EVENT_TYPE_FEED_RETRIEVED.equals(eventType)) {
144 				System.err.println("\tEVENT: Feed Retrieved. URL = " + event.getUrlString());
145 				retrieved = true;
146 			} else if (FetcherEvent.EVENT_TYPE_FEED_UNCHANGED.equals(eventType)) {
147 				System.err.println("\tEVENT: Feed Unchanged. URL = " + event.getUrlString());
148 				unchanged = true;
149 			}
150 		}
151 	}
152 
153 	public void testRetrieveFeed() {
154 		FeedFetcher feedFetcher = getFeedFetcher();
155 		try {
156 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet/"));
157 			assertNotNull(feed);
158 			assertEquals("atom_0.3.feed.title", feed.getTitle());
159 		} catch (Exception e) {
160 			e.printStackTrace();
161 			fail(e.getMessage());
162 		}
163 	}
164 
165 	public void testBasicAuthentication() {	    
166 		try {
167             setupServer();
168             
169             HttpContext context = createContext();
170 
171             URL url = this.getClass().getResource("/testuser.properties");            
172             UserRealm ur = new HashUserRealm("test", url.getFile());						
173             context.setRealm(ur);
174 
175             BasicAuthenticator ba = new BasicAuthenticator();
176             context.setAuthenticator(ba);		
177             
178             SecurityHandler sh =  new SecurityHandler();					
179             context.addHandler(sh);
180 
181             SecurityConstraint sc = new SecurityConstraint();
182             sc.setName("test");
183             sc.addRole("*");
184             sc.setAuthenticate(true);		
185             context.addSecurityConstraint("/", sc);			
186             
187             ServletHandler servlets = createServletHandler();
188             context.addHandler(servlets);
189             
190             server.addContext(context);		
191             
192             server.start();            
193             
194             FeedFetcher feedFetcher = getAuthenticatedFeedFetcher();
195 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet/"));
196 			assertNotNull(feed);
197 			assertEquals("atom_0.3.feed.title", feed.getTitle());
198             
199             
200         } catch (Exception e) {
201             e.printStackTrace();
202             fail(e.getMessage());
203         }	    
204 	    
205 		
206 	}
207 	
208 	public abstract FeedFetcher getAuthenticatedFeedFetcher();
209 	
210 	/***
211 	 * Test getting a feed via a http 301 redirect
212 	 *
213 	 */
214 	public void testRetrieveRedirectedFeed() {
215 		FeedFetcher feedFetcher = getFeedFetcher();
216 		try {
217 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet?redirect=TRUE"));
218 			assertNotNull(feed);
219 			assertEquals("atom_0.3.feed.title", feed.getTitle());
220 		} catch (Exception e) {
221 			e.printStackTrace();
222 			fail(e.getMessage());
223 		}
224 	}
225 
226 	/***
227 	 * Test error handling
228 	 *
229 	 */
230 	public void testErrorHandling() {
231 		FeedFetcher feedFetcher = getFeedFetcher();
232 		try {
233 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet?error=404"));
234 			fail("4xx error handling did not work correctly");
235 		} catch (FetcherException e) {
236 			// expect this exception
237 			assertEquals(404, e.getResponseCode());
238 		} catch (Exception e) {
239 			e.printStackTrace();
240 			fail(e.getMessage());
241 		}
242 	
243 		try {
244 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet?error=500"));
245 			fail("5xx error handling did not work correctly");
246 		} catch (FetcherException e) {
247 			// expect this exception
248 			assertEquals(500, e.getResponseCode());
249 		} catch (Exception e) {
250 			e.printStackTrace();
251 			fail(e.getMessage());
252 		}
253 	}
254 
255 	public void testUserAgent() {
256 		FeedFetcher feedFetcher = getFeedFetcher();
257 		//System.out.println(feedFetcher.getUserAgent());
258 		//System.out.println(System.getProperty("rome.fetcher.version", "UNKNOWN"));
259 		assertEquals("Rome Client (http://tinyurl.com/64t5n) Ver: " + System.getProperty("rome.fetcher.version", "UNKNOWN"), feedFetcher.getUserAgent());
260 	}
261 
262 	/***
263 	 * Test events fired when there is no cache in use
264 	 *
265 	 */
266 	public void testFetchEvents() {
267 		FeedFetcher feedFetcher = getFeedFetcher();
268 		FetcherEventListenerImpl listener = new FetcherEventListenerImpl();
269 		feedFetcher.addFetcherEventListener(listener);
270 		try {
271 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet/"));
272 			assertNotNull(feed);
273 			assertTrue(listener.polled);
274 			assertTrue(listener.retrieved);
275 			assertFalse(listener.unchanged);
276 			listener.reset();
277 	
278 			// since there is no cache, the events fired should be exactly the same if
279 			// we re-retrieve the feed
280 			feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet/"));
281 			assertNotNull(feed);
282 			assertTrue(listener.polled);
283 			assertTrue(listener.retrieved);
284 			assertFalse(listener.unchanged);
285 			listener.reset();
286 		} catch (Exception e) {
287 			e.printStackTrace();
288 			fail(e.getMessage());
289 		}
290 	}
291 
292 	/***
293 	 * Test events fired when there is a cache in use
294 	 *
295 	 */
296 	public void testFetchEventsWithCache() {
297 		FeedFetcherCache feedInfoCache = new HashMapFeedInfoCache();
298 		FeedFetcher feedFetcher = getFeedFetcher(feedInfoCache);
299 		FetcherEventListenerImpl listener = new FetcherEventListenerImpl();
300 		feedFetcher.addFetcherEventListener(listener);
301 		try {
302 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet/"));
303 			assertNotNull(feed);
304 			assertTrue(listener.polled);
305 			assertTrue(listener.retrieved);
306 			assertFalse(listener.unchanged);
307 			listener.reset();
308 	
309 			// Since the feed is cached, the second request should not
310 			// actually retrieve the feed
311 			feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet/"));
312 			assertNotNull(feed);
313 			assertTrue(listener.polled);
314 			assertFalse(listener.retrieved);
315 			assertTrue(listener.unchanged);
316 			listener.reset();
317 	
318 			// now simulate getting the feed after it has changed
319 			feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet?refreshfeed=TRUE"));
320 			assertNotNull(feed);
321 			assertTrue(listener.polled);
322 			assertTrue(listener.retrieved);
323 			assertFalse(listener.unchanged);
324 			listener.reset();
325 		} catch (Exception e) {
326 			e.printStackTrace();
327 			fail(e.getMessage());
328 		}
329 	}
330 	
331 	/***
332 	 * Test handling of GZipped feed
333 	 *
334 	 */
335 	public void testGZippedFeed() {
336 	    FeedFetcher feedFetcher = getFeedFetcher();
337 		try {
338 			SyndFeed feed = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet?gzipfeed=TRUE"));
339 			assertNotNull(feed);
340 			assertEquals("atom_0.3.feed.title", feed.getTitle());
341 		} catch (Exception e) {
342 			e.printStackTrace();
343 			fail(e.getMessage());
344 		}	    
345 	}
346 	
347 	public void testDeltaEncoding() {
348 	    FeedFetcherCache feedInfoCache = new HashMapFeedInfoCache();
349 		FeedFetcher feedFetcher = getFeedFetcher(feedInfoCache);	    		
350 		try {
351 		    feedFetcher.setUsingDeltaEncoding(true);
352 		    
353 		    // first retrieval should just grab the default feed
354 			SyndFeed feed1 = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet?deltaencode=TRUE&refreshfeed=TRUE"));
355 			assertNotNull(feed1);
356 			assertEquals("atom_0.3.feed.title", feed1.getTitle());
357 			assertEquals(2, feed1.getEntries().size());
358 			SyndEntry entry1 = (SyndEntry) feed1.getEntries().get(0);
359 			assertEquals("atom_0.3.feed.entry[0].title", entry1.getTitle());
360 			
361 			// second retrieval should get only the new item
362 			/*
363 			 * This is breaking with Rome 0.5 ??
364 			 */ 
365 			SyndFeed feed2 = feedFetcher.retrieveFeed(new URL("http://localhost:8080/rome/FetcherTestServlet?deltaencode=TRUE&refreshfeed=TRUE"));					
366 			assertNotNull(feed2);
367 			assertEquals(FetcherTestServlet.DELTA_FEED_TITLE, feed2.getTitle());
368 			assertEquals(3, feed2.getEntries().size());
369 			entry1 = (SyndEntry) feed2.getEntries().get(0);
370 			assertEquals(FetcherTestServlet.DELTA_FEED_ENTRY_TITLE, entry1.getTitle());
371 			
372 			SyndEntry entry2 = (SyndEntry) feed2.getEntries().get(1);
373 			assertEquals("atom_0.3.feed.entry[0].title", entry2.getTitle());			
374 			
375 		} catch (Exception e) {
376 			e.printStackTrace();
377 			fail(e.getMessage());
378 		}	    	    
379 	}
380 		
381 	
382 }