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.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.io.OutputStream;
24  import java.io.OutputStreamWriter;
25  import java.text.DateFormat;
26  import java.text.ParseException;
27  import java.text.SimpleDateFormat;
28  import java.util.ArrayList;
29  import java.util.List;
30  import java.util.zip.GZIPOutputStream;
31  
32  import javax.servlet.ServletException;
33  import javax.servlet.http.HttpServletRequest;
34  import javax.servlet.http.HttpServletResponse;
35  
36  import com.sun.syndication.feed.synd.SyndContent;
37  import com.sun.syndication.feed.synd.SyndContentImpl;
38  import com.sun.syndication.feed.synd.SyndEntry;
39  import com.sun.syndication.feed.synd.SyndEntryImpl;
40  import com.sun.syndication.feed.synd.SyndFeed;
41  import com.sun.syndication.feed.synd.SyndFeedImpl;
42  import com.sun.syndication.io.FeedException;
43  import com.sun.syndication.io.SyndFeedOutput;
44  
45  
46  public class FetcherTestServlet extends javax.servlet.http.HttpServlet {
47      public static final String ETAG_1 = "ETAG-1";
48      public static final String ETAG_2 = "ETAG-2";
49      
50      public static final String DELTA_FEED_TITLE = "Delta Encoded Feed";
51      public static final String DELTA_FEED_ENTRY_TITLE = "Delta Encoded Feed Entry";
52      
53  	/***
54  	 * @throws IOException
55  	 * @throws 
56  	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
57  	 */
58  	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
59  		
60  		if ("TRUE".equalsIgnoreCase(request.getParameter("redirect"))) {
61  			//	testing redirection support			
62  			response.sendRedirect(request.getRequestURI());
63  			return;
64  		} else if (request.getParameter("error") != null) {
65  			//response.sendError(HttpServletResponse.SC_NOT_FOUND);	
66  			int errorToThrow = Integer.parseInt(request.getParameter("error"));
67  			response.sendError(errorToThrow);
68  			return;
69  		} else {
70  			
71  			// We manually set the date headers using strings
72  			// instead of the get/setDateHeader methods because
73  			// those methods return longs, which has too much
74  			// precision for the real date headers
75  			// this is just a random date
76  			String lastModifiedDate = "Thu, 08 Jan 2009 23:06:39 GMT"; 
77  			String eTag = ETAG_1;
78  			
79  			if ("TRUE".equalsIgnoreCase(request.getParameter("refreshfeed"))) {
80  				lastModifiedDate = "Fri, 09 Jan 2009 12:06:39 GMT";
81  				eTag = ETAG_2; 
82  			}
83  			
84  			boolean serveFeed = checkModified(request, lastModifiedDate, eTag) || ("TRUE".equalsIgnoreCase(request.getParameter("deltaencode")));
85  			boolean gzip = "TRUE".equalsIgnoreCase(request.getParameter("gzipfeed"));
86  			
87  			if (serveFeed) {
88  			    String aimHeader = request.getHeader("A-IM");
89  			    boolean serveDeltaEncodedFeed = ((aimHeader != null) && (aimHeader.indexOf("feed") >=0) && "TRUE".equalsIgnoreCase(request.getParameter("deltaencode")));
90  			    if (serveDeltaEncodedFeed) {
91  			        try {
92                          sendDeltaEncodedData(response, lastModifiedDate, request.getHeader("If-None-Match"), eTag, gzip);
93                      } catch (FeedException e) {
94                          throw new ServletException(e);
95                      }
96  			    } else {
97  			        sendFeedData(response, lastModifiedDate, eTag, gzip);
98  			    }
99  				return;					
100 			} else {
101 				response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
102 				return;							
103 			}
104 		}							
105 	}
106 
107 
108 
109     private boolean checkModified(HttpServletRequest request, String lastModifiedDate, String eTag) {
110 		
111 		String requestedETag = request.getHeader("If-None-Match");			
112 		String requestedLastModified = request.getHeader("If-Modified-Since");
113 		boolean modified = true;
114 		boolean mustServer = false;			
115 		if (requestedETag != null) {
116 			if (eTag.equals(requestedETag)) {
117 				modified = false;
118 			} else {
119 				modified = true;
120 				mustServer = true;				
121 			}
122 		}
123 		if (requestedLastModified != null) {
124 			if (lastModifiedDate.equals(requestedLastModified)) {
125 				modified = false;
126 			} else {
127 				modified = true;
128 				mustServer = true;					
129 			}
130 		}
131 		boolean serveFeed = (modified || mustServer);
132 		return serveFeed;
133 	}
134 
135 	/***
136      * @param request
137      * @param lastModifiedDate
138      * @param tag
139      * @param gzip
140 	 * @throws IOException
141 	 * @throws FeedException
142      */
143     private void sendDeltaEncodedData(HttpServletResponse response, String lastModifiedDate, String requestedETag, String responseETag, boolean gzip) throws IOException, FeedException {
144         if (ETAG_1.equals(requestedETag) || ETAG_2.equals(requestedETag)) {               
145 		    OutputStream out = null;
146 		    if (gzip) {
147 		        response.setHeader("Content-Encoding", "gzip");
148 		        out = new GZIPOutputStream(response.getOutputStream());	        
149 		    } else {
150 		        out = response.getOutputStream();	        
151 		    }
152 		    
153 			response.setContentType("text/xml");
154 			response.setStatus(226);
155 			if (gzip) {
156 			    response.setHeader("IM", "feed, gzip");
157 			} else {
158 			    response.setHeader("IM", "feed");
159 			}
160 			
161 			if (responseETag != null) {
162 				response.setHeader("ETag", responseETag);
163 			}		
164 			if (lastModifiedDate != null) {
165 				response.setHeader("Last-Modified", lastModifiedDate);
166 			}		    
167 		    
168 	        SyndFeed feed = new SyndFeedImpl();
169 	        feed.setFeedType("atom_0.3");
170 	
171 	        feed.setTitle(DELTA_FEED_TITLE);        
172 	        feed.setLink("http://rome.dev.java.net");
173 	        feed.setDescription("This tests using rfc3229 delta encoding.");
174 	
175 	        List entries = new ArrayList();
176 	        SyndEntry entry;
177 	        SyndContent description;
178 	
179 	        entry = new SyndEntryImpl();
180 	        entry.setTitle(DELTA_FEED_ENTRY_TITLE);
181 	        entry.setLink("http://bobwyman.pubsub.com/main/2004/09/using_rfc3229_w.html");
182 	        try {
183 	            DateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd");
184 	            entry.setPublishedDate(dateParser.parse("2004-11-25"));
185 	        }
186 	        catch (ParseException ex) {
187 	            // 
188 	        }
189 	        description = new SyndContentImpl();
190 	        description.setType("text/plain");
191 	        description.setValue("Test for RFC3229 Delta Encoding");	        
192 	        entry.setDescription(description);	        
193 	        entries.add(entry);
194 	        
195 	        feed.setEntries(entries);
196 	        
197 	        SyndFeedOutput output = new SyndFeedOutput();        
198 	        output.output(feed, new OutputStreamWriter(out));
199         } else {
200             sendFeedData(response, lastModifiedDate, responseETag, gzip);
201         }
202     }    
203     
204 	private void sendFeedData(HttpServletResponse response, String lastModifiedDate, String eTag, boolean gzip) throws IOException {
205 	    OutputStream out = null;
206 	    if (gzip) {
207 	        response.setHeader("Content-Encoding", "gzip");
208 	        out = new GZIPOutputStream(response.getOutputStream());	        
209 	    } else {
210 	        out = response.getOutputStream();
211 	    }	    
212 	    
213 		response.setContentType("text/xml");
214 		if (eTag != null) {
215 			response.setHeader("ETag", eTag);
216 		}		
217 		if (lastModifiedDate != null) {
218 			response.setHeader("Last-Modified", lastModifiedDate);
219 		}
220 		
221 		InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("/atom_0.3.xml");
222 		if (inputStream == null) {
223 		    inputStream = this.getClass().getResourceAsStream("/atom_0.3.xml");
224 		}
225 		
226 		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
227 		try {
228 			String line;
229 			while ((line = reader.readLine()) != null) {									
230 			    out.write(line.getBytes());
231 				line = null;
232 			}
233 		} finally {
234 			if (reader != null) {
235 			    reader.close();
236 			}
237 		}
238 		
239 		out.close();
240 	}
241 }