KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > coyote > Response


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.coyote;
19
20 import java.io.IOException JavaDoc;
21 import java.util.Locale JavaDoc;
22
23 import org.apache.tomcat.util.buf.ByteChunk;
24 import org.apache.tomcat.util.http.MimeHeaders;
25
26 /**
27  * Response object.
28  *
29  * @author James Duncan Davidson [duncan@eng.sun.com]
30  * @author Jason Hunter [jch@eng.sun.com]
31  * @author James Todd [gonzo@eng.sun.com]
32  * @author Harish Prabandham
33  * @author Hans Bergsten <hans@gefionsoftware.com>
34  * @author Remy Maucherat
35  */

36 public final class Response {
37
38
39     // ----------------------------------------------------------- Constructors
40

41
42     public Response() {
43     }
44
45
46     // ----------------------------------------------------- Class Variables
47

48     /**
49      * Default locale as mandated by the spec.
50      */

51     private static Locale JavaDoc DEFAULT_LOCALE = Locale.getDefault();
52
53
54     // ----------------------------------------------------- Instance Variables
55

56     /**
57      * Status code.
58      */

59     protected int status = 200;
60
61
62     /**
63      * Status message.
64      */

65     protected String JavaDoc message = null;
66
67
68     /**
69      * Response headers.
70      */

71     protected MimeHeaders headers = new MimeHeaders();
72
73
74     /**
75      * Associated output buffer.
76      */

77     protected OutputBuffer outputBuffer;
78
79
80     /**
81      * Notes.
82      */

83     protected Object JavaDoc notes[] = new Object JavaDoc[Constants.MAX_NOTES];
84
85
86     /**
87      * Committed flag.
88      */

89     protected boolean commited = false;
90
91
92     /**
93      * Action hook.
94      */

95     public ActionHook hook;
96
97
98     /**
99      * HTTP specific fields.
100      */

101     protected String JavaDoc contentType = null;
102     protected String JavaDoc contentLanguage = null;
103     protected String JavaDoc characterEncoding = Constants.DEFAULT_CHARACTER_ENCODING;
104     protected long contentLength = -1;
105     private Locale JavaDoc locale = DEFAULT_LOCALE;
106
107     // General informations
108
private long bytesWritten=0;
109
110     /**
111      * Holds request error exception.
112      */

113     protected Exception JavaDoc errorException = null;
114
115     /**
116      * Has the charset been explicitly set.
117      */

118     protected boolean charsetSet = false;
119
120     /**
121      * Request error URI.
122      */

123     protected String JavaDoc errorURI = null;
124
125     protected Request req;
126
127     // ------------------------------------------------------------- Properties
128

129     public Request getRequest() {
130         return req;
131     }
132
133     public void setRequest( Request req ) {
134         this.req=req;
135     }
136
137     public OutputBuffer getOutputBuffer() {
138         return outputBuffer;
139     }
140
141
142     public void setOutputBuffer(OutputBuffer outputBuffer) {
143         this.outputBuffer = outputBuffer;
144     }
145
146
147     public MimeHeaders getMimeHeaders() {
148         return headers;
149     }
150
151
152     public ActionHook getHook() {
153         return hook;
154     }
155
156
157     public void setHook(ActionHook hook) {
158         this.hook = hook;
159     }
160
161
162     // -------------------- Per-Response "notes" --------------------
163

164
165     public final void setNote(int pos, Object JavaDoc value) {
166         notes[pos] = value;
167     }
168
169
170     public final Object JavaDoc getNote(int pos) {
171         return notes[pos];
172     }
173
174
175     // -------------------- Actions --------------------
176

177
178     public void action(ActionCode actionCode, Object JavaDoc param) {
179         if (hook != null) {
180             if( param==null )
181                 hook.action(actionCode, this);
182             else
183                 hook.action(actionCode, param);
184         }
185     }
186
187
188     // -------------------- State --------------------
189

190
191     public int getStatus() {
192         return status;
193     }
194
195     
196     /**
197      * Set the response status
198      */

199     public void setStatus( int status ) {
200         this.status = status;
201     }
202
203
204     /**
205      * Get the status message.
206      */

207     public String JavaDoc getMessage() {
208         return message;
209     }
210
211
212     /**
213      * Set the status message.
214      */

215     public void setMessage(String JavaDoc message) {
216         this.message = message;
217     }
218
219
220     public boolean isCommitted() {
221         return commited;
222     }
223
224
225     public void setCommitted(boolean v) {
226         this.commited = v;
227     }
228
229
230     // -----------------Error State --------------------
231

232
233     /**
234      * Set the error Exception that occurred during
235      * request processing.
236      */

237     public void setErrorException(Exception JavaDoc ex) {
238     errorException = ex;
239     }
240
241
242     /**
243      * Get the Exception that occurred during request
244      * processing.
245      */

246     public Exception JavaDoc getErrorException() {
247         return errorException;
248     }
249
250
251     public boolean isExceptionPresent() {
252         return ( errorException != null );
253     }
254
255
256     /**
257      * Set request URI that caused an error during
258      * request processing.
259      */

260     public void setErrorURI(String JavaDoc uri) {
261         errorURI = uri;
262     }
263
264
265     /** Get the request URI that caused the original error.
266      */

267     public String JavaDoc getErrorURI() {
268         return errorURI;
269     }
270
271
272     // -------------------- Methods --------------------
273

274     
275     public void reset()
276         throws IllegalStateException JavaDoc {
277         
278         // Reset the headers only if this is the main request,
279
// not for included
280
contentType = null;
281         locale = DEFAULT_LOCALE;
282         contentLanguage = null;
283         characterEncoding = Constants.DEFAULT_CHARACTER_ENCODING;
284         contentLength = -1;
285         charsetSet = false;
286
287         status = 200;
288         message = null;
289         headers.clear();
290         
291         // Force the PrintWriter to flush its data to the output
292
// stream before resetting the output stream
293
//
294
// Reset the stream
295
if (commited) {
296             //String msg = sm.getString("servletOutputStreamImpl.reset.ise");
297
throw new IllegalStateException JavaDoc();
298         }
299         
300         action(ActionCode.ACTION_RESET, this);
301     }
302
303
304     public void finish() throws IOException JavaDoc {
305         action(ActionCode.ACTION_CLOSE, this);
306     }
307
308
309     public void acknowledge() throws IOException JavaDoc {
310         action(ActionCode.ACTION_ACK, this);
311     }
312
313
314     // -------------------- Headers --------------------
315
/**
316      * Warning: This method always returns <code>false<code> for Content-Type
317      * and Content-Length.
318      */

319     public boolean containsHeader(String JavaDoc name) {
320         return headers.getHeader(name) != null;
321     }
322
323
324     public void setHeader(String JavaDoc name, String JavaDoc value) {
325         char cc=name.charAt(0);
326         if( cc=='C' || cc=='c' ) {
327             if( checkSpecialHeader(name, value) )
328             return;
329         }
330         headers.setValue(name).setString( value);
331     }
332
333
334     public void addHeader(String JavaDoc name, String JavaDoc value) {
335         char cc=name.charAt(0);
336         if( cc=='C' || cc=='c' ) {
337             if( checkSpecialHeader(name, value) )
338             return;
339         }
340         headers.addValue(name).setString( value );
341     }
342
343     
344     /**
345      * Set internal fields for special header names.
346      * Called from set/addHeader.
347      * Return true if the header is special, no need to set the header.
348      */

349     private boolean checkSpecialHeader( String JavaDoc name, String JavaDoc value) {
350         // XXX Eliminate redundant fields !!!
351
// ( both header and in special fields )
352
if( name.equalsIgnoreCase( "Content-Type" ) ) {
353             setContentType( value );
354             return true;
355         }
356         if( name.equalsIgnoreCase( "Content-Length" ) ) {
357             try {
358                 long cL=Long.parseLong( value );
359                 setContentLength( cL );
360                 return true;
361             } catch( NumberFormatException JavaDoc ex ) {
362                 // Do nothing - the spec doesn't have any "throws"
363
// and the user might know what he's doing
364
return false;
365             }
366         }
367         if( name.equalsIgnoreCase( "Content-Language" ) ) {
368             // XXX XXX Need to construct Locale or something else
369
}
370         return false;
371     }
372
373
374     /** Signal that we're done with the headers, and body will follow.
375      * Any implementation needs to notify ContextManager, to allow
376      * interceptors to fix headers.
377      */

378     public void sendHeaders() throws IOException JavaDoc {
379         action(ActionCode.ACTION_COMMIT, this);
380         commited = true;
381     }
382
383
384     // -------------------- I18N --------------------
385

386
387     public Locale JavaDoc getLocale() {
388         return locale;
389     }
390
391     /**
392      * Called explicitely by user to set the Content-Language and
393      * the default encoding
394      */

395     public void setLocale(Locale JavaDoc locale) {
396
397         if (locale == null) {
398             return; // throw an exception?
399
}
400
401         // Save the locale for use by getLocale()
402
this.locale = locale;
403
404         // Set the contentLanguage for header output
405
contentLanguage = locale.getLanguage();
406         if ((contentLanguage != null) && (contentLanguage.length() > 0)) {
407             String JavaDoc country = locale.getCountry();
408             StringBuffer JavaDoc value = new StringBuffer JavaDoc(contentLanguage);
409             if ((country != null) && (country.length() > 0)) {
410                 value.append('-');
411                 value.append(country);
412             }
413             contentLanguage = value.toString();
414         }
415
416     }
417
418     /**
419      * Return the content language.
420      */

421     public String JavaDoc getContentLanguage() {
422         return contentLanguage;
423     }
424
425     /*
426      * Overrides the name of the character encoding used in the body
427      * of the response. This method must be called prior to writing output
428      * using getWriter().
429      *
430      * @param charset String containing the name of the chararacter encoding.
431      */

432     public void setCharacterEncoding(String JavaDoc charset) {
433
434         if (isCommitted())
435             return;
436         if (charset == null)
437             return;
438
439         characterEncoding = charset;
440         charsetSet=true;
441     }
442
443     public String JavaDoc getCharacterEncoding() {
444         return characterEncoding;
445     }
446
447     /**
448      * Sets the content type.
449      *
450      * This method must preserve any response charset that may already have
451      * been set via a call to response.setContentType(), response.setLocale(),
452      * or response.setCharacterEncoding().
453      *
454      * @param type the content type
455      */

456     public void setContentType(String JavaDoc type) {
457
458         int semicolonIndex = -1;
459
460         if (type == null) {
461             this.contentType = null;
462             return;
463         }
464
465         /*
466          * Remove the charset param (if any) from the Content-Type, and use it
467          * to set the response encoding.
468          * The most recent response encoding setting will be appended to the
469          * response's Content-Type (as its charset param) by getContentType();
470          */

471         boolean hasCharset = false;
472         int len = type.length();
473         int index = type.indexOf(';');
474         while (index != -1) {
475             semicolonIndex = index;
476             index++;
477             while (index < len && Character.isSpace(type.charAt(index))) {
478                 index++;
479             }
480             if (index+8 < len
481                     && type.charAt(index) == 'c'
482                     && type.charAt(index+1) == 'h'
483                     && type.charAt(index+2) == 'a'
484                     && type.charAt(index+3) == 'r'
485                     && type.charAt(index+4) == 's'
486                     && type.charAt(index+5) == 'e'
487                     && type.charAt(index+6) == 't'
488                     && type.charAt(index+7) == '=') {
489                 hasCharset = true;
490                 break;
491             }
492             index = type.indexOf(';', index);
493         }
494
495         if (!hasCharset) {
496             this.contentType = type;
497             return;
498         }
499
500         this.contentType = type.substring(0, semicolonIndex);
501         String JavaDoc tail = type.substring(index+8);
502         int nextParam = tail.indexOf(';');
503         String JavaDoc charsetValue = null;
504         if (nextParam != -1) {
505             this.contentType += tail.substring(nextParam);
506             charsetValue = tail.substring(0, nextParam);
507         } else {
508             charsetValue = tail;
509         }
510
511         // The charset value may be quoted, but must not contain any quotes.
512
if (charsetValue != null && charsetValue.length() > 0) {
513             charsetSet=true;
514             charsetValue = charsetValue.replace('"', ' ');
515             this.characterEncoding = charsetValue.trim();
516         }
517     }
518
519     public String JavaDoc getContentType() {
520
521         String JavaDoc ret = contentType;
522
523         if (ret != null
524             && characterEncoding != null
525             && charsetSet) {
526             ret = ret + ";charset=" + characterEncoding;
527         }
528
529         return ret;
530     }
531     
532     public void setContentLength(int contentLength) {
533         this.contentLength = contentLength;
534     }
535
536     public void setContentLength(long contentLength) {
537         this.contentLength = contentLength;
538     }
539
540     public int getContentLength() {
541         long length = getContentLengthLong();
542         
543         if (length < Integer.MAX_VALUE) {
544             return (int) length;
545         }
546         return -1;
547     }
548     
549     public long getContentLengthLong() {
550         return contentLength;
551     }
552
553
554     /**
555      * Write a chunk of bytes.
556      */

557     public void doWrite(ByteChunk chunk/*byte buffer[], int pos, int count*/)
558         throws IOException JavaDoc
559     {
560         outputBuffer.doWrite(chunk, this);
561         bytesWritten+=chunk.getLength();
562     }
563
564     // --------------------
565

566     public void recycle() {
567         
568         contentType = null;
569         contentLanguage = null;
570         locale = DEFAULT_LOCALE;
571         characterEncoding = Constants.DEFAULT_CHARACTER_ENCODING;
572         charsetSet = false;
573         contentLength = -1;
574         status = 200;
575         message = null;
576         commited = false;
577         errorException = null;
578         errorURI = null;
579         headers.clear();
580
581         // update counters
582
bytesWritten=0;
583     }
584
585     public long getBytesWritten() {
586         return bytesWritten;
587     }
588
589     public void setBytesWritten(long bytesWritten) {
590         this.bytesWritten = bytesWritten;
591     }
592 }
593
Popular Tags