KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > winstone > WinstoneResponse


1 /*
2  * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
3  * Distributed under the terms of either:
4  * - the common development and distribution license (CDDL), v1.0; or
5  * - the GNU Lesser General Public License, v2.1 or later
6  */

7 package winstone;
8
9 import java.io.IOException JavaDoc;
10 import java.io.PrintWriter JavaDoc;
11 import java.io.UnsupportedEncodingException JavaDoc;
12 import java.io.Writer JavaDoc;
13 import java.text.DateFormat JavaDoc;
14 import java.text.SimpleDateFormat JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Date JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Locale JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.StringTokenizer JavaDoc;
22 import java.util.TimeZone JavaDoc;
23
24 import javax.servlet.ServletOutputStream JavaDoc;
25 import javax.servlet.http.Cookie JavaDoc;
26 import javax.servlet.http.HttpServletResponse JavaDoc;
27
28 /**
29  * Response for servlet
30  *
31  * @author <a HREF="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
32  * @version $Id: WinstoneResponse.java,v 1.28 2005/04/19 07:33:41 rickknowles
33  * Exp $
34  */

35 public class WinstoneResponse implements HttpServletResponse JavaDoc {
36     private static final DateFormat JavaDoc HTTP_DF = new SimpleDateFormat JavaDoc(
37             "EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
38     private static final DateFormat JavaDoc VERSION0_DF = new SimpleDateFormat JavaDoc(
39             "EEE, dd-MMM-yy HH:mm:ss z", Locale.US);
40     static {
41         HTTP_DF.setTimeZone(TimeZone.getTimeZone("GMT"));
42         VERSION0_DF.setTimeZone(TimeZone.getTimeZone("GMT"));
43     }
44
45     static final String JavaDoc CONTENT_LENGTH_HEADER = "Content-Length";
46     static final String JavaDoc CONTENT_TYPE_HEADER = "Content-Type";
47
48     // Response header constants
49
static final String JavaDoc CONTENT_LANGUAGE_HEADER = "Content-Language";
50     static final String JavaDoc KEEP_ALIVE_HEADER = "Connection";
51     static final String JavaDoc ENCODING_HEADER = "Transfer-Encoding";
52     static final String JavaDoc KEEP_ALIVE_OPEN = "Keep-Alive";
53     static final String JavaDoc KEEP_ALIVE_CLOSE = "Close";
54     static final String JavaDoc DATE_HEADER = "Date";
55     static final String JavaDoc SERVER_HEADER = "Server";
56     static final String JavaDoc LOCATION_HEADER = "Location";
57     static final String JavaDoc OUT_COOKIE_HEADER1 = "Set-Cookie";
58     static final String JavaDoc OUT_COOKIE_HEADER2 = "Set-Cookie2";
59     static final String JavaDoc X_POWERED_BY_HEADER = "X-Powered-By";
60     static final String JavaDoc POWERED_BY_WINSTONE = "Servlet/2.4 (Winstone/0.8)";
61
62     private int statusCode;
63     private WinstoneRequest req;
64     private WebAppConfiguration webAppConfig;
65     private WinstoneOutputStream outputStream;
66     private PrintWriter JavaDoc outputWriter;
67     
68     private List JavaDoc headers;
69     private String JavaDoc explicitEncoding;
70     private String JavaDoc implicitEncoding;
71     private List JavaDoc cookies;
72     
73     private Locale JavaDoc locale;
74     private String JavaDoc protocol;
75     private String JavaDoc reqKeepAliveHeader;
76     private Integer JavaDoc errorStatusCode;
77     
78     /**
79      * Constructor
80      */

81     public WinstoneResponse() {
82         
83         this.headers = new ArrayList JavaDoc();
84         this.cookies = new ArrayList JavaDoc();
85
86         this.statusCode = SC_OK;
87         this.locale = null; //Locale.getDefault();
88
this.explicitEncoding = null;
89         this.protocol = null;
90         this.reqKeepAliveHeader = null;
91     }
92
93     /**
94      * Resets the request to be reused
95      */

96     public void cleanUp() {
97         this.req = null;
98         this.webAppConfig = null;
99         this.outputStream = null;
100         this.outputWriter = null;
101         this.headers.clear();
102         this.cookies.clear();
103         this.protocol = null;
104         this.reqKeepAliveHeader = null;
105
106         this.statusCode = SC_OK;
107         this.errorStatusCode = null;
108         this.locale = null; //Locale.getDefault();
109
this.explicitEncoding = null;
110         this.implicitEncoding = null;
111     }
112
113     private String JavaDoc getEncodingFromLocale(Locale JavaDoc loc) {
114         String JavaDoc localeString = loc.getLanguage() + "_" + loc.getCountry();
115         Map JavaDoc encMap = this.webAppConfig.getLocaleEncodingMap();
116         Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
117                 "WinstoneResponse.LookForLocaleEncoding",
118                 new String JavaDoc[] {localeString, encMap + ""});
119
120         String JavaDoc fullMatch = (String JavaDoc) encMap.get(localeString);
121         if (fullMatch != null) {
122             Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
123                     "WinstoneResponse.FoundLocaleEncoding", fullMatch);
124             return fullMatch;
125         } else {
126             localeString = loc.getLanguage();
127             Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
128                     "WinstoneResponse.LookForLocaleEncoding",
129                     new String JavaDoc[] {localeString, encMap + ""});
130             String JavaDoc match = (String JavaDoc) encMap.get(localeString);
131             if (match != null) {
132                 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
133                         "WinstoneResponse.FoundLocaleEncoding", match);
134             }
135             return match;
136         }
137     }
138
139     public void setErrorStatusCode(int statusCode) {
140         this.errorStatusCode = new Integer JavaDoc(statusCode);
141         this.statusCode = statusCode;
142     }
143     
144     public WinstoneOutputStream getWinstoneOutputStream() {
145         return this.outputStream;
146     }
147     
148     public void setOutputStream(WinstoneOutputStream outData) {
149         this.outputStream = outData;
150     }
151
152     public void setWebAppConfig(WebAppConfiguration webAppConfig) {
153         this.webAppConfig = webAppConfig;
154     }
155
156     public String JavaDoc getProtocol() {
157         return this.protocol;
158     }
159
160     public void setProtocol(String JavaDoc protocol) {
161         this.protocol = protocol;
162     }
163
164     public void extractRequestKeepAliveHeader(WinstoneRequest req) {
165         this.reqKeepAliveHeader = req.getHeader(KEEP_ALIVE_HEADER);
166     }
167
168     public List JavaDoc getHeaders() {
169         return this.headers;
170     }
171
172     public List JavaDoc getCookies() {
173         return this.cookies;
174     }
175
176     public WinstoneRequest getRequest() {
177         return this.req;
178     }
179
180     public void setRequest(WinstoneRequest req) {
181         this.req = req;
182     }
183     
184     public void startIncludeBuffer() {
185         this.outputStream.startIncludeBuffer();
186     }
187     
188     public void finishIncludeBuffer() throws IOException JavaDoc {
189         if (isIncluding()) {
190             if (this.outputWriter != null) {
191                 this.outputWriter.flush();
192             }
193             this.outputStream.finishIncludeBuffer();
194         }
195     }
196     
197     public void clearIncludeStackForForward() throws IOException JavaDoc {
198         this.outputStream.clearIncludeStackForForward();
199     }
200
201     protected static String JavaDoc getCharsetFromContentTypeHeader(String JavaDoc type, StringBuffer JavaDoc remainder) {
202         if (type == null) {
203             return null;
204         }
205         // Parse type to set encoding if needed
206
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(type, ";");
207         String JavaDoc localEncoding = null;
208         while (st.hasMoreTokens()) {
209             String JavaDoc clause = st.nextToken().trim();
210             if (clause.startsWith("charset="))
211                 localEncoding = clause.substring(8);
212             else {
213                 if (remainder.length() > 0) {
214                     remainder.append(";");
215                 }
216                 remainder.append(clause);
217             }
218         }
219         if ((localEncoding == null) ||
220                 !localEncoding.startsWith("\"") ||
221                 !localEncoding.endsWith("\"")) {
222             return localEncoding;
223         } else {
224             return localEncoding.substring(1, localEncoding.length() - 1);
225         }
226     }
227
228     /**
229      * This ensures the bare minimum correct http headers are present
230      */

231     public void validateHeaders() {
232         // Need this block for WebDAV support. "Connection:close" header is ignored
233
String JavaDoc lengthHeader = getHeader(CONTENT_LENGTH_HEADER);
234         if ((lengthHeader == null) && (this.statusCode >= 300)) {
235             int bodyBytes = this.outputStream.getOutputStreamLength();
236             if (getBufferSize() > bodyBytes) {
237                 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
238                         "WinstoneResponse.ForcingContentLength", "" + bodyBytes);
239                 forceHeader(CONTENT_LENGTH_HEADER, "" + bodyBytes);
240                 lengthHeader = getHeader(CONTENT_LENGTH_HEADER);
241             }
242         }
243         
244         forceHeader(KEEP_ALIVE_HEADER, !closeAfterRequest() ? KEEP_ALIVE_OPEN : KEEP_ALIVE_CLOSE);
245         String JavaDoc contentType = getHeader(CONTENT_TYPE_HEADER);
246         if (this.statusCode != SC_MOVED_TEMPORARILY) {
247             if (contentType == null) {
248                 // Bypass normal encoding
249
forceHeader(CONTENT_TYPE_HEADER, "text/html;charset=" + getCharacterEncoding());
250             } else if (contentType.startsWith("text/")) {
251                 // replace charset in content
252
StringBuffer JavaDoc remainder = new StringBuffer JavaDoc();
253                 getCharsetFromContentTypeHeader(contentType, remainder);
254                 forceHeader(CONTENT_TYPE_HEADER, remainder.toString() + ";charset=" + getCharacterEncoding());
255             }
256         }
257         if (getHeader(DATE_HEADER) == null) {
258             forceHeader(DATE_HEADER, formatHeaderDate(new Date JavaDoc()));
259         }
260         if (getHeader(X_POWERED_BY_HEADER) == null) {
261             forceHeader(X_POWERED_BY_HEADER, POWERED_BY_WINSTONE);
262         }
263         if (this.locale != null) {
264             String JavaDoc lang = this.locale.getLanguage();
265             if ((this.locale.getCountry() != null) && !this.locale.getCountry().equals("")) {
266                 lang = lang + "-" + this.locale.getCountry();
267             }
268             forceHeader(CONTENT_LANGUAGE_HEADER, lang);
269         }
270         
271         // If we don't have a webappConfig, exit here, cause we definitely don't
272
// have a session
273
if (req.getWebAppConfig() == null) {
274             return;
275         }
276         // Write out the new session cookie if it's present
277
HostConfiguration hostConfig = req.getHostGroup().getHostByName(req.getServerName());
278         for (Iterator JavaDoc i = req.getCurrentSessionIds().keySet().iterator(); i.hasNext(); ) {
279             String JavaDoc prefix = (String JavaDoc) i.next();
280             String JavaDoc sessionId = (String JavaDoc) req.getCurrentSessionIds().get(prefix);
281             WebAppConfiguration ownerContext = hostConfig.getWebAppByURI(prefix);
282             if (ownerContext != null) {
283                 WinstoneSession session = ownerContext.getSessionById(sessionId, true);
284                 if ((session != null) && session.isNew()) {
285                     session.setIsNew(false);
286                     Cookie JavaDoc cookie = new Cookie JavaDoc(WinstoneSession.SESSION_COOKIE_NAME, session.getId());
287                     cookie.setMaxAge(-1);
288                     cookie.setSecure(req.isSecure());
289                     cookie.setVersion(0); //req.isSecure() ? 1 : 0);
290
cookie.setPath(req.getWebAppConfig().getContextPath().equals("") ? "/"
291                                     : req.getWebAppConfig().getContextPath());
292                     this.cookies.add(cookie); // don't call addCookie because we might be including
293
}
294             }
295         }
296         
297         // Look for expired sessions: ie ones where the requested and current ids are different
298
for (Iterator JavaDoc i = req.getRequestedSessionIds().keySet().iterator(); i.hasNext(); ) {
299             String JavaDoc prefix = (String JavaDoc) i.next();
300             String JavaDoc sessionId = (String JavaDoc) req.getRequestedSessionIds().get(prefix);
301             if (!req.getCurrentSessionIds().containsKey(prefix)) {
302                 Cookie JavaDoc cookie = new Cookie JavaDoc(WinstoneSession.SESSION_COOKIE_NAME, sessionId);
303                 cookie.setMaxAge(0); // explicitly expire this cookie
304
cookie.setSecure(req.isSecure());
305                 cookie.setVersion(0); //req.isSecure() ? 1 : 0);
306
cookie.setPath(prefix.equals("") ? "/" : prefix);
307                 this.cookies.add(cookie); // don't call addCookie because we might be including
308
}
309         }
310         
311         Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeadersPreCommit",
312                 this.headers + "");
313     }
314
315     /**
316      * Writes out the http header for a single cookie
317      */

318     public String JavaDoc writeCookie(Cookie JavaDoc cookie) throws IOException JavaDoc {
319         
320         Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.WritingCookie", cookie + "");
321         StringBuffer JavaDoc out = new StringBuffer JavaDoc();
322
323         // Set-Cookie or Set-Cookie2
324
if (cookie.getVersion() >= 1)
325             out.append(OUT_COOKIE_HEADER1).append(": "); // TCK doesn't like set-cookie2
326
else
327             out.append(OUT_COOKIE_HEADER1).append(": ");
328
329         // name/value pair
330
if (cookie.getVersion() == 0)
331             out.append(cookie.getName()).append("=").append(cookie.getValue());
332         else {
333             out.append(cookie.getName()).append("=");
334             quote(cookie.getValue(), out);
335         }
336
337         if (cookie.getVersion() >= 1) {
338             out.append("; Version=1");
339             if (cookie.getDomain() != null) {
340                 out.append("; Domain=");
341                 quote(cookie.getDomain(), out);
342             }
343             if (cookie.getSecure())
344                 out.append("; Secure");
345
346             if (cookie.getMaxAge() >= 0)
347                 out.append("; Max-Age=").append(cookie.getMaxAge());
348             else
349                 out.append("; Discard");
350             if (cookie.getPath() != null) {
351                 out.append("; Path=");
352                 quote(cookie.getPath(), out);
353             }
354         } else {
355             if (cookie.getDomain() != null) {
356                 out.append("; Domain=");
357                 out.append(cookie.getDomain());
358             }
359             if (cookie.getMaxAge() > 0) {
360                 long expiryMS = System.currentTimeMillis()
361                         + (1000 * (long) cookie.getMaxAge());
362                 String JavaDoc expiryDate = null;
363                 synchronized (VERSION0_DF) {
364                     expiryDate = VERSION0_DF.format(new Date JavaDoc(expiryMS));
365                 }
366                 out.append("; Expires=").append(expiryDate);
367             } else if (cookie.getMaxAge() == 0) {
368                 String JavaDoc expiryDate = null;
369                 synchronized (VERSION0_DF) {
370                     expiryDate = VERSION0_DF.format(new Date JavaDoc(5000));
371                 }
372                 out.append("; Expires=").append(expiryDate);
373             }
374             if (cookie.getPath() != null)
375                 out.append("; Path=").append(cookie.getPath());
376             if (cookie.getSecure())
377                 out.append("; Secure");
378         }
379         return out.toString();
380     }
381
382     private static String JavaDoc formatHeaderDate(Date JavaDoc dateIn) {
383         String JavaDoc date = null;
384         synchronized (HTTP_DF) {
385             date = HTTP_DF.format(dateIn);
386         }
387         return date;
388     }
389     
390     /**
391      * Quotes the necessary strings in a cookie header. The quoting is only
392      * applied if the string contains special characters.
393      */

394     protected void quote(String JavaDoc value, StringBuffer JavaDoc out) {
395         if (value.startsWith("\"") && value.endsWith("\"")) {
396             out.append(value);
397         } else {
398             boolean containsSpecial = false;
399             for (int n = 0; n < value.length(); n++) {
400                 char thisChar = value.charAt(n);
401                 if ((thisChar < 32) || (thisChar >= 127)
402                         || (specialCharacters.indexOf(thisChar) != -1)) {
403                     containsSpecial = true;
404                     break;
405                 }
406             }
407             if (containsSpecial)
408                 out.append('"').append(value).append('"');
409             else
410                 out.append(value);
411         }
412     }
413
414     final String JavaDoc specialCharacters = "()<>@,;:\\\"/[]?={} \t";
415
416     /**
417      * Based on request/response headers and the protocol, determine whether or
418      * not this connection should operate in keep-alive mode.
419      */

420     public boolean closeAfterRequest() {
421         String JavaDoc inKeepAliveHeader = this.reqKeepAliveHeader;
422         String JavaDoc outKeepAliveHeader = getHeader(KEEP_ALIVE_HEADER);
423         boolean hasContentLength = (getHeader(CONTENT_LENGTH_HEADER) != null);
424         if (this.protocol.startsWith("HTTP/0"))
425             return true;
426         else if ((inKeepAliveHeader == null) && (outKeepAliveHeader == null))
427             return this.protocol.equals("HTTP/1.0") ? true : !hasContentLength;
428         else if (outKeepAliveHeader != null)
429             return outKeepAliveHeader.equalsIgnoreCase(KEEP_ALIVE_CLOSE) || !hasContentLength;
430         else if (inKeepAliveHeader != null)
431             return inKeepAliveHeader.equalsIgnoreCase(KEEP_ALIVE_CLOSE) || !hasContentLength;
432         else
433             return false;
434     }
435     
436     // ServletResponse interface methods
437
public void flushBuffer() throws IOException JavaDoc {
438         if (this.outputWriter != null) {
439             this.outputWriter.flush();
440         }
441         this.outputStream.flush();
442     }
443
444     public void setBufferSize(int size) {
445         this.outputStream.setBufferSize(size);
446     }
447
448     public int getBufferSize() {
449         return this.outputStream.getBufferSize();
450     }
451
452     public String JavaDoc getCharacterEncoding() {
453         String JavaDoc enc = getCurrentEncoding();
454         return (enc == null ? "ISO-8859-1" : enc);
455     }
456
457     public void setCharacterEncoding(String JavaDoc encoding) {
458         if ((this.outputWriter == null) && !isCommitted()) {
459             Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.SettingEncoding", encoding);
460             this.explicitEncoding = encoding;
461             correctContentTypeHeaderEncoding(encoding);
462         }
463     }
464
465     private void correctContentTypeHeaderEncoding(String JavaDoc encoding) {
466         String JavaDoc contentType = getContentType();
467         if (contentType != null) {
468             StringBuffer JavaDoc remainderHeader = new StringBuffer JavaDoc();
469             getCharsetFromContentTypeHeader(contentType, remainderHeader);
470             if (remainderHeader.length() != 0) {
471                 forceHeader(CONTENT_TYPE_HEADER, remainderHeader + ";charset=" + encoding);
472             }
473         }
474     }
475     
476     public String JavaDoc getContentType() {
477         return getHeader(CONTENT_TYPE_HEADER);
478     }
479
480     public void setContentType(String JavaDoc type) {
481         setHeader(CONTENT_TYPE_HEADER, type);
482     }
483
484     public Locale JavaDoc getLocale() {
485         return this.locale == null ? Locale.getDefault() : this.locale;
486     }
487
488     private boolean isIncluding() {
489         return this.outputStream.isIncluding();
490     }
491     
492     public void setLocale(Locale JavaDoc loc) {
493         if (isIncluding()) {
494             return;
495         } else if (isCommitted()) {
496             Logger.log(Logger.WARNING, Launcher.RESOURCES,
497                     "WinstoneResponse.SetLocaleTooLate");
498         } else {
499             if ((this.outputWriter == null) && (this.explicitEncoding == null)) {
500                 String JavaDoc localeEncoding = getEncodingFromLocale(loc);
501                 if (localeEncoding != null) {
502                     this.implicitEncoding = localeEncoding;
503                     correctContentTypeHeaderEncoding(localeEncoding);
504                 }
505             }
506             this.locale = loc;
507         }
508     }
509
510     public ServletOutputStream JavaDoc getOutputStream() throws IOException JavaDoc {
511         Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.GetOutputStream");
512         return this.outputStream;
513     }
514
515     public PrintWriter JavaDoc getWriter() throws IOException JavaDoc {
516         Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.GetWriter");
517         if (this.outputWriter != null)
518             return this.outputWriter;
519         else {
520             this.outputWriter = new WinstoneResponseWriter(this.outputStream, this);
521             return this.outputWriter;
522         }
523     }
524
525     public boolean isCommitted() {
526         return this.outputStream.isCommitted();
527     }
528
529     public void reset() {
530         if (!isIncluding()) {
531             resetBuffer();
532             this.statusCode = SC_OK;
533             this.headers.clear();
534             this.cookies.clear();
535         }
536     }
537
538     public void resetBuffer() {
539         if (!isIncluding()) {
540             if (isCommitted())
541                 throw new IllegalStateException JavaDoc(Launcher.RESOURCES
542                         .getString("WinstoneResponse.ResponseCommitted"));
543             
544             // Disregard any output temporarily while we flush
545
this.outputStream.setDisregardMode(true);
546             
547             if (this.outputWriter != null) {
548                 this.outputWriter.flush();
549             }
550             
551             this.outputStream.setDisregardMode(false);
552             this.outputStream.reset();
553         }
554     }
555
556     public void setContentLength(int len) {
557         setIntHeader(CONTENT_LENGTH_HEADER, len);
558     }
559
560     // HttpServletResponse interface methods
561
public void addCookie(Cookie JavaDoc cookie) {
562         if (!isIncluding()) {
563             this.cookies.add(cookie);
564         }
565     }
566
567     public boolean containsHeader(String JavaDoc name) {
568         for (int n = 0; n < this.headers.size(); n++)
569             if (((String JavaDoc) this.headers.get(n)).startsWith(name))
570                 return true;
571         return false;
572     }
573
574     public void addDateHeader(String JavaDoc name, long date) {
575         addHeader(name, formatHeaderDate(new Date JavaDoc(date)));
576     } // df.format(new Date(date)));}
577

578     public void addIntHeader(String JavaDoc name, int value) {
579         addHeader(name, "" + value);
580     }
581
582     public void addHeader(String JavaDoc name, String JavaDoc value) {
583         if (isIncluding()) {
584             Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderInInclude",
585                     new String JavaDoc[] {name, value});
586         } else if (isCommitted()) {
587             Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderAfterCommitted",
588                     new String JavaDoc[] {name, value});
589         } else if (value != null) {
590             if (name.equals(CONTENT_TYPE_HEADER)) {
591                 StringBuffer JavaDoc remainderHeader = new StringBuffer JavaDoc();
592                 String JavaDoc headerEncoding = getCharsetFromContentTypeHeader(value, remainderHeader);
593                 if (this.outputWriter != null) {
594                     value = remainderHeader + ";charset=" + getCharacterEncoding();
595                 } else if (headerEncoding != null) {
596                     this.explicitEncoding = headerEncoding;
597                 }
598             }
599             this.headers.add(name + ": " + value);
600         }
601     }
602
603     public void setDateHeader(String JavaDoc name, long date) {
604         setHeader(name, formatHeaderDate(new Date JavaDoc(date)));
605     }
606
607     public void setIntHeader(String JavaDoc name, int value) {
608         setHeader(name, "" + value);
609     }
610
611     public void setHeader(String JavaDoc name, String JavaDoc value) {
612         if (isIncluding()) {
613             Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderInInclude",
614                     new String JavaDoc[] {name, value});
615         } else if (isCommitted()) {
616             Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderAfterCommitted",
617                     new String JavaDoc[] {name, value});
618         } else {
619             boolean found = false;
620             for (int n = 0; (n < this.headers.size()); n++) {
621                 String JavaDoc header = (String JavaDoc) this.headers.get(n);
622                 if (header.startsWith(name + ": ")) {
623                     if (found) {
624                         this.headers.remove(n);
625                         continue;
626                     }
627                     if (name.equals(CONTENT_TYPE_HEADER)) {
628                         if (value != null) {
629                             StringBuffer JavaDoc remainderHeader = new StringBuffer JavaDoc();
630                             String JavaDoc headerEncoding = getCharsetFromContentTypeHeader(
631                                     value, remainderHeader);
632                             if (this.outputWriter != null) {
633                                 value = remainderHeader + ";charset=" + getCharacterEncoding();
634                             } else if (headerEncoding != null) {
635                                 this.explicitEncoding = headerEncoding;
636                             }
637                         }
638                     }
639
640                     if (value != null) {
641                         this.headers.set(n, name + ": " + value);
642                     } else {
643                         this.headers.remove(n);
644                     }
645                     found = true;
646                 }
647             }
648             if (!found) {
649                 addHeader(name, value);
650             }
651         }
652     }
653
654     private void forceHeader(String JavaDoc name, String JavaDoc value) {
655         boolean found = false;
656         for (int n = 0; (n < this.headers.size()); n++) {
657             String JavaDoc header = (String JavaDoc) this.headers.get(n);
658             if (header.startsWith(name + ": ")) {
659                 found = true;
660                 this.headers.set(n, name + ": " + value);
661             }
662         }
663         if (!found) {
664             this.headers.add(name + ": " + value);
665         }
666     }
667     
668     private String JavaDoc getCurrentEncoding() {
669         if (this.explicitEncoding != null) {
670             return this.explicitEncoding;
671         } else if (this.implicitEncoding != null) {
672             return this.implicitEncoding;
673         } else if ((this.req != null) && (this.req.getCharacterEncoding() != null)) {
674             try {
675                 "0".getBytes(this.req.getCharacterEncoding());
676                 return this.req.getCharacterEncoding();
677             } catch (UnsupportedEncodingException JavaDoc err) {
678                 return null;
679             }
680         } else {
681             return null;
682         }
683     }
684     
685     public String JavaDoc getHeader(String JavaDoc name) {
686         for (int n = 0; n < this.headers.size(); n++) {
687             String JavaDoc header = (String JavaDoc) this.headers.get(n);
688             if (header.startsWith(name + ": "))
689                 return header.substring(name.length() + 2);
690         }
691         return null;
692     }
693
694     public String JavaDoc encodeRedirectURL(String JavaDoc url) {
695         return url;
696     }
697
698     public String JavaDoc encodeURL(String JavaDoc url) {
699         return url;
700     }
701
702     public int getStatus() {
703         return this.statusCode;
704     }
705
706     public Integer JavaDoc getErrorStatusCode() {
707         return this.errorStatusCode;
708     }
709
710     public void setStatus(int sc) {
711         if (!isIncluding() && (this.errorStatusCode == null)) {
712 // if (!isIncluding()) {
713
this.statusCode = sc;
714 // if (this.errorStatusCode != null) {
715
// this.errorStatusCode = new Integer(sc);
716
// }
717
}
718     }
719
720     public void sendRedirect(String JavaDoc location) throws IOException JavaDoc {
721         if (isIncluding()) {
722             Logger.log(Logger.ERROR, Launcher.RESOURCES, "IncludeResponse.Redirect",
723                     location);
724             return;
725         } else if (isCommitted()) {
726             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString("WinstoneOutputStream.AlreadyCommitted"));
727         }
728         resetBuffer();
729         
730         // Build location
731
StringBuffer JavaDoc fullLocation = new StringBuffer JavaDoc();
732         if (location.startsWith("http://") || location.startsWith("https://"))
733             fullLocation.append(location);
734         else {
735             fullLocation.append(this.req.getScheme()).append("://");
736             fullLocation.append(this.req.getServerName());
737             if (!((this.req.getServerPort() == 80) && this.req.getScheme()
738                     .equals("http"))
739                     && !((this.req.getServerPort() == 443) && this.req
740                             .getScheme().equals("https")))
741                 fullLocation.append(':').append(this.req.getServerPort());
742             if (location.startsWith("/")) {
743                 fullLocation.append(location);
744             } else {
745                 fullLocation.append(this.req.getRequestURI());
746                 if (fullLocation.toString().indexOf("?") != -1)
747                     fullLocation.delete(fullLocation.toString().indexOf("?"),
748                             fullLocation.length());
749                 fullLocation.delete(
750                         fullLocation.toString().lastIndexOf("/") + 1,
751                         fullLocation.length());
752                 fullLocation.append(location);
753             }
754         }
755         if (this.req != null) {
756             this.req.discardRequestBody();
757         }
758         this.statusCode = HttpServletResponse.SC_MOVED_TEMPORARILY;
759         setHeader(LOCATION_HEADER, fullLocation.toString());
760         setContentLength(0);
761         getWriter().flush();
762     }
763
764     public void sendError(int sc) throws IOException JavaDoc {
765         sendError(sc, null);
766     }
767
768     public void sendError(int sc, String JavaDoc msg) throws IOException JavaDoc {
769         if (isIncluding()) {
770             Logger.log(Logger.ERROR, Launcher.RESOURCES, "IncludeResponse.Error",
771                     new String JavaDoc[] { "" + sc, msg });
772             return;
773         }
774         
775         Logger.log(Logger.DEBUG, Launcher.RESOURCES,
776                 "WinstoneResponse.SendingError", new String JavaDoc[] { "" + sc, msg });
777
778         if ((this.webAppConfig != null) && (this.req != null)) {
779             
780             RequestDispatcher rd = this.webAppConfig
781                     .getErrorDispatcherByCode(sc, msg, null);
782             if (rd != null) {
783                 try {
784                     rd.forward(this.req, this);
785                     return;
786                 } catch (IllegalStateException JavaDoc err) {
787                     throw err;
788                 } catch (IOException JavaDoc err) {
789                     throw err;
790                 } catch (Throwable JavaDoc err) {
791                     Logger.log(Logger.WARNING, Launcher.RESOURCES,
792                             "WinstoneResponse.ErrorInErrorPage", new String JavaDoc[] {
793                                     rd.getName(), sc + "" }, err);
794                     return;
795                 }
796             }
797         }
798         // If we are here there was no webapp and/or no request object, so
799
// show the default error page
800
if (this.errorStatusCode == null) {
801             this.statusCode = sc;
802         }
803         String JavaDoc output = Launcher.RESOURCES.getString("WinstoneResponse.ErrorPage",
804                 new String JavaDoc[] { sc + "", (msg == null ? "" : msg), "",
805                         Launcher.RESOURCES.getString("ServerVersion"),
806                         "" + new Date JavaDoc() });
807         setContentLength(output.getBytes(getCharacterEncoding()).length);
808         Writer JavaDoc out = getWriter();
809         out.write(output);
810         out.flush();
811     }
812
813     /**
814      * @deprecated
815      */

816     public String JavaDoc encodeRedirectUrl(String JavaDoc url) {
817         return encodeRedirectURL(url);
818     }
819
820     /**
821      * @deprecated
822      */

823     public String JavaDoc encodeUrl(String JavaDoc url) {
824         return encodeURL(url);
825     }
826
827     /**
828      * @deprecated
829      */

830     public void setStatus(int sc, String JavaDoc sm) {
831         setStatus(sc);
832     }
833 }
834
Popular Tags