KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > core > helper > servlet > DeferredResponseWrapper


1 /*
2  * Copyright (C) 2003 Christian Cryder [christianc@granitepeaks.com]
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * $Id: DeferredResponseWrapper.java,v 1.4 2004/02/01 05:16:28 christianc Exp $
19  */

20 package org.enhydra.barracuda.core.helper.servlet;
21
22 import java.io.*;
23 import java.text.*;
24 import java.security.*;
25 import java.util.*;
26 import javax.servlet.*;
27 import javax.servlet.http.*;
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29
30 import org.apache.log4j.Logger;
31
32 import org.enhydra.barracuda.core.event.*;
33 import org.enhydra.barracuda.core.helper.state.*;
34 import org.enhydra.barracuda.plankton.data.*;
35
36 //csc_010404_1 - created
37
/**
38  * <p>This class acts as a thin wrapper around a ServletResponse. By using this wrapper,
39  * the response is actually "absorbed" or "deferred", so that it can be manually extracted
40  * later.
41  */

42 public class DeferredResponseWrapper implements BarracudaServletResponseWrapper {
43
44     protected static final Logger logger = Logger.getLogger(DeferredResponseWrapper.class.getName());
45
46     static final String JavaDoc eol = System.getProperty("line.separator");
47
48     protected final SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); //from org.apache.catalina.connector.HttpResponseBase
49
HttpServletResponse JavaDoc uresp = null;
50     LongRunning lr = null;
51     Thread JavaDoc th = null;
52 // ServletOutputStream out = null;
53
StringWriter sw = null;
54     PrintWriter pw = null;
55     Map headers = null;
56     List cookies = null;
57     boolean gotStream = false;
58     boolean gotWriter = false;
59
60     int bufferSize = -1;
61     int contentLength = -1;
62     String JavaDoc contentType = "text/html";
63     Locale locale = null;
64     int sc = HttpServletResponse.SC_OK;
65     String JavaDoc scmsg = getStatusMessage(sc);
66     int err = -1;
67     String JavaDoc errmsg = null;
68     String JavaDoc redirectLoc = null;
69     boolean committed = false;
70     boolean interrupted = false;
71     Object JavaDoc sync = new Object JavaDoc();
72     
73     /**
74      * Create a DeferredResponseWrapper
75      */

76     public DeferredResponseWrapper() {
77     }
78
79     protected void _resetVars() {
80         pw = null;
81         sw = null;
82         gotStream = false;
83         gotWriter = false;
84         headers = null;
85         cookies = null;
86         bufferSize = -1;
87         contentLength = -1;
88         contentType = "text/html";
89         sc = HttpServletResponse.SC_OK;
90         scmsg = getStatusMessage(sc);
91         err = -1;
92         errmsg = null;
93         redirectLoc = null;
94         committed = false;
95         interrupted = false;
96     }
97
98     /**
99      * Go ahead and actually write the response
100      */

101     public void actuallySendResponse(HttpServletResponse JavaDoc resp) throws IOException {
102         synchronized (sync) {
103             //adjust the response
104
if (bufferSize>-1) resp.setBufferSize(bufferSize);
105             if (contentLength>-1) resp.setBufferSize(contentLength);
106             if (contentType!=null) resp.setContentType(contentType);
107             if (locale!=null) resp.setLocale(locale);
108                 
109             //add in any headers
110
if (headers!=null) {
111                 Iterator it = headers.entrySet().iterator();
112                 while (it.hasNext()) {
113                     Map.Entry me = (Map.Entry) it.next();
114                     String JavaDoc key = (String JavaDoc) me.getKey();
115                     Iterator it2 = ((List) me.getValue()).iterator();
116                     while (it2.hasNext()) {
117                         resp.addHeader(key, ""+it2.next());
118                     }
119                 }
120             }
121
122             //add in any cookies
123
if (cookies!=null) {
124                 Iterator it = cookies.iterator();
125                 while (it.hasNext()) {
126                     resp.addCookie((Cookie) it.next());
127                 }
128             }
129
130             //set the error code if any
131
if (err>-1) {
132                 resp.sendError(err, errmsg);
133         
134             //else see if we need to send a redirect
135
} else if (redirectLoc!=null) {
136                 resp.sendRedirect(redirectLoc);
137         
138             //else actually write a response
139
} else {
140                 //finally, set the status
141
resp.setStatus(sc);
142
143                 //then write the response and be done
144
Writer realwr = resp.getWriter();
145                 realwr.write(sw.toString());
146                 realwr.close();
147             }
148         }
149     }
150
151     public void setUnderlyingResponse(HttpServletResponse JavaDoc iuresp) {
152         uresp = iuresp;
153         locale = iuresp.getLocale();
154     }
155     
156     public void setLongRunning(LongRunning ilr) {
157         lr = ilr;
158     }
159     
160     public LongRunning getLongRunning() {
161         return lr;
162     }
163     
164     public void setLongRunningThread(Thread JavaDoc ith) {
165         th = ith;
166     }
167     
168     public Thread JavaDoc getLongRunningThread() {
169         return th;
170     }
171     
172     public void interrupt() {
173         synchronized (sync) {
174             if (!committed) {
175                 interrupted = true;
176                 th.interrupt();
177             }
178         }
179     }
180     
181     public boolean isInterrupted() {
182         return interrupted;
183     }
184     
185     public void setCommitted(boolean val) {
186         committed = true;
187     }
188
189
190     //--------------- ServletResponseWrapper ---------------------
191
/**
192      * Forces any content in the buffer to be written to the client. This implementation
193      * doesn't do aything.
194      */

195     public void flushBuffer() {
196         return;
197     }
198
199     /**
200      * Returns the actual buffer size used for the response.
201      */

202     public int getBufferSize() {
203         return sw.toString().length();
204     }
205
206     /**
207      * Returns the name of the charset used for the MIME body sent in this response.
208      * This implementation is hardcoded to return "ISO-8859-1"
209      */

210     public String JavaDoc getCharacterEncoding() {
211         return "ISO-8859-1";
212     }
213
214     /**
215      * Returns the locale assigned to the response.
216      */

217     public Locale getLocale() {
218         return locale;
219     }
220
221     /**
222      * Allow the ServletOutputStream to be overridden. Resets the PrintWriter and OutputStream
223      *
224      * @exception IllegalStateException if <code>getWriter</code> or
225      * <code>getStream</code>has already been called for this response
226      */

227 // public void setOutputStream(ServletOutputStream iout) {
228
// _resetVars();
229
// out = iout;
230
// }
231

232     /**
233      * Return the servlet output stream associated with this Response.
234      *
235      * @exception IllegalStateException if <code>getWriter</code> has
236      * already been called for this response, or if the response wrapper
237      * writer has been overridden (in that case you ust use <code>getWriter</code>)
238      * @exception IOException if an input/output error occurs
239      */

240     public ServletOutputStream getOutputStream() throws IOException {
241         throw new IllegalStateException JavaDoc("no ServletOutputStream available - you need to use getPrintWriter() instead");
242 // try {
243
// if (gotWriter) throw new IllegalStateException("getPrintWriter() has already been called");
244
// if (gotStream) throw new IllegalStateException("getOutputStream() has already been called");
245
// if (out==null) throw new IllegalStateException("no ServletOutputStream available - you need to call setOutputStream() or use getPrintWriter() instead");
246
// return out;
247
// } finally {
248
// gotStream = true;
249
// }
250
}
251
252     /**
253      * Allow the PrintWriter to be overridden. Resets the PrintWriter and OutputStream
254      *
255      * @exception IllegalStateException if <code>getWriter</code> or
256      * <code>getStream</code>has already been called for this response
257      */

258 // public void setWriter(PrintWriter ipw) {
259
// _resetVars();
260
// pw = ipw;
261
// }
262

263     /**
264      * Return the print writer associated with this Response (this method may
265      * be called multiple times).
266      *
267      * @exception IllegalStateException if <code>getOutputStream</code> has
268      * already been called for this response
269      * @exception IOException if an input/output error occurs
270      */

271     public PrintWriter getWriter() throws IOException {
272         try {
273             if (gotWriter) throw new IllegalStateException JavaDoc("getPrintWriter() has already been called");
274             if (gotStream) throw new IllegalStateException JavaDoc("getOutputStream() has already been called");
275             if (pw==null) {
276                 sw = new StringWriter(1000);
277                 pw = new PrintWriter(sw);
278             }
279             return pw;
280         } finally {
281             gotWriter = true;
282         }
283     }
284     
285     /**
286      * Returns a boolean indicating if the response has been committed.
287      */

288     public boolean isCommitted() {
289         return committed;
290     }
291
292     /**
293      * Clears any data that exists in the buffer as well as the status
294      * code and headers.
295      */

296     public void reset() {
297         _resetVars();
298     }
299
300     /**
301      * Clears the content of the underlying buffer in the response without
302      * clearing headers or status code.
303      */

304     public void resetBuffer() {
305         pw = null;
306         sw = null;
307         gotStream = false;
308         gotWriter = false;
309     }
310
311     /**
312      * Sets the preferred buffer size for the body of the response.
313      * Doesn't do anything in this implementation
314      */

315     public void setBufferSize(int size) {
316         bufferSize = size;
317     }
318
319     /**
320      * Sets the length of the content body in the response In HTTP servlets,
321      * this method sets the HTTP Content-Length header.
322      */

323     public void setContentLength(int len) {
324         contentLength = len;
325     }
326
327     /**
328      * Sets the content type of the response being sent to the client.
329      */

330     public void setContentType(String JavaDoc type) {
331         contentType = type;
332     }
333
334     /**
335      * Sets the locale of the response, setting the headers
336      * (including the Content-Type's charset) as appropriate.
337      */

338     public void setLocale(Locale loc) {
339         locale = loc;
340     }
341
342     //--------------- HttpServletResponseWrapper -----------------
343
/**
344      * Adds the specified cookie to the response.
345      */

346     public void addCookie(Cookie cookie) {
347         if (cookies==null) cookies = new ArrayList();
348         cookies.add(cookie);
349     }
350     
351     /**
352      * Adds a response header with the given name and date-value.
353      */

354     public void addDateHeader(String JavaDoc name, long date) {
355         addHeader(name, sdf.format(new Date(date)));
356     }
357
358
359     /**
360      * Adds a response header with the given name and value.
361      */

362     public void addHeader(String JavaDoc name, String JavaDoc value) {
363         if (headers==null) headers = new TreeMap();
364         List values = (List) headers.get(name);
365         if (values==null) {
366             values = new ArrayList();
367             headers.put(name, values);
368         } else {
369             values.add(value);
370         }
371     }
372
373     /**
374      * Adds a response header with the given name and integer value.
375      */

376     public void addIntHeader(String JavaDoc name, int value) {
377         addHeader(name, ""+value);
378     }
379
380     /**
381      * Returns a boolean indicating whether the named response header
382      * has already been set.
383      */

384     public boolean containsHeader(String JavaDoc name) {
385         return (headers!=null && headers.containsKey(name));
386     }
387
388     /**
389      * Deprecated. As of version 2.1, use encodeRedirectURL(String url)
390      * instead
391      */

392     public String JavaDoc encodeRedirectUrl(String JavaDoc url) {
393         return encodeRedirectURL(url);
394     }
395
396     /**
397      * Encodes the specified URL for use in the sendRedirect method or,
398      * if encoding is not needed, returns the URL unchanged.
399      */

400     public String JavaDoc encodeRedirectURL(String JavaDoc url) {
401         return uresp.encodeRedirectURL(url);
402     }
403
404     /**
405      * Deprecated. As of version 2.1, use encodeURL(String url) instead
406      */

407     public String JavaDoc encodeUrl(String JavaDoc url) {
408         return encodeURL(url);
409     }
410
411     /**
412      * Encodes the specified URL by including the session ID in it, or,
413      * if encoding is not needed, returns the URL unchanged.
414      */

415     public String JavaDoc encodeURL(String JavaDoc url) {
416         return uresp.encodeURL(url);
417     }
418
419     /**
420      * Sends an error response to the client using the specified status
421      * code and clearing the buffer.
422      */

423     public void sendError(int sc) {
424         sendError(sc, getStatusMessage(sc));
425     }
426
427     /**
428      * Sends an error response to the client using the specified status
429      * clearing the buffer.
430      */

431     public void sendError(int sc, String JavaDoc msg) {
432         err = sc;
433         errmsg = msg;
434     }
435
436     /**
437      * Sends a temporary redirect response to the client using the specified
438      * redirect location URL.
439      */

440     public void sendRedirect(String JavaDoc location) {
441         redirectLoc = location;
442     }
443
444     /**
445      * Sets a response header with the given name and date-value.
446      */

447     public void setDateHeader(String JavaDoc name, long date) {
448         setHeader(name, sdf.format(new Date(date)));
449     }
450
451     /**
452      * Sets a response header with the given name and value.
453      */

454     public void setHeader(String JavaDoc name, String JavaDoc value) {
455         if (headers==null) headers = new TreeMap();
456         List values = new ArrayList(1);
457         headers.put(name, values);
458         values.add(value);
459     }
460
461     /**
462      * Sets a response header with the given name and integer value.
463      */

464     public void setIntHeader(String JavaDoc name, int value) {
465         setHeader(name, ""+value);
466     }
467
468     /**
469      * Sets the status code for this response.
470      */

471     public void setStatus(int isc) {
472         sc = isc;
473     }
474
475     /**
476      * Sets the status code for this response.
477      */

478     public void setStatus(int isc, String JavaDoc sm) {
479         sc = sc;
480         scmsg = sm;
481     }
482
483     /**
484      * Returns a default status message for the specified HTTP status code.
485      *
486      * @param status The status code for which a message is desired
487      */

488     public static String JavaDoc getStatusMessage(int isc) {
489         switch (isc) {
490         case SC_OK:
491             return ("OK");
492         case SC_ACCEPTED:
493             return ("Accepted");
494         case SC_BAD_GATEWAY:
495             return ("Bad Gateway");
496         case SC_BAD_REQUEST:
497             return ("Bad Request");
498         case SC_CONFLICT:
499             return ("Conflict");
500         case SC_CONTINUE:
501             return ("Continue");
502         case SC_CREATED:
503             return ("Created");
504         case SC_EXPECTATION_FAILED:
505             return ("Expectation Failed");
506         case SC_FORBIDDEN:
507             return ("Forbidden");
508         case SC_GATEWAY_TIMEOUT:
509             return ("Gateway Timeout");
510         case SC_GONE:
511             return ("Gone");
512         case SC_HTTP_VERSION_NOT_SUPPORTED:
513             return ("HTTP Version Not Supported");
514         case SC_INTERNAL_SERVER_ERROR:
515             return ("Internal Server Error");
516         case SC_LENGTH_REQUIRED:
517             return ("Length Required");
518         case SC_METHOD_NOT_ALLOWED:
519             return ("Method Not Allowed");
520         case SC_MOVED_PERMANENTLY:
521             return ("Moved Permanently");
522         case SC_MOVED_TEMPORARILY:
523             return ("Moved Temporarily");
524         case SC_MULTIPLE_CHOICES:
525             return ("Multiple Choices");
526         case SC_NO_CONTENT:
527             return ("No Content");
528         case SC_NON_AUTHORITATIVE_INFORMATION:
529             return ("Non-Authoritative Information");
530         case SC_NOT_ACCEPTABLE:
531             return ("Not Acceptable");
532         case SC_NOT_FOUND:
533             return ("Not Found");
534         case SC_NOT_IMPLEMENTED:
535             return ("Not Implemented");
536         case SC_NOT_MODIFIED:
537             return ("Not Modified");
538         case SC_PARTIAL_CONTENT:
539             return ("Partial Content");
540         case SC_PAYMENT_REQUIRED:
541             return ("Payment Required");
542         case SC_PRECONDITION_FAILED:
543             return ("Precondition Failed");
544         case SC_PROXY_AUTHENTICATION_REQUIRED:
545             return ("Proxy Authentication Required");
546         case SC_REQUEST_ENTITY_TOO_LARGE:
547             return ("Request Entity Too Large");
548         case SC_REQUEST_TIMEOUT:
549             return ("Request Timeout");
550         case SC_REQUEST_URI_TOO_LONG:
551             return ("Request URI Too Long");
552         case SC_REQUESTED_RANGE_NOT_SATISFIABLE:
553             return ("Requested Range Not Satisfiable");
554         case SC_RESET_CONTENT:
555             return ("Reset Content");
556         case SC_SEE_OTHER:
557             return ("See Other");
558         case SC_SERVICE_UNAVAILABLE:
559             return ("Service Unavailable");
560         case SC_SWITCHING_PROTOCOLS:
561             return ("Switching Protocols");
562         case SC_UNAUTHORIZED:
563             return ("Unauthorized");
564         case SC_UNSUPPORTED_MEDIA_TYPE:
565             return ("Unsupported Media Type");
566         case SC_USE_PROXY:
567             return ("Use Proxy");
568         case 207: // WebDAV
569
return ("Multi-Status");
570         case 422: // WebDAV
571
return ("Unprocessable Entity");
572         case 423: // WebDAV
573
return ("Locked");
574         case 507: // WebDAV
575
return ("Insufficient Storage");
576         default:
577             return ("HTTP Response Status " + isc);
578         }
579
580     }
581           
582           
583 }
584
585
Popular Tags