KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openejb > webadmin > httpd > HttpResponseImpl


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "OpenEJB" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of The OpenEJB Group. For written permission,
18  * please contact dev@openejb.org.
19  *
20  * 4. Products derived from this Software may not be called "OpenEJB"
21  * nor may "OpenEJB" appear in their names without prior written
22  * permission of The OpenEJB Group. OpenEJB is a registered
23  * trademark of The OpenEJB Group.
24  *
25  * 5. Due credit should be given to the OpenEJB Project
26  * (http://www.openejb.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 2001 (C) The OpenEJB Group. All Rights Reserved.
42  *
43  * $Id: HttpResponseImpl.java 1921 2005-06-19 22:40:34Z jlaskowski $
44  */

45 package org.openejb.webadmin.httpd;
46
47 import java.io.ByteArrayOutputStream JavaDoc;
48 import java.io.DataOutput JavaDoc;
49 import java.io.DataOutputStream JavaDoc;
50 import java.io.IOException JavaDoc;
51 import java.io.InputStream JavaDoc;
52 import java.io.OutputStream JavaDoc;
53 import java.io.PrintWriter JavaDoc;
54 import java.net.URL JavaDoc;
55 import java.net.URLConnection JavaDoc;
56 import java.util.HashMap JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.Map JavaDoc;
59 import java.util.Properties JavaDoc;
60 import java.util.StringTokenizer JavaDoc;
61
62 import org.openejb.webadmin.HttpRequest;
63 import org.openejb.webadmin.HttpResponse;
64 import org.openejb.webadmin.HttpSession;
65 import org.openejb.util.JarUtils;
66
67 /** This class takes care of HTTP Responses. It sends data back to the browser.
68  * @author <a HREF="mailto:david.blevins@visi.com">David Blevins</a>
69  * @author <a HREF="mailto:tim_urberg@yahoo.com">Tim Urberg</a>
70  */

71 public class HttpResponseImpl implements HttpResponse {
72     
73     /** Response string */
74     private String JavaDoc responseString = "OK";
75
76     /** Code */
77     private int code = 200;
78     
79     /** Response headers */
80     private HashMap JavaDoc headers;
81     
82     /** Response body */
83     private byte[] body = new byte[0];
84     
85     /** the writer for the response */
86     private transient PrintWriter JavaDoc writer;
87     /** the raw body */
88     private transient ByteArrayOutputStream JavaDoc baos;
89     
90     /** the HTTP version */
91     public static final String JavaDoc HTTP_VERSION = "HTTP/1.1";
92     /** a line feed character */
93     public static final String JavaDoc CRLF = "\r\n";
94     /** a space character */
95     public static final String JavaDoc SP = " ";
96     /** a colon and space */
97     public static final String JavaDoc CSP = ": ";
98     /** the server to send data from */
99     public static String JavaDoc server;
100
101     private HttpRequestImpl request;
102     private URLConnection JavaDoc content;
103     
104     protected void setRequest(HttpRequestImpl request){
105         this.request = request;
106     }
107     
108     /** sets a header to be sent back to the browser
109      * @param name the name of the header
110      * @param value the value of the header
111      */

112     public void setHeader(String JavaDoc name, String JavaDoc value){
113         headers.put(name, value);
114     }
115
116     /** Gets a header based on the name passed in
117      * @param name The name of the header
118      * @return the value of the header
119      */

120     public String JavaDoc getHeader(String JavaDoc name){
121         return (String JavaDoc) headers.get(name);
122     }
123
124     /** Gets the PrintWriter to send data to the browser
125      * @return the PrintWriter to send data to the browser
126      */

127     public PrintWriter JavaDoc getPrintWriter(){
128         return writer;
129     }
130
131     /** gets the OutputStream to send data to the browser
132      * @return the OutputStream to send data to the browser
133      */

134     public OutputStream JavaDoc getOutputStream(){
135         return baos;
136     }
137
138     /** sets the HTTP response code to be sent to the browser. These codes are:
139      *
140      * OPTIONS = 0
141      * GET = 1
142      * HEAD = 2
143      * POST = 3
144      * PUT = 4
145      * DELETE = 5
146      * TRACE = 6
147      * CONNECT = 7
148      * UNSUPPORTED = 8
149      * @param code the code to be sent to the browser
150      */

151     public void setCode(int code){
152         this.code = code;
153     }
154
155     /** gets the HTTP response code
156      * @return the HTTP response code
157      */

158     public int getCode(){
159         return code;
160     }
161
162     /** sets the content type to be sent back to the browser
163      * @param type the type to be sent to the browser (i.e. "text/html")
164      */

165     public void setContentType(String JavaDoc type){
166         setHeader("Content-Type", type);
167     }
168
169     /** gets the content type that will be sent to the browser
170      * @return the content type (i.e. "text/html")
171      */

172     public String JavaDoc getContentType(){
173         return getHeader("Content-Type");
174     }
175
176     /** Sets the response string to be sent to the browser
177      * @param responseString the response string
178      */

179     public void setResponseString(String JavaDoc responseString){
180        this.responseString = responseString;
181     }
182
183     /** Sets the response string to be sent to the browser
184      * @return the response string
185      */

186     public String JavaDoc getResponseString(){
187         return responseString;
188     }
189     
190     /** resets the data to be sent to the browser */
191     public void reset(){
192         initBody();
193     }
194
195     /** resets the data to be sent to the browser with the response code and response
196      * string
197      * @param code the code to be sent to the browser
198      * @param responseString the response string to be sent to the browser
199      */

200     public void reset(int code, String JavaDoc responseString){
201         setCode(code);
202         setResponseString(responseString);
203         initBody();
204     }
205
206     /*------------------------------------------------------------*/
207     /* Methods for writing out a response */
208     /*------------------------------------------------------------*/
209     /** creates a new instance of HttpResponseImpl with default values */
210     protected HttpResponseImpl(){
211         this(200, "OK", "text/html");
212     }
213
214     /** Creates a new HttpResponseImpl with user provided parameters
215      * @param code the HTTP Response code, see <a HREF="http://www.ietf.org/rfc/rfc2616.txt">http://www.ietf.org/rfc/rfc2616.txt</a>
216      * for these codes
217      * @param responseString the response string to be sent back
218      * @param contentType the content type to be sent back
219      */

220     protected HttpResponseImpl(int code, String JavaDoc responseString, String JavaDoc contentType){
221         this.responseString = responseString;
222         this.headers = new HashMap JavaDoc();
223         this.code = code;
224         
225         // Default headers
226
setHeader("Server", getServerName());
227         setHeader("Connection","close");
228         setHeader("Content-Type",contentType);
229         
230         // create the body.
231
initBody();
232     }
233
234     /** Takes care of sending the response line, headers and body
235      *
236      * HTTP/1.1 200 OK
237      * Server: Netscape-Enterprise/3.6 SP3
238      * Date: Thu, 07 Jun 2001 17:30:42 GMT
239      * Content-Type: text/html
240      * Connection: close
241      * @param output the output to send the response to
242      * @throws IOException if an exception is thrown
243      */

244     protected void writeMessage(OutputStream JavaDoc output) throws IOException JavaDoc{
245         DataOutput JavaDoc out = new DataOutputStream JavaDoc(output);
246         DataOutput JavaDoc log = new DataOutputStream JavaDoc(System.out);
247         //System.out.println("\nRESPONSE");
248
closeMessage();
249         //writeResponseLine(log);
250
// writeHeaders(log);
251
// writeBody(log);
252
writeResponseLine(out);
253         writeHeaders(out);
254         writeBody(out);
255     }
256
257      /** initalizes the body */
258     private void initBody(){
259         baos = new ByteArrayOutputStream JavaDoc();
260         writer = new PrintWriter JavaDoc( baos );
261     }
262
263     /** Creates a string version of the response similar to:
264      *
265      * HTTP/1.1 200 OK
266      * @return the string value of this HttpResponseImpl
267      */

268     public String JavaDoc toString(){
269         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(40);
270
271         buf.append(HTTP_VERSION);
272         buf.append(SP);
273         buf.append(code+"");
274         buf.append(SP);
275         buf.append(responseString);
276
277         return buf.toString();
278     }
279
280     /** closes the message sent to the browser
281      * @throws IOException if an exception is thrown
282      */

283     private void closeMessage() throws IOException JavaDoc{
284         setContentLengthHeader();
285         setCookieHeader();
286     }
287
288
289     private void setContentLengthHeader() {
290         if (content == null){
291             writer.flush();
292             writer.close();
293             body = baos.toByteArray();
294             setHeader("Content-Length", body.length+"");
295         } else {
296             setHeader("Content-Length", content.getContentLength()+"");
297         }
298     }
299
300     private void setCookieHeader() {
301         if (request == null || request.getSession() == null) return;
302         
303         HttpSession session = request.getSession(false);
304
305         if (session == null) return;
306
307         StringBuffer JavaDoc cookie = new StringBuffer JavaDoc();
308         cookie.append(HttpRequestImpl.EJBSESSIONID);
309         cookie.append('=');
310         cookie.append(session.getId());
311         cookie.append("; Path=/");
312
313         headers.put(HttpRequest.HEADER_SET_COOKIE, cookie.toString());
314     }
315     
316     /** Writes a response line similar to this:
317      *
318      * HTTP/1.1 200 OK
319      *
320      * to the browser
321      * @param out the output stream to write the response line to
322      * @throws IOException if an exception is thrown
323      */

324     private void writeResponseLine(DataOutput JavaDoc out) throws IOException JavaDoc{
325         out.writeBytes(HTTP_VERSION);
326         out.writeBytes(SP);
327         out.writeBytes(code+"");
328         out.writeBytes(SP);
329         out.writeBytes(responseString);
330         out.writeBytes(CRLF);
331     }
332
333     /** writes the headers out to the browser
334      * @param out the output stream to be sent to the browser
335      * @throws IOException if an exception is thrown
336      */

337     private void writeHeaders(DataOutput JavaDoc out) throws IOException JavaDoc{
338         Iterator JavaDoc it = headers.entrySet().iterator();
339
340         while (it.hasNext()){
341             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
342             out.writeBytes(""+entry.getKey());
343             out.writeBytes(CSP);
344             out.writeBytes(""+entry.getValue());
345             out.writeBytes(CRLF);
346         }
347     }
348
349     /** writes the body out to the browser
350      * @param out the output stream that writes to the browser
351      * @throws IOException if an exception is thrown
352      */

353     private void writeBody(DataOutput JavaDoc out) throws IOException JavaDoc{
354         out.writeBytes(CRLF);
355         if (content == null){
356             out.write(body);
357         } else {
358             InputStream JavaDoc in = content.getInputStream();
359             byte buf[] = new byte[1024];
360             for(int i = 0; (i = in.read(buf)) != -1; out.write(buf, 0, i));
361         }
362     }
363
364     /** gets the name of the server being used
365      * @return the name of the server
366      */

367     public String JavaDoc getServerName(){
368         if (server == null) {
369             String JavaDoc version = "???";
370             String JavaDoc os = "(unknown os)";
371             
372             try {
373                 Properties JavaDoc versionInfo = new Properties JavaDoc();
374                 JarUtils.setHandlerSystemProperty();
375                 versionInfo.load( new URL JavaDoc( "resource:/openejb-version.properties" ).openConnection().getInputStream() );
376                 version = versionInfo.getProperty( "version" );
377                 os = System.getProperty("os.name")+"/"+System.getProperty("os.version")+" ("+System.getProperty("os.arch")+")";
378             } catch (java.io.IOException JavaDoc e) {
379             }
380             
381             server = "OpenEJB/" +version+ " "+os;
382         }
383         return server;
384     }
385     
386     
387     /** This could be improved at some day in the future
388      * to also include a stack trace of the exceptions
389      * @param message the error message to be sent
390      * @return the HttpResponseImpl that this error belongs to
391      */

392     protected static HttpResponseImpl createError(String JavaDoc message){
393         return createError(message, null);
394     }
395
396     /** creates an error with user defined variables
397      * @param message the message of the error
398      * @param t a Throwable to print a stack trace to
399      * @return the HttpResponseImpl that this error belongs to
400      */

401     protected static HttpResponseImpl createError(String JavaDoc message, Throwable JavaDoc t){
402         HttpResponseImpl res = new HttpResponseImpl(500, "Internal Server Error", "text/html");
403         java.io.PrintWriter JavaDoc body = res.getPrintWriter();
404
405         body.println("<html>");
406         body.println("<body>");
407         body.println("<h3>Internal Server Error</h3>");
408         body.println("<br><br>");
409
410         if (message != null) {
411             StringTokenizer JavaDoc msg = new StringTokenizer JavaDoc(message, "\n\r");
412
413             while (msg.hasMoreTokens()) {
414                 body.print( msg.nextToken() );
415                 body.println("<br>");
416             }
417         }
418
419         if (t != null) {
420             try{
421                 body.println("<br><br>");
422                 body.println("Stack Trace:<br>");
423                 ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
424                 PrintWriter JavaDoc writer = new PrintWriter JavaDoc( baos );
425                 t.printStackTrace(writer);
426                 writer.flush();
427                 writer.close();
428                 message = new String JavaDoc(baos.toByteArray());
429                 StringTokenizer JavaDoc msg = new StringTokenizer JavaDoc(message, "\n\r");
430                 
431                 while (msg.hasMoreTokens()) {
432                     body.print( msg.nextToken() );
433                     body.println("<br>");
434                 }
435             } catch (Exception JavaDoc e){
436             }
437         }
438
439         body.println("</body>");
440         body.println("</html>");
441
442         return res;
443     }
444
445     /** Creates a forbidden response to be sent to the browser using IP authentication
446      * @param ip the ip that is forbidden
447      * @return the HttpResponseImpl that this error belongs to
448      */

449     protected static HttpResponseImpl createForbidden(String JavaDoc ip){
450         HttpResponseImpl res = new HttpResponseImpl(403, "Forbidden", "text/html");
451         java.io.PrintWriter JavaDoc body = res.getPrintWriter();
452
453         body.println("<html>");
454         body.println("<body>");
455         body.println("<h3>Forbidden</h3>");
456         body.println("<br><br>");
457         // Add more text here
458
// IP not allowed, etc.
459
body.println("IP address: " + ip + " is not registered on this server, please contact your system administrator.");
460         body.println("</body>");
461         body.println("</html>");
462
463         return res;
464     }
465
466     /** writes this object out to a file
467      * @param out the ObjectOutputStream to write to
468      * @throws IOException if an exception is thrown
469      */

470     private void writeObject(java.io.ObjectOutputStream JavaDoc out) throws IOException JavaDoc{
471         /** Response string */
472         out.writeObject( responseString );
473
474         /** Code */
475         out.writeInt( code );
476
477         /** Response headers */
478         out.writeObject( headers );
479
480         /** Response body */
481         writer.flush();
482         body = baos.toByteArray();
483         //System.out.println("[] body "+body.length );
484
out.writeObject( body );
485     }
486     
487     /** Reads in a serilized HttpResponseImpl object from a file
488      * @param in the input to read the object from
489      * @throws IOException if an exception is thrown
490      * @throws ClassNotFoundException if an exception is thrown
491      */

492     private void readObject(java.io.ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc{
493         /** Response string */
494         this.responseString = (String JavaDoc)in.readObject();
495
496         /** Code */
497         this.code = in.readInt();
498
499         /** Response headers */
500         this.headers = (HashMap JavaDoc) in.readObject();
501
502         /** Response body */
503         body = (byte[]) in.readObject();
504         //System.out.println("[] body "+body.length );
505
baos = new ByteArrayOutputStream JavaDoc();
506         baos.write( body );
507         writer = new PrintWriter JavaDoc( baos );
508
509     }
510     /**
511      * @param content The content to set.
512      */

513     public void setContent(URLConnection JavaDoc content) {
514         this.content = content;
515     }
516
517 }
Popular Tags