1   /*
2    * Created on 26.09.2004
3    *
4    */
5   package org.w3c.tidy.servlet;
6   
7   import java.io.ByteArrayOutputStream;
8   import java.io.File;
9   import java.io.InputStream;
10  import java.io.IOException;
11  import java.util.Hashtable;
12  import java.net.MalformedURLException;
13  import java.net.URL;
14  
15  import org.apache.commons.lang.StringUtils;
16  import org.apache.commons.lang.SystemUtils;
17  import org.apache.commons.logging.Log;
18  import org.apache.commons.logging.LogFactory;
19  import org.w3c.tidy.servlet.util.HTMLEncode;
20  import org.xml.sax.SAXException;
21  
22  import com.meterware.httpunit.GetMethodWebRequest;
23  import com.meterware.httpunit.WebLink;
24  import com.meterware.httpunit.WebRequest;
25  import com.meterware.httpunit.WebResponse;
26  import com.meterware.servletunit.ServletTestCase;
27  
28  import com.meterware.servletunit.ServletRunner;
29  
30  
31  /***
32   * Base TestCase class for tests.
33   * @author Vlad Skarzhevskyy <a href="mailto:skarzhevskyy@gmail.com">skarzhevskyy@gmail.com </a>
34   * @version $Revision: 1.6 $ ($Author: fgiust $)
35   */
36  public abstract class TidyServletCase extends ServletTestCase
37  {
38  
39      /***
40       * Context mapped to the test application.
41       */
42      public static final String CONTEXT = "/context";
43  
44      /***
45       * HttpUnit ServletRunner.
46       */
47      protected ServletRunner runner;
48  
49      /***
50       * logger.
51       */
52      protected final Log log = LogFactory.getLog(this.getClass());
53  
54      /***
55       * Instantiates a new test case.
56       * @param name test name
57       */
58      public TidyServletCase(String name)
59      {
60          super(name);
61      }
62  
63      /***
64       * Returns the tested jsp name.
65       * @return jsp name
66       */
67      public String getJspName()
68      {
69          return "servlet/" + this.getClass().getName() + ".jsp";
70      }
71  
72      /***
73       * @see junit.framework.TestCase#getName()
74       */
75      public String getName()
76      {
77          return getClass().getName() + "." + super.getName();
78      }
79  
80      /***
81       * Get the Response to analize using default JSP name.
82       * @throws Exception any axception thrown during test.
83       */
84  
85      public WebResponse getResponse() throws Exception
86      {
87          return getJSPResponse(getJspName());
88      }
89  
90      public WebResponse getResponseQuery(String[] args) throws Exception
91      {
92          return getJSPResponse(HTMLEncode.encodeQuery(getJspName(), args));
93      }
94  
95      /***
96       * Get the Response to analize using Given JSP name.
97       * @throws Exception any axception thrown during test.
98       */
99  
100     public WebResponse getJSPResponse(String jspName) throws Exception
101     {
102         cleanupTempFile(jspName);
103         return getResponse(CONTEXT + "/" + jspName);
104     }
105 
106     /***
107      * Get the Response to analize.
108      * @throws Exception any axception thrown during test.
109      */
110     public WebResponse getResponse(String url) throws Exception
111     {
112         String urlString = "http://localhost" + url;
113         if (log.isDebugEnabled())
114         {
115             log.debug("REQUEST: " + urlString);
116         }
117         WebRequest request = new GetMethodWebRequest(urlString);
118 
119         WebResponse response;
120         try
121         {
122             response = runner.getResponse(request);
123         }
124         catch (MalformedURLException e)
125         {
126             log.debug("MalformedURL ", e);
127             throw e;
128         }
129         catch (IOException e)
130         {
131             log.debug("IO Error ", e);
132             throw e;
133         }
134         catch (SAXException e)
135         {
136             log.debug("Parsing Error ", e);
137             throw e;
138         }
139         catch (Exception e)
140         {
141             log.debug("Request Error ", e);
142             throw e;
143         }
144 
145         if (log.isDebugEnabled())
146         {
147             if (response.getContentType().startsWith("image"))
148             {
149                 log.debug("RESPONSE: is Image Len:" + response.getContentLength());
150             }
151             else
152             {
153                 log.debug("RESPONSE: [" + response.getText() + "]");
154                 /*
155                  * String elemetns[] = response.getElementNames(); for(int i =0; i < elemetns.length; i ++) {
156                  * log.debug("RESPONSE element [" + i + "]=" + elemetns[i]); }
157                  */
158             }
159         }
160         return response;
161     }
162 
163     /***
164      * @see junit.framework.TestCase#setUp()
165      */
166     protected void setUp() throws Exception
167     {
168         // need to pass a web.xml file to setup servletunit working directory
169         final String web_xml = "WEB-INF/web.xml";
170         ClassLoader classLoader = getClass().getClassLoader();
171         URL webXmlUrl = classLoader.getResource(web_xml);
172         if (webXmlUrl == null)
173         {
174             throw new Exception(web_xml + " not in class path");
175         }
176         File webXml = new File(webXmlUrl.getFile());
177         log.debug("web.xml:" + webXml.getAbsolutePath());
178 
179         cleanupTempFile(getJspName());
180 
181         // start servletRunner
182         runner = new ServletRunner(webXml, CONTEXT);
183 
184         Hashtable initParameters = new Hashtable();
185         setServletInitParameters(initParameters);
186         String servletURI = "/JTidy";
187         runner.registerServlet(servletURI, TidyServlet.class.getName(), initParameters);
188         // initialize it - load-on-startup
189         getResponse(CONTEXT + servletURI + "?initialize");
190 
191         // register the filter servlet
192         Hashtable filterInitParameters = new Hashtable();
193         setFilterInitParameters(filterInitParameters);
194         runner.registerServlet(
195             "*" + MockFilterSupport.FILTERED_EXTENSION,
196             MockFilterSupport.class.getName(),
197             filterInitParameters);
198 
199         log.debug("ServletRunner setup OK");
200 
201         super.setUp();
202     }
203 
204     /***
205      * Define servlet init Parameters in child class
206      * @param initParameters
207      */
208     public void setServletInitParameters(Hashtable initParameters)
209     {
210         // initParameters.put("properties.filename", "JTidyServletTest.properties");
211     }
212 
213     /***
214      * Define filter init Parameters in child class
215      * @param initParameters
216      */
217     public void setFilterInitParameters(Hashtable initParameters)
218     {
219         // initParameters.put("properties.filename", "JTidyServletTest.properties");
220     }
221 
222     /***
223      * @see junit.framework.TestCase#tearDown()
224      */
225     protected void tearDown() throws Exception
226     {
227         // shutdown servlet engine
228         runner.shutDown();
229         super.tearDown();
230     }
231 
232     public void validateReport(WebResponse reportResponse) throws Exception
233     {
234         // assertEquals("Messages exists exists", 1, reportResponse.getElementsWithName("JTidyMessagesTable").length);
235         // assertEquals("Source code exists", 1, reportResponse.getElementsWithName("JTidyOriginalSource").length);
236         assertTrue("Messages exists exists", reportResponse.getText().indexOf("JTidyMessagesTable") > 0);
237         assertTrue("Source code exists", reportResponse.getText().indexOf("JTidyOriginalSource") > 0);
238     }
239 
240     public void validateBinaryContext(WebResponse response) throws Exception
241     {
242         assertFalse("Type is HTML", "text/html".equals(response.getContentType()));
243         InputStream in = response.getInputStream();
244         ByteArrayOutputStream data = new ByteArrayOutputStream();
245         // write in to data;
246         final int BUFFER_SIZE = 2048;
247         byte[] buffer = new byte[BUFFER_SIZE];
248         int r = 0;
249         while ((r = in.read(buffer)) != -1)
250         {
251             data.write(buffer, 0, r);
252         }
253         assertEquals("Content Length", data.size(), response.getContentLength());
254 
255     }
256 
257     public WebResponse getReportResponse(WebResponse response) throws Exception
258     {
259         WebLink servletLink = response.getLinkWithName("JTidyValidationImageLink");
260 
261         return getResponse(servletLink.getURLString());
262     }
263 
264     /***
265      * Clean up temporary files from a previous test.
266      * @param jspName jsp name, with full path
267      */
268     private void cleanupTempFile(String uri)
269     {
270         String jspName = StringUtils.replace(uri, MockFilterSupport.FILTERED_EXTENSION, "");
271 
272         URL resourceUrl = getClass().getResource("/" + jspName);
273         if (resourceUrl != null && SystemUtils.JAVA_IO_TMPDIR != null)
274         {
275             File jspFile = new File(resourceUrl.getFile());
276             long jspModified = jspFile.lastModified();
277 
278             String path = SystemUtils.JAVA_IO_TMPDIR + StringUtils.replace(jspName, ".", "$");
279 
280             File tempFile = new File(path + ".java");
281             // log.debug("JSP file " + jspFile.getPath() + " " + (new java.util.Date(jspFile.lastModified())));
282             // log.debug("Java file " + tempFile.getPath() + " "+ (new java.util.Date(tempFile.lastModified())));
283 
284             // delete file only if jsp has been modified
285             if (tempFile.exists())
286             {
287                 if (tempFile.lastModified() < jspModified)
288                 {
289                     if (log.isDebugEnabled())
290                     {
291                         log.debug("Deleting temporary file " + tempFile.getPath());
292                     }
293                     tempFile.delete();
294                 }
295             }
296 
297             tempFile = new File(path + ".class");
298             if (tempFile.exists() && tempFile.lastModified() < jspModified)
299             {
300                 if (log.isDebugEnabled())
301                 {
302                     log.debug("Deleting temporary file " + tempFile.getPath());
303                 }
304                 tempFile.delete();
305             }
306         }
307     }
308 }