KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > coyote > tomcat4 > CoyoteResponse


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

16
17 package org.apache.coyote.tomcat4;
18
19
20 import java.io.IOException JavaDoc;
21 import java.io.OutputStream JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.net.MalformedURLException JavaDoc;
24 import java.text.SimpleDateFormat JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Date JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.Locale JavaDoc;
29 import java.util.TimeZone JavaDoc;
30 import java.util.Vector JavaDoc;
31
32 import javax.servlet.ServletOutputStream JavaDoc;
33 import javax.servlet.ServletResponse JavaDoc;
34 import javax.servlet.http.Cookie JavaDoc;
35 import javax.servlet.http.HttpServletRequest JavaDoc;
36 import javax.servlet.http.HttpServletResponse JavaDoc;
37 import javax.servlet.http.HttpSession JavaDoc;
38
39 import org.apache.catalina.Connector;
40 import org.apache.catalina.Context;
41 import org.apache.catalina.HttpResponse;
42 import org.apache.catalina.util.CharsetMapper;
43 import org.apache.catalina.util.StringManager;
44 import org.apache.coyote.Response;
45 import org.apache.tomcat.util.buf.CharChunk;
46 import org.apache.tomcat.util.buf.UEncoder;
47 import org.apache.tomcat.util.http.MimeHeaders;
48 import org.apache.tomcat.util.http.ServerCookie;
49 import org.apache.tomcat.util.net.URL;
50
51
52 /**
53  * Wrapper object for the Coyote response.
54  *
55  * @author Remy Maucherat
56  * @author Craig R. McClanahan
57  * @version $Revision: 1.40 $ $Date: 2004/08/29 17:14:41 $
58  */

59
60 public class CoyoteResponse
61     implements HttpResponse, HttpServletResponse JavaDoc {
62
63
64     // ----------------------------------------------------------- Constructors
65

66
67     public CoyoteResponse() {
68
69         format.setTimeZone(TimeZone.getTimeZone("GMT"));
70         urlEncoder.addSafeCharacter('/');
71
72     }
73
74
75     // ----------------------------------------------------- Instance Variables
76

77
78     /**
79      * The date format we will use for creating date headers.
80      */

81     protected final SimpleDateFormat JavaDoc format =
82         new SimpleDateFormat JavaDoc("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
83
84
85     /**
86      * Descriptive information about this Response implementation.
87      */

88     protected static final String JavaDoc info =
89         "org.apache.coyote.tomcat4.CoyoteResponse/1.0";
90
91
92     /**
93      * The string manager for this package.
94      */

95     protected static StringManager sm =
96         StringManager.getManager(Constants.Package);
97
98
99     // ------------------------------------------------------------- Properties
100

101
102     /**
103      * Associated Catalina connector.
104      */

105     protected Connector connector;
106
107     /**
108      * Return the Connector through which this Request was received.
109      */

110     public Connector getConnector() {
111         return (this.connector);
112     }
113
114     /**
115      * Set the Connector through which this Request was received.
116      *
117      * @param connector The new connector
118      */

119     public void setConnector(Connector connector) {
120         this.connector = connector;
121     }
122
123
124     /**
125      * Coyote response.
126      */

127     protected Response JavaDoc coyoteResponse;
128
129     /**
130      * Set the Coyote response.
131      *
132      * @param coyoteResponse The Coyote response
133      */

134     public void setCoyoteResponse(Response JavaDoc coyoteResponse) {
135         this.coyoteResponse = coyoteResponse;
136         outputBuffer.setResponse(coyoteResponse);
137     }
138
139     /**
140      * Get the Coyote response.
141      */

142     public Response JavaDoc getCoyoteResponse() {
143         return (coyoteResponse);
144     }
145
146
147     /**
148      * The Context within which this Request is being processed.
149      */

150     protected Context context = null;
151
152     /**
153      * Return the Context within which this Request is being processed.
154      */

155     public Context getContext() {
156         return (this.context);
157     }
158
159     /**
160      * Set the Context within which this Request is being processed. This
161      * must be called as soon as the appropriate Context is identified, because
162      * it identifies the value to be returned by <code>getContextPath()</code>,
163      * and thus enables parsing of the request URI.
164      *
165      * @param context The newly associated Context
166      */

167     public void setContext(Context context) {
168         this.context = context;
169     }
170
171
172     /**
173      * The associated output buffer.
174      */

175     protected OutputBuffer outputBuffer = new OutputBuffer();
176
177
178     /**
179      * The associated output stream.
180      */

181     protected CoyoteOutputStream outputStream =
182         new CoyoteOutputStream(outputBuffer);
183
184
185     /**
186      * The associated writer.
187      */

188     protected CoyoteWriter writer = new CoyoteWriter(outputBuffer);
189
190
191     /**
192      * The application commit flag.
193      */

194     protected boolean appCommitted = false;
195
196
197     /**
198      * The included flag.
199      */

200     protected boolean included = false;
201
202
203     /**
204      * The error flag.
205      */

206     protected boolean error = false;
207
208
209     /**
210      * The set of Cookies associated with this Response.
211      */

212     protected ArrayList JavaDoc cookies = new ArrayList JavaDoc();
213
214
215     /**
216      * Using output stream flag.
217      */

218     protected boolean usingOutputStream = false;
219
220
221     /**
222      * Using writer flag.
223      */

224     protected boolean usingWriter = false;
225
226
227     /**
228      * URL encoder.
229      */

230     protected UEncoder urlEncoder = new UEncoder();
231
232
233     /**
234      * Recyclable buffer to hold the redirect URL.
235      */

236     protected CharChunk redirectURLCC = new CharChunk();
237
238
239     // --------------------------------------------------------- Public Methods
240

241
242     /**
243      * Release all object references, and initialize instance variables, in
244      * preparation for reuse of this object.
245      */

246     public void recycle() {
247
248         outputBuffer.recycle();
249         usingOutputStream = false;
250         usingWriter = false;
251         appCommitted = false;
252         included = false;
253         error = false;
254         cookies.clear();
255
256         if (facade != null) {
257             facade.clear();
258             facade = null;
259         }
260
261         writer.recycle();
262
263     }
264
265
266     // ------------------------------------------------------- Response Methods
267

268
269     /**
270      * Return the number of bytes actually written to the output stream.
271      */

272     public int getContentCount() {
273         return outputBuffer.getContentWritten();
274     }
275
276
277     /**
278      * Set the application commit flag.
279      *
280      * @param appCommitted The new application committed flag value
281      */

282     public void setAppCommitted(boolean appCommitted) {
283         this.appCommitted = appCommitted;
284     }
285
286
287     /**
288      * Application commit flag accessor.
289      */

290     public boolean isAppCommitted() {
291         return (this.appCommitted || isCommitted() || isSuspended());
292     }
293
294
295     /**
296      * Return the "processing inside an include" flag.
297      */

298     public boolean getIncluded() {
299         return included;
300     }
301
302
303     /**
304      * Set the "processing inside an include" flag.
305      *
306      * @param included <code>true</code> if we are currently inside a
307      * RequestDispatcher.include(), else <code>false</code>
308      */

309     public void setIncluded(boolean included) {
310         this.included = included;
311     }
312
313
314     /**
315      * Return descriptive information about this Response implementation and
316      * the corresponding version number, in the format
317      * <code>&lt;description&gt;/&lt;version&gt;</code>.
318      */

319     public String JavaDoc getInfo() {
320         return (info);
321     }
322
323
324     /**
325      * The request with which this response is associated.
326      */

327     protected CoyoteRequest request = null;
328
329     /**
330      * Return the Request with which this Response is associated.
331      */

332     public org.apache.catalina.Request getRequest() {
333         return (this.request);
334     }
335
336     /**
337      * Set the Request with which this Response is associated.
338      *
339      * @param request The new associated request
340      */

341     public void setRequest(org.apache.catalina.Request request) {
342         this.request = (CoyoteRequest) request;
343     }
344
345
346     /**
347      * The facade associated with this response.
348      */

349     protected CoyoteResponseFacade facade = null;
350
351     /**
352      * Return the <code>ServletResponse</code> for which this object
353      * is the facade.
354      */

355     public ServletResponse JavaDoc getResponse() {
356         if (facade == null) {
357             facade = new CoyoteResponseFacade(this);
358         }
359         return (facade);
360     }
361
362
363     /**
364      * Return the output stream associated with this Response.
365      */

366     public OutputStream JavaDoc getStream() {
367         return outputStream;
368     }
369
370
371     /**
372      * Set the output stream associated with this Response.
373      *
374      * @param stream The new output stream
375      */

376     public void setStream(OutputStream JavaDoc stream) {
377         // This method is evil
378
}
379
380
381     /**
382      * Set the suspended flag.
383      *
384      * @param suspended The new suspended flag value
385      */

386     public void setSuspended(boolean suspended) {
387         outputBuffer.setSuspended(suspended);
388     }
389
390
391     /**
392      * Suspended flag accessor.
393      */

394     public boolean isSuspended() {
395         return outputBuffer.isSuspended();
396     }
397
398
399     /**
400      * Set the error flag.
401      */

402     public void setError() {
403         error = true;
404     }
405
406
407     /**
408      * Error flag accessor.
409      */

410     public boolean isError() {
411         return error;
412     }
413
414
415     /**
416      * Create and return a ServletOutputStream to write the content
417      * associated with this Response.
418      *
419      * @exception IOException if an input/output error occurs
420      */

421     public ServletOutputStream JavaDoc createOutputStream()
422         throws IOException JavaDoc {
423         // Probably useless
424
return outputStream;
425     }
426
427
428     /**
429      * Perform whatever actions are required to flush and close the output
430      * stream or writer, in a single operation.
431      *
432      * @exception IOException if an input/output error occurs
433      */

434     public void finishResponse()
435         throws IOException JavaDoc {
436         // Writing leftover bytes
437
try {
438             outputBuffer.close();
439         } catch(IOException JavaDoc e) {
440             ;
441         } catch(Throwable JavaDoc t) {
442             t.printStackTrace();
443         }
444     }
445
446
447     /**
448      * Return the content length that was set or calculated for this Response.
449      */

450     public int getContentLength() {
451         return (coyoteResponse.getContentLength());
452     }
453
454
455     /**
456      * Return the content type that was set or calculated for this response,
457      * or <code>null</code> if no content type was set.
458      */

459     public String JavaDoc getContentType() {
460         return (coyoteResponse.getContentType());
461     }
462
463
464     /**
465      * Return a PrintWriter that can be used to render error messages,
466      * regardless of whether a stream or writer has already been acquired.
467      *
468      * @return Writer which can be used for error reports. If the response is
469      * not an error report returned using sendError or triggered by an
470      * unexpected exception thrown during the servlet processing
471      * (and only in that case), null will be returned if the response stream
472      * has already been used.
473      */

474     public PrintWriter JavaDoc getReporter() {
475         if (outputBuffer.isNew()) {
476             return writer;
477         } else {
478             return null;
479         }
480     }
481
482
483     // ------------------------------------------------ ServletResponse Methods
484

485
486     /**
487      * Flush the buffer and commit this response.
488      *
489      * @exception IOException if an input/output error occurs
490      */

491     public void flushBuffer()
492         throws IOException JavaDoc {
493         outputBuffer.flush();
494     }
495
496
497     /**
498      * Return the actual buffer size used for this Response.
499      */

500     public int getBufferSize() {
501         return outputBuffer.getBufferSize();
502     }
503
504
505     /**
506      * Return the character encoding used for this Response.
507      */

508     public String JavaDoc getCharacterEncoding() {
509         return (coyoteResponse.getCharacterEncoding());
510     }
511
512
513     /**
514      * Return the servlet output stream associated with this Response.
515      *
516      * @exception IllegalStateException if <code>getWriter</code> has
517      * already been called for this response
518      * @exception IOException if an input/output error occurs
519      */

520     public ServletOutputStream JavaDoc getOutputStream()
521         throws IOException JavaDoc {
522
523         if (usingWriter)
524             throw new IllegalStateException JavaDoc
525                 (sm.getString("coyoteResponse.getOutputStream.ise"));
526
527         usingOutputStream = true;
528         return outputStream;
529
530     }
531
532
533     /**
534      * Return the Locale assigned to this response.
535      */

536     public Locale JavaDoc getLocale() {
537         return (coyoteResponse.getLocale());
538     }
539
540
541     /**
542      * Return the writer associated with this Response.
543      *
544      * @exception IllegalStateException if <code>getOutputStream</code> has
545      * already been called for this response
546      * @exception IOException if an input/output error occurs
547      */

548     public PrintWriter JavaDoc getWriter()
549         throws IOException JavaDoc {
550
551         if (usingOutputStream)
552             throw new IllegalStateException JavaDoc
553                 (sm.getString("coyoteResponse.getWriter.ise"));
554
555         usingWriter = true;
556         return writer;
557
558     }
559
560
561     /**
562      * Has the output of this response already been committed?
563      */

564     public boolean isCommitted() {
565         return (coyoteResponse.isCommitted());
566     }
567
568
569     /**
570      * Clear any content written to the buffer.
571      *
572      * @exception IllegalStateException if this response has already
573      * been committed
574      */

575     public void reset() {
576
577         if (included)
578             return; // Ignore any call from an included servlet
579

580         coyoteResponse.reset();
581         outputBuffer.reset();
582
583     }
584
585
586     /**
587      * Reset the data buffer but not any status or header information.
588      *
589      * @exception IllegalStateException if the response has already
590      * been committed
591      */

592     public void resetBuffer() {
593
594         if (isCommitted())
595             throw new IllegalStateException JavaDoc
596                 (sm.getString("coyoteResponse.resetBuffer.ise"));
597
598         outputBuffer.reset();
599
600     }
601
602
603     /**
604      * Set the buffer size to be used for this Response.
605      *
606      * @param size The new buffer size
607      *
608      * @exception IllegalStateException if this method is called after
609      * output has been committed for this response
610      */

611     public void setBufferSize(int size) {
612
613         if (isCommitted() || !outputBuffer.isNew())
614             throw new IllegalStateException JavaDoc
615                 (sm.getString("coyoteResponse.setBufferSize.ise"));
616
617         outputBuffer.setBufferSize(size);
618
619     }
620
621
622     /**
623      * Set the content length (in bytes) for this Response.
624      *
625      * @param length The new content length
626      */

627     public void setContentLength(int length) {
628
629         if (isCommitted())
630             return;
631
632         // Ignore any call from an included servlet
633
if (included)
634             return;
635
636         coyoteResponse.setContentLength(length);
637
638     }
639
640
641     /**
642      * Set the content type for this Response.
643      *
644      * @param type The new content type
645      */

646     public void setContentType(String JavaDoc type) {
647
648         if (isCommitted())
649             return;
650
651         // Ignore any call from an included servlet
652
if (included)
653             return;
654
655         coyoteResponse.setContentType(type);
656
657     }
658
659
660     /**
661      * Set the Locale that is appropriate for this response, including
662      * setting the appropriate character encoding.
663      *
664      * @param locale The new locale
665      */

666     public void setLocale(Locale JavaDoc locale) {
667
668         if (isCommitted())
669             return;
670
671         // Ignore any call from an included servlet
672
if (included)
673             return;
674
675         coyoteResponse.setLocale(locale);
676         
677         // Set the specified locale's default encoding of a response
678
CharsetMapper cm = context.getCharsetMapper();
679         String JavaDoc charset = cm.getCharset(locale);
680
681         if (charset != null) {
682             coyoteResponse.setCharacterEncoding(charset);
683         }
684     
685     }
686
687
688     // --------------------------------------------------- HttpResponse Methods
689

690
691     /**
692      * Return an array of all cookies set for this response, or
693      * a zero-length array if no cookies have been set.
694      */

695     public Cookie JavaDoc[] getCookies() {
696         return ((Cookie JavaDoc[]) cookies.toArray(new Cookie JavaDoc[cookies.size()]));
697     }
698
699
700     /**
701      * Return the value for the specified header, or <code>null</code> if this
702      * header has not been set. If more than one value was added for this
703      * name, only the first is returned; use getHeaderValues() to retrieve all
704      * of them.
705      *
706      * @param name Header name to look up
707      */

708     public String JavaDoc getHeader(String JavaDoc name) {
709         return coyoteResponse.getMimeHeaders().getHeader(name);
710     }
711
712
713     /**
714      * Return an array of all the header names set for this response, or
715      * a zero-length array if no headers have been set.
716      */

717     public String JavaDoc[] getHeaderNames() {
718
719         MimeHeaders headers = coyoteResponse.getMimeHeaders();
720         int n = headers.size();
721         String JavaDoc[] result = new String JavaDoc[n];
722         for (int i = 0; i < n; i++) {
723             result[i] = headers.getName(i).toString();
724         }
725         return result;
726
727     }
728
729
730     /**
731      * Return an array of all the header values associated with the
732      * specified header name, or an zero-length array if there are no such
733      * header values.
734      *
735      * @param name Header name to look up
736      */

737     public String JavaDoc[] getHeaderValues(String JavaDoc name) {
738
739         Enumeration JavaDoc headerValues = coyoteResponse.getMimeHeaders().values(name);
740         Vector JavaDoc result = new Vector JavaDoc();
741         while (headerValues.hasMoreElements()) {
742             result.addElement(headerValues.nextElement());
743         }
744         String JavaDoc[] resultArray = new String JavaDoc[result.size()];
745         result.copyInto(resultArray);
746         return resultArray;
747
748     }
749
750
751     /**
752      * Return the error message that was set with <code>sendError()</code>
753      * for this Response.
754      */

755     public String JavaDoc getMessage() {
756         return coyoteResponse.getMessage();
757     }
758
759
760     /**
761      * Return the HTTP status code associated with this Response.
762      */

763     public int getStatus() {
764         return coyoteResponse.getStatus();
765     }
766
767
768     /**
769      * Reset this response, and specify the values for the HTTP status code
770      * and corresponding message.
771      *
772      * @exception IllegalStateException if this response has already been
773      * committed
774      */

775     public void reset(int status, String JavaDoc message) {
776         reset();
777         setStatus(status, message);
778     }
779
780
781     // -------------------------------------------- HttpServletResponse Methods
782

783
784     /**
785      * Add the specified Cookie to those that will be included with
786      * this Response.
787      *
788      * @param cookie Cookie to be added
789      */

790     public void addCookie(Cookie JavaDoc cookie) {
791
792         if (isCommitted())
793             return;
794
795         // Ignore any call from an included servlet
796
if (included)
797             return;
798
799         cookies.add(cookie);
800
801         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
802         ServerCookie.appendCookieValue
803             (sb, cookie.getVersion(), cookie.getName(), cookie.getValue(),
804              cookie.getPath(), cookie.getDomain(), cookie.getComment(),
805              cookie.getMaxAge(), cookie.getSecure());
806         // the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
807
// RFC2965 is not supported by browsers and the Servlet spec
808
// asks for 2109.
809
addHeader("Set-Cookie", sb.toString());
810
811     }
812
813
814     /**
815      * Add the specified date header to the specified value.
816      *
817      * @param name Name of the header to set
818      * @param value Date value to be set
819      */

820     public void addDateHeader(String JavaDoc name, long value) {
821
822         if (isCommitted())
823             return;
824
825         // Ignore any call from an included servlet
826
if (included)
827             return;
828
829         addHeader(name, format.format(new Date JavaDoc(value)));
830
831     }
832
833
834     /**
835      * Add the specified header to the specified value.
836      *
837      * @param name Name of the header to set
838      * @param value Value to be set
839      */

840     public void addHeader(String JavaDoc name, String JavaDoc value) {
841
842         if (isCommitted())
843             return;
844
845         // Ignore any call from an included servlet
846
if (included)
847             return;
848
849         coyoteResponse.addHeader(name, value);
850
851     }
852
853
854     /**
855      * Add the specified integer header to the specified value.
856      *
857      * @param name Name of the header to set
858      * @param value Integer value to be set
859      */

860     public void addIntHeader(String JavaDoc name, int value) {
861
862         if (isCommitted())
863             return;
864
865         // Ignore any call from an included servlet
866
if (included)
867             return;
868
869         addHeader(name, "" + value);
870
871     }
872
873
874     /**
875      * Has the specified header been set already in this response?
876      *
877      * @param name Name of the header to check
878      */

879     public boolean containsHeader(String JavaDoc name) {
880         return coyoteResponse.containsHeader(name);
881     }
882
883
884     /**
885      * Encode the session identifier associated with this response
886      * into the specified redirect URL, if necessary.
887      *
888      * @param url URL to be encoded
889      */

890     public String JavaDoc encodeRedirectURL(String JavaDoc url) {
891
892         if (isEncodeable(toAbsolute(url))) {
893             HttpServletRequest JavaDoc hreq =
894                 (HttpServletRequest JavaDoc) request.getRequest();
895             return (toEncoded(url, hreq.getSession().getId()));
896         } else {
897             return (url);
898         }
899
900     }
901
902
903     /**
904      * Encode the session identifier associated with this response
905      * into the specified redirect URL, if necessary.
906      *
907      * @param url URL to be encoded
908      *
909      * @deprecated As of Version 2.1 of the Java Servlet API, use
910      * <code>encodeRedirectURL()</code> instead.
911      */

912     public String JavaDoc encodeRedirectUrl(String JavaDoc url) {
913         return (encodeRedirectURL(url));
914     }
915
916
917     /**
918      * Encode the session identifier associated with this response
919      * into the specified URL, if necessary.
920      *
921      * @param url URL to be encoded
922      */

923     public String JavaDoc encodeURL(String JavaDoc url) {
924         
925         String JavaDoc absolute = toAbsolute(url);
926         if (isEncodeable(absolute)) {
927             HttpServletRequest JavaDoc hreq =
928                 (HttpServletRequest JavaDoc) request.getRequest();
929             
930             // W3c spec clearly said
931
if (url.equalsIgnoreCase("")){
932                 url = absolute;
933             }
934             return (toEncoded(url, hreq.getSession().getId()));
935         } else {
936             return (url);
937         }
938
939     }
940
941
942     /**
943      * Encode the session identifier associated with this response
944      * into the specified URL, if necessary.
945      *
946      * @param url URL to be encoded
947      *
948      * @deprecated As of Version 2.1 of the Java Servlet API, use
949      * <code>encodeURL()</code> instead.
950      */

951     public String JavaDoc encodeUrl(String JavaDoc url) {
952         return (encodeURL(url));
953     }
954
955
956     /**
957      * Send an acknowledgment of a request.
958      *
959      * @exception IOException if an input/output error occurs
960      */

961     public void sendAcknowledgement()
962         throws IOException JavaDoc {
963
964         if (isCommitted())
965             return;
966
967         // Ignore any call from an included servlet
968
if (included)
969             return;
970
971         coyoteResponse.acknowledge();
972
973     }
974
975
976     /**
977      * Send an error response with the specified status and a
978      * default message.
979      *
980      * @param status HTTP status code to send
981      *
982      * @exception IllegalStateException if this response has
983      * already been committed
984      * @exception IOException if an input/output error occurs
985      */

986     public void sendError(int status)
987         throws IOException JavaDoc {
988         sendError(status, null);
989     }
990
991
992     /**
993      * Send an error response with the specified status and message.
994      *
995      * @param status HTTP status code to send
996      * @param message Corresponding message to send
997      *
998      * @exception IllegalStateException if this response has
999      * already been committed
1000     * @exception IOException if an input/output error occurs
1001     */

1002    public void sendError(int status, String JavaDoc message)
1003        throws IOException JavaDoc {
1004
1005        if (isCommitted())
1006            throw new IllegalStateException JavaDoc
1007                (sm.getString("coyoteResponse.sendError.ise"));
1008
1009        // Ignore any call from an included servlet
1010
if (included)
1011            return;
1012
1013        setError();
1014
1015        coyoteResponse.setStatus(status);
1016        coyoteResponse.setMessage(message);
1017
1018        // Clear any data content that has been buffered
1019
resetBuffer();
1020
1021        // Cause the response to be finished (from the application perspective)
1022
setSuspended(true);
1023
1024    }
1025
1026
1027    /**
1028     * Send a temporary redirect to the specified redirect location URL.
1029     *
1030     * @param location Location URL to redirect to
1031     *
1032     * @exception IllegalStateException if this response has
1033     * already been committed
1034     * @exception IOException if an input/output error occurs
1035     */

1036    public void sendRedirect(String JavaDoc location)
1037        throws IOException JavaDoc {
1038
1039        if (isCommitted())
1040            throw new IllegalStateException JavaDoc
1041                (sm.getString("coyoteResponse.sendRedirect.ise"));
1042
1043        // Ignore any call from an included servlet
1044
if (included)
1045            return;
1046
1047        // Clear any data content that has been buffered
1048
resetBuffer();
1049
1050        // Generate a temporary redirect to the specified location
1051
try {
1052            String JavaDoc absolute = toAbsolute(location);
1053            setStatus(SC_MOVED_TEMPORARILY);
1054            setHeader("Location", absolute);
1055        } catch (IllegalArgumentException JavaDoc e) {
1056            setStatus(SC_NOT_FOUND);
1057        }
1058
1059        // Cause the response to be finished (from the application perspective)
1060
setSuspended(true);
1061
1062    }
1063
1064
1065    /**
1066     * Set the specified date header to the specified value.
1067     *
1068     * @param name Name of the header to set
1069     * @param value Date value to be set
1070     */

1071    public void setDateHeader(String JavaDoc name, long value) {
1072
1073        if (isCommitted())
1074            return;
1075
1076        // Ignore any call from an included servlet
1077
if (included)
1078            return;
1079
1080        setHeader(name, format.format(new Date JavaDoc(value)));
1081
1082    }
1083
1084
1085    /**
1086     * Set the specified header to the specified value.
1087     *
1088     * @param name Name of the header to set
1089     * @param value Value to be set
1090     */

1091    public void setHeader(String JavaDoc name, String JavaDoc value) {
1092
1093        if (isCommitted())
1094            return;
1095
1096        // Ignore any call from an included servlet
1097
if (included)
1098            return;
1099
1100        coyoteResponse.setHeader(name, value);
1101
1102    }
1103
1104
1105    /**
1106     * Set the specified integer header to the specified value.
1107     *
1108     * @param name Name of the header to set
1109     * @param value Integer value to be set
1110     */

1111    public void setIntHeader(String JavaDoc name, int value) {
1112
1113        if (isCommitted())
1114            return;
1115
1116        // Ignore any call from an included servlet
1117
if (included)
1118            return;
1119
1120        setHeader(name, "" + value);
1121
1122    }
1123
1124
1125    /**
1126     * Set the HTTP status to be returned with this response.
1127     *
1128     * @param status The new HTTP status
1129     */

1130    public void setStatus(int status) {
1131        setStatus(status, null);
1132    }
1133
1134
1135    /**
1136     * Set the HTTP status and message to be returned with this response.
1137     *
1138     * @param status The new HTTP status
1139     * @param message The associated text message
1140     *
1141     * @deprecated As of Version 2.1 of the Java Servlet API, this method
1142     * has been deprecated due to the ambiguous meaning of the message
1143     * parameter.
1144     */

1145    public void setStatus(int status, String JavaDoc message) {
1146
1147        if (isCommitted())
1148            return;
1149
1150        // Ignore any call from an included servlet
1151
if (included)
1152            return;
1153
1154        coyoteResponse.setStatus(status);
1155        coyoteResponse.setMessage(message);
1156
1157    }
1158
1159
1160    // ------------------------------------------------------ Protected Methods
1161

1162
1163    /**
1164     * Return <code>true</code> if the specified URL should be encoded with
1165     * a session identifier. This will be true if all of the following
1166     * conditions are met:
1167     * <ul>
1168     * <li>The request we are responding to asked for a valid session
1169     * <li>The requested session ID was not received via a cookie
1170     * <li>The specified URL points back to somewhere within the web
1171     * application that is responding to this request
1172     * </ul>
1173     *
1174     * @param location Absolute URL to be validated
1175     */

1176    protected boolean isEncodeable(String JavaDoc location) {
1177
1178        if (location == null)
1179            return (false);
1180
1181        // Is this an intra-document reference?
1182
if (location.startsWith("#"))
1183            return (false);
1184
1185        // Are we in a valid session that is not using cookies?
1186
HttpServletRequest JavaDoc hreq = (HttpServletRequest JavaDoc) request.getRequest();
1187        HttpSession JavaDoc session = hreq.getSession(false);
1188        if (session == null)
1189            return (false);
1190        if (hreq.isRequestedSessionIdFromCookie())
1191            return (false);
1192
1193        // Is this a valid absolute URL?
1194
URL url = null;
1195        try {
1196            url = new URL(location);
1197        } catch (MalformedURLException JavaDoc e) {
1198            return (false);
1199        }
1200
1201        // Does this URL match down to (and including) the context path?
1202
if (!hreq.getScheme().equalsIgnoreCase(url.getProtocol()))
1203            return (false);
1204        if (!hreq.getServerName().equalsIgnoreCase(url.getHost()))
1205            return (false);
1206        int serverPort = hreq.getServerPort();
1207        if (serverPort == -1) {
1208            if ("https".equals(hreq.getScheme()))
1209                serverPort = 443;
1210            else
1211                serverPort = 80;
1212        }
1213        int urlPort = url.getPort();
1214        if (urlPort == -1) {
1215            if ("https".equals(url.getProtocol()))
1216                urlPort = 443;
1217            else
1218                urlPort = 80;
1219        }
1220        if (serverPort != urlPort)
1221            return (false);
1222
1223        String JavaDoc contextPath = getContext().getPath();
1224        if (contextPath != null) {
1225            String JavaDoc file = url.getFile();
1226            if ((file == null) || !file.startsWith(contextPath))
1227                return (false);
1228            if( file.indexOf(";jsessionid=" + session.getId()) >= 0 )
1229                return (false);
1230        }
1231
1232        // This URL belongs to our web application, so it is encodeable
1233
return (true);
1234
1235    }
1236
1237
1238    /**
1239     * Convert (if necessary) and return the absolute URL that represents the
1240     * resource referenced by this possibly relative URL. If this URL is
1241     * already absolute, return it unchanged.
1242     *
1243     * @param location URL to be (possibly) converted and then returned
1244     *
1245     * @exception IllegalArgumentException if a MalformedURLException is
1246     * thrown when converting the relative URL to an absolute one
1247     */

1248    private String JavaDoc toAbsolute(String JavaDoc location) {
1249
1250        if (location == null)
1251            return (location);
1252
1253        // Construct a new absolute URL if possible (cribbed from
1254
// the DefaultErrorPage servlet)
1255
URL url = null;
1256        try {
1257            url = new URL(location);
1258
1259            if (url.getAuthority() == null)
1260                return location;
1261
1262        } catch (MalformedURLException JavaDoc e1) {
1263            HttpServletRequest JavaDoc hreq =
1264                (HttpServletRequest JavaDoc) request.getRequest();
1265            String JavaDoc requrl = request.getRequestURL().toString();
1266            try {
1267                url = new URL(new URL(requrl), location);
1268            } catch (MalformedURLException JavaDoc e2) {
1269                throw new IllegalArgumentException JavaDoc(location);
1270            }
1271        }
1272        return (url.toExternalForm());
1273    }
1274
1275
1276    /**
1277     * Return the specified URL with the specified session identifier
1278     * suitably encoded.
1279     *
1280     * @param url URL to be encoded with the session id
1281     * @param sessionId Session id to be included in the encoded URL
1282     */

1283    private String JavaDoc toEncoded(String JavaDoc url, String JavaDoc sessionId) {
1284
1285        if ((url == null) || (sessionId == null))
1286            return (url);
1287
1288        String JavaDoc path = url;
1289        String JavaDoc query = "";
1290        String JavaDoc anchor = "";
1291        int question = url.indexOf('?');
1292        if (question >= 0) {
1293            path = url.substring(0, question);
1294            query = url.substring(question);
1295        }
1296        int pound = path.indexOf('#');
1297        if (pound >= 0) {
1298            anchor = path.substring(pound);
1299            path = path.substring(0, pound);
1300        }
1301        StringBuffer JavaDoc sb = new StringBuffer JavaDoc(path);
1302        if( sb.length() > 0 ) { // jsessionid can't be first.
1303
sb.append(";jsessionid=");
1304            sb.append(sessionId);
1305        }
1306        sb.append(anchor);
1307        sb.append(query);
1308        return (sb.toString());
1309
1310    }
1311
1312
1313}
1314
Popular Tags