Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/enhydra/httpServerTest/server/application/presentation/BasicTest.java


1   /*
2    * Enhydra Java Application Server Project
3    * 
4    * The contents of this file are subject to the Enhydra Public License
5    * Version 1.1 (the "License"); you may not use this file except in
6    * compliance with the License. You may obtain a copy of the License on
7    * the Enhydra web site ( http://www.enhydra.org/ ).
8    * 
9    * Software distributed under the License is distributed on an "AS IS"
10   * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 
11   * the License for the specific terms governing rights and limitations
12   * under the License.
13   * 
14   * The Initial Developer of the Enhydra Application Server is Lutris
15   * Technologies, Inc. The Enhydra Application Server and portions created
16   * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17   * All Rights Reserved.
18   * 
19   * Contributor(s):
20   * 
21   * $Id: BasicTest.java,v 1.3.2.1.2.1 2000/10/19 17:59:08 jasona Exp $
22   */
23  
24  package org.enhydra.httpServerTest.server.application.presentation;
25  
26  import org.enhydra.httpServerTest.server.application.BasicTestApp;
27  import org.enhydra.httpServerTest.common.HttpResponseObject;
28  import org.enhydra.httpServerTest.common.HttpServerTestUtils;
29  import org.enhydra.httpServerTest.server.common.FileUploadMangler;
30  
31  import com.lutris.appserver.server.httpPresentation.HttpPresentationException;
32  
33  import com.lutris.appserver.server.httpPresentation.HttpPresentation;
34  import com.lutris.appserver.server.httpPresentation.HttpPresentationRequest;
35  import com.lutris.appserver.server.httpPresentation.HttpPresentationComms;
36  import com.lutris.appserver.server.httpPresentation.HttpPresentationException;
37  import com.lutris.appserver.server.session.SessionException;
38  import com.lutris.appserver.server.session.SessionManager;
39  import com.lutris.appserver.server.session.Session;
40  
41  import HTTPClient.NVPair;
42  import HTTPClient.Codecs;
43  
44  import java.util.Random;
45  import java.util.Enumeration;
46  import java.util.StringTokenizer;
47  import java.net.URLEncoder;
48  import java.io.DataInputStream;
49  import java.io.File;
50  
51  import javax.servlet.http.Cookie;
52  
53  /**
54   * This class is the generic server side test presentation object that client
55   * side test threads talk to.  This class respondes to every request comming in
56   * by constructing an HttpResponseObject and returning it in the response as
57   * an XML stream.  The response object returned contains information about
58   * all data received via the request.  This presentation object properly
59   * handles GET and POST method request and multi-part mime encodings.
60   *
61   * @see org.enhydra.httpServerTest.common.HttpResponseObject
62   *
63   * @author Mike Ward
64   **/
65  public class BasicTest
66      implements HttpPresentation {
67  
68      /**
69       * This holds the directory, unique to this request, that any uploaded
70       * files are stored.
71       **/
72      private File fileCacheDir = null;
73  
74      /**
75       * The run method for this presentation object.  This method runs through
76       * the remainder of the functions held in this class to initialize the
77       * response object based on information pulled from the request.  Once
78       * the response object is populated, this method calls toString() on it
79       * and returns the generated XML structure to the client.
80       *
81       * @param comms
82       *        The comms objects for this request.  All request, response,
83       *        and session information are available from this object.
84       **/
85      public void run(HttpPresentationComms comms) 
86          throws HttpPresentationException {
87  
88    HttpPresentationRequest request = comms.request;
89    Session session = comms.session;
90  
91    HttpResponseObject httpResponseObject = new HttpResponseObject();
92    httpResponseObject.HTTP_RESPONSE_OBJECT_DTD = 
93        BasicTestApp.httpResponseObjectDTD;
94  
95    populateRequestInfo(httpResponseObject, request);
96    if (request.getMethod().equals(HttpServerTestUtils.GET_REQUEST_TAG) ||
97        request.getContentType().equals(HttpServerTestUtils.POST_URL_ENCODED_CONTENT_TYPE)) {
98        // Standard request, url-encoded
99        populateCgiArgsFromGet(httpResponseObject, request);
100     } else {
101       // Multi-part mime request, file uploads expected
102         populateCgiArgsFromPost(httpResponseObject, request);
103         populateFileUploadFromPost(httpResponseObject);
104   }
105   populateCgiParams(httpResponseObject, request);
106   populateHeaders(httpResponseObject, request);
107   populateCookies(httpResponseObject, request);
108   populateSessionInfo(httpResponseObject, comms);
109   
110         comms.response.writeHTML(httpResponseObject.toString());
111     }
112 
113     /**
114      * This function runs through the HttpPresentationRequest API and 
115      * populates the response object with retrieved information.  The 
116      * request API used here is a sub-set of the HttpPresentationRequest
117      * API that is common with a stardard servlet request object.  Each
118      * of the requst method calls are individually wrapped in a try/catch
119      * block so that an error thrown from one will not cause the remaining
120      * calls to be skipped.
121      *
122      * @param httpResponseObject
123      *        The response object to populate with request data.
124      * @param request
125      *        The HttpPresentationRequest object to pull data from.
126      **/
127     protected void populateRequestInfo(HttpResponseObject httpResponseObject,
128                HttpPresentationRequest request) {
129   try {
130       httpResponseObject.authType = request.getAuthType();
131   } catch (HttpPresentationException e) {
132   }
133 
134   try {
135       httpResponseObject.method = request.getMethod();
136   } catch (HttpPresentationException e) {
137   }
138 
139   try {
140       httpResponseObject.pathInfo = request.getPathInfo();
141   } catch (HttpPresentationException e) {
142   }
143   
144   try {
145       httpResponseObject.pathTranslated = request.getPathTranslated();
146   } catch (Exception e) {
147   }
148 
149   try {
150       String queryString = request.getQueryString();
151       if (queryString != null) {
152     httpResponseObject.queryString = 
153         URLEncoder.encode(queryString);
154       } else {
155     httpResponseObject.queryString = null;
156       }
157   } catch (HttpPresentationException e) {
158   }
159 
160   try {
161       httpResponseObject.remoteUser = request.getRemoteUser();
162   } catch (HttpPresentationException e) {
163   }
164 
165   try {
166       httpResponseObject.requestURI = request.getRequestURI();
167   } catch (HttpPresentationException e) {
168   }
169   
170   try {
171       httpResponseObject.servletPath = request.getApplicationPath();
172   } catch (HttpPresentationException e) {
173   }
174     }
175 
176     /**
177      * This function will populate the response object with all CGI parameters
178      * submitted with the request.
179      *
180      * @param httpResponseObject
181      *        The response object to populate with request data.
182      * @param request
183      *        The HttpPresentationRequest object to pull data from.
184      **/
185     protected void populateCgiParams(HttpResponseObject httpResponseObject,
186              HttpPresentationRequest request) {
187   StringTokenizer paramTokens = null;
188   try {
189       paramTokens = 
190     new StringTokenizer(request.getPathInfo(), ";", false);
191   } catch (HttpPresentationException e) {
192       return;
193   }
194 
195   while (paramTokens.hasMoreTokens()) {
196       String currentToken = paramTokens.nextToken();
197       StringTokenizer currentNameValuePair = 
198     new StringTokenizer(currentToken, "=", false);
199       if (currentNameValuePair.countTokens() == 2) {
200     String paramName = currentNameValuePair.nextToken();
201     String paramValue = currentNameValuePair.nextToken();
202     httpResponseObject.cgiParams.put(paramName, paramValue);
203       }
204   }
205     }
206 
207     /**
208      * This function will populate the response object with all CGI arguments
209      * submitted with the request.  This method assumes a stardard GET or
210      * url-encoded POST request (ie. no multi-part mime).
211      *
212      * @param httpResponseObject
213      *        The response object to populate with request data.
214      * @param request
215      *        The HttpPresentationRequest object to pull data from.
216      **/
217     protected void populateCgiArgsFromGet(HttpResponseObject httpResponseObject,
218             HttpPresentationRequest request) {
219   try {
220       Enumeration cgiArgs = request.getParameterNames();
221       while (cgiArgs.hasMoreElements()) {
222     String cgiArgName = (String)cgiArgs.nextElement();
223     String cgiArgValue = 
224         request.getParameter(cgiArgName);
225     httpResponseObject.cgiArgs.put(cgiArgName, cgiArgValue);
226       }
227   } catch (HttpPresentationException e) {      
228   }
229     }
230 
231     /**
232      * This function will populate the response object with all http headers
233      * submitted with the request.  This function will not include any
234      * 'default' headers applied by HTTPConnection.
235      *
236      * @see HTTPClient.HTTPConnection
237      * @see org.enhydra.httpServerTest.common.HttpServerTestUtils
238      *
239      * @param httpResponseObject
240      *        The response object to populate with request data.
241      * @param request
242      *        The HttpPresentationRequest object to pull data from.
243      **/
244     protected void populateHeaders(HttpResponseObject httpResponseObject,
245            HttpPresentationRequest request) {
246   try {
247       Enumeration headers = request.getHeaderNames();
248       while (headers.hasMoreElements()) {
249     String headerName = (String)headers.nextElement();
250     if (!HttpServerTestUtils.isDefaultHeader(headerName)) {
251         String headerValue = 
252       request.getHeader(headerName);
253         httpResponseObject.headers.put(headerName, headerValue);
254     }
255       }
256   } catch (HttpPresentationException e) {      
257   }
258 
259     }
260 
261     /**
262      * This function will populate the response object with all http cookies
263      * submitted with the request.
264      *
265      * @param httpResponseObject
266      *        The response object to populate with request data.
267      * @param request
268      *        The HttpPresentationRequest object to pull data from.
269      **/
270     protected void populateCookies(HttpResponseObject httpResponseObject,
271            HttpPresentationRequest request) {
272   try {
273       Cookie[] cookies = request.getCookies();
274       for (int i = 0; i < cookies.length; i++) {
275     httpResponseObject.cookies.put(cookies[i].getName(),
276                  cookies[i].getValue());
277       }
278   } catch (HttpPresentationException e) {
279   }
280     }
281 
282     /**
283      * This function will populate the response object with all CGI arguments
284      * submitted with the request.  This method assumes a multi-part mime
285      * encoding from a POST request.
286      *
287      * @see HTTPClient.Codecs
288      *
289      * @param httpResponseObject
290      *        The response object to populate with request data.
291      * @param request
292      *        The HttpPresentationRequest object to pull data from.
293      **/
294     protected void populateCgiArgsFromPost(HttpResponseObject httpResponseObject,
295             HttpPresentationRequest request) {
296   try {
297       byte[] body = new byte[request.getContentLength()];
298       new DataInputStream(request.getInputStream()).readFully(body);
299       String contentTypeAndBoundary = request.getContentType();
300   
301       initFileCacheDir();
302 
303       NVPair[] cgiArgs = 
304     Codecs.mpFormDataDecode(body, 
305           contentTypeAndBoundary,
306           fileCacheDir.toString(),
307           new FileUploadMangler());
308       for (int i = 0; i < cgiArgs.length; i++) {
309     if (!cgiArgs[i].getName().startsWith(HttpServerTestUtils.POST_FILE_UPLOAD_PREFIX)) {
310         httpResponseObject.cgiArgs.put(cgiArgs[i].getName(),
311                cgiArgs[i].getValue());
312     }
313       }
314   } catch (Exception e) {
315   }
316     }
317 
318     /**
319      * This function will continually loop until a unique temporary sub-
320      * directory is found.  This is accomplished by using the static data 
321      * members and methods held in the BasicTestApp class.  Once a unique
322      * path is found, the directories are created and the global fileCacheDir
323      * is initialized.
324      **/
325     protected void initFileCacheDir() {
326 
327   String fileCacheDirString = BasicTestApp.temporaryBaseDir + 
328       BasicTestApp.getFileCacheDirCnt() + File.separator;
329   fileCacheDir = new File(fileCacheDirString);
330       
331   while (true) {
332       if (fileCacheDir.exists()) {
333     fileCacheDirString = BasicTestApp.temporaryBaseDir + 
334         BasicTestApp.getFileCacheDirCnt() + File.separator;
335     fileCacheDir = new File(fileCacheDirString);
336       } else {
337     break;
338       } 
339   }
340   fileCacheDir.mkdirs();
341     }
342 
343     /**
344      * This function will loop through all files found under the unique 
345      * directory created by initFileCacheDir() and compute an MD5 hashkey
346      * for each individual file.  The response object is then populated with
347      * each hashkey.
348      *
349      * @param httpResponseObject
350      *        The response object to populate with file upload data.
351      **/
352     protected void populateFileUploadFromPost(HttpResponseObject httpResponseObject) {
353   String[] uploadedFiles = fileCacheDir.list();
354   for (int i = 0; i < uploadedFiles.length; i++) {
355       String currentFile = fileCacheDir.toString() + 
356     File.separator + uploadedFiles[i];
357       String hashKey = null;
358       try {
359     hashKey = 
360         HttpServerTestUtils.calculateFileHash(currentFile);
361       } catch (Exception e) {
362       }
363       if (!(hashKey == null)) {
364     httpResponseObject.md5HashKey.addElement(hashKey);
365       }
366   }
367   cleanupFiles();
368     }
369 
370     /**
371      * This function is called after all file MD5 hashkeys have been computed.
372      * This function will recursively delete all uploaded files and temporary
373      * directories created while caching uploaded files.
374      **/
375     public void cleanupFiles() {
376   String[] uploadedFiles = fileCacheDir.list();
377   for (int i = 0; i < uploadedFiles.length; i++) {
378       String currentFile = fileCacheDir.toString() + 
379     File.separator + uploadedFiles[i];
380       File tmpFile = new File(currentFile);
381       tmpFile.delete();
382   }
383   fileCacheDir.delete();
384     }
385 
386     /**
387      * This function will populate the response object with all session
388      * information submitted with the request.
389      *
390      * @param httpResponseObject
391      *        The response object to populate with request data.
392      * @param request
393      *        The HttpPresentationRequest object to pull data from.
394      **/
395     protected void populateSessionInfo(HttpResponseObject httpResponseObject,
396                HttpPresentationComms comms) {
397       
398   try {
399       httpResponseObject.sessionIdFromCookie = 
400     comms.request.isRequestedSessionIdFromCookie();
401       httpResponseObject.sessionIdFromURL = 
402     comms.request.isRequestedSessionIdFromUrl();
403   } catch (HttpPresentationException e) {
404   }
405 
406   if (httpResponseObject.sessionIdFromCookie ||
407       httpResponseObject.sessionIdFromURL) {
408       httpResponseObject.sessionIdInvalid = false;
409       httpResponseObject.session = comms.session.getSessionKey();
410   } else {
411       httpResponseObject.sessionIdInvalid = true;
412       httpResponseObject.session = HttpResponseObject.DEFAULT_SESSION;
413   }
414     }
415 }