KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > HttpResponse


1 // ========================================================================
2
// $Id: HttpResponse.java,v 1.61 2005/10/26 08:10:14 gregwilkins Exp $
3
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http;
17
18 import java.io.IOException JavaDoc;
19 import java.io.Writer JavaDoc;
20 import java.lang.reflect.Field JavaDoc;
21 import java.lang.reflect.Modifier JavaDoc;
22 import java.util.HashMap JavaDoc;
23
24 import javax.servlet.http.Cookie JavaDoc;
25
26 import org.apache.commons.logging.Log;
27 import org.mortbay.log.LogFactory;
28 import org.mortbay.util.LogSupport;
29 import org.mortbay.util.StringUtil;
30 import org.mortbay.util.TypeUtil;
31 import org.mortbay.util.UrlEncoded;
32
33
34 /* ------------------------------------------------------------ */
35 /** HTTP Response.
36  * This class manages the headers, trailers and content streams
37  * of a HTTP response. It can be used for receiving or generating
38  * requests.
39  *
40  * This class is not synchronized. It should be explicitly
41  * synchronized if it is used by multiple threads.
42  *
43  * @see HttpRequest
44  * @version $Id: HttpResponse.java,v 1.61 2005/10/26 08:10:14 gregwilkins Exp $
45  * @author Greg Wilkins (gregw)
46  */

47 public class HttpResponse extends HttpMessage
48 {
49     private static Log log = LogFactory.getLog(HttpResponse.class);
50  
51       public final static int
52           __100_Continue = 100,
53           __101_Switching_Protocols = 101,
54           __102_Processing = 102,
55           __200_OK = 200,
56           __201_Created = 201,
57           __202_Accepted = 202,
58           __203_Non_Authoritative_Information = 203,
59           __204_No_Content = 204,
60           __205_Reset_Content = 205,
61           __206_Partial_Content = 206,
62           __207_Multi_Status = 207,
63           __300_Multiple_Choices = 300,
64           __301_Moved_Permanently = 301,
65           __302_Moved_Temporarily = 302,
66           __302_Found = 302,
67           __303_See_Other = 303,
68           __304_Not_Modified = 304,
69           __305_Use_Proxy = 305,
70           __400_Bad_Request = 400,
71           __401_Unauthorized = 401,
72           __402_Payment_Required = 402,
73           __403_Forbidden = 403,
74           __404_Not_Found = 404,
75           __405_Method_Not_Allowed = 405,
76           __406_Not_Acceptable = 406,
77           __407_Proxy_Authentication_Required = 407,
78           __408_Request_Timeout = 408,
79           __409_Conflict = 409,
80           __410_Gone = 410,
81           __411_Length_Required = 411,
82           __412_Precondition_Failed = 412,
83           __413_Request_Entity_Too_Large = 413,
84           __414_Request_URI_Too_Large = 414,
85           __415_Unsupported_Media_Type = 415,
86           __416_Requested_Range_Not_Satisfiable = 416,
87           __417_Expectation_Failed = 417,
88           __422_Unprocessable_Entity = 422,
89           __423_Locked = 423,
90           __424_Failed_Dependency = 424,
91           __500_Internal_Server_Error = 500,
92           __501_Not_Implemented = 501,
93           __502_Bad_Gateway = 502,
94           __503_Service_Unavailable = 503,
95           __504_Gateway_Timeout = 504,
96           __505_HTTP_Version_Not_Supported = 505,
97           __507_Insufficient_Storage = 507;
98
99           
100     /* -------------------------------------------------------------- */
101     public final static HashMap JavaDoc __statusMsg = new HashMap JavaDoc();
102     static
103     {
104         // Build error code map using reflection
105
try
106         {
107             Field JavaDoc[] fields = org.mortbay.http.HttpResponse.class
108                 .getDeclaredFields();
109             for (int f=fields.length; f-->0 ;)
110             {
111                 int m = fields[f].getModifiers();
112                 String JavaDoc name=fields[f].getName();
113                 if (Modifier.isFinal(m) &&
114                     Modifier.isStatic(m) &&
115                     fields[f].getType().equals(Integer.TYPE) &&
116                     name.startsWith("__") &&
117                     Character.isDigit(name.charAt(2)))
118                 {
119                     String JavaDoc message = name.substring(6);
120                     message = message.replace('_',' ');
121                     __statusMsg.put(fields[f].get(null),message);
122                 }
123             }
124         }
125         catch (Exception JavaDoc e)
126         {
127             log.warn(LogSupport.EXCEPTION,e);
128         }
129     }
130     
131     /* ------------------------------------------------------------ */
132     static byte[] __Continue;
133     static
134     {
135         try{
136             __Continue="HTTP/1.1 100 Continue\015\012\015\012".getBytes(StringUtil.__ISO_8859_1);
137         }
138         catch (Exception JavaDoc e){log.fatal(e); System.exit(1);}
139     }
140     
141     /* -------------------------------------------------------------- */
142     private int _status= __200_OK;
143     private String JavaDoc _reason;
144     private HttpContext _httpContext;
145     
146     /* ------------------------------------------------------------ */
147     /** Constructor.
148      */

149     public HttpResponse()
150     {
151         _version=__HTTP_1_1;
152         _dotVersion=1;
153         _state=__MSG_EDITABLE;
154     }
155     
156     /* ------------------------------------------------------------ */
157     /** Constructor.
158      * @param connection
159      */

160     public HttpResponse(HttpConnection connection)
161     {
162         super(connection);
163         _version=__HTTP_1_1;
164         _dotVersion=1;
165         _state=__MSG_EDITABLE;
166     }
167
168     /* ------------------------------------------------------------ */
169     /** Get the HttpContext handling this reponse.
170      * @return The HttpContext that is handling this request.
171      */

172     public HttpContext getHttpContext()
173     {
174         return _httpContext;
175     }
176     
177     /* ------------------------------------------------------------ */
178     /** Set the HttpContext handling this reponse.
179      * @param context The HttpContext handling this reponse.
180      */

181     public void setHttpContext(HttpContext context)
182     {
183         _httpContext=context;
184     }
185     
186     /* ------------------------------------------------------------ */
187     /**
188      * @return true if the message has been modified.
189      */

190     public boolean isDirty()
191     {
192         return _status!=__200_OK || super.isDirty();
193     }
194
195     /* ------------------------------------------------------------ */
196     /** Reset the response.
197      * Clears any data that exists in the buffer as well as the status
198      * code. If the response has been committed, this method throws an
199      * <code>IllegalStateException</code>.
200      *
201      * @exception IllegalStateException if the response has already been
202      * committed
203      */

204     public void reset()
205     {
206         if (isCommitted())
207             throw new IllegalStateException JavaDoc("Already committed");
208
209         try
210         {
211             ((HttpOutputStream)getOutputStream()).resetBuffer();
212             _status= __200_OK;
213             _reason=null;
214             super.reset();
215
216             setField(HttpFields.__Date,getRequest().getTimeStampStr());
217             if (!Version.isParanoid())
218                 setField(HttpFields.__Server,Version.getDetail());
219         }
220         catch(Exception JavaDoc e)
221         {
222             log.warn(LogSupport.EXCEPTION,e);
223             throw new IllegalStateException JavaDoc(e.toString());
224         }
225     }
226     
227     
228     /* ------------------------------------------------------------ */
229     /**
230      * @deprecated use getHttpRequest()
231      */

232     public HttpRequest getRequest()
233     {
234         return getHttpRequest();
235     }
236     
237     /* ------------------------------------------------------------ */
238     /** Get the HTTP Request.
239      * Get the HTTP Request associated with this response.
240      * @return associated request
241      */

242     public HttpRequest getHttpRequest()
243     {
244         if (_connection==null)
245             return null;
246         return _connection.getRequest();
247     }
248     
249     /* ------------------------------------------------------------ */
250     /** Not Implemented.
251      * @param in
252      * @exception IOException
253      */

254     public void readHeader(HttpInputStream in)
255         throws IOException JavaDoc
256     {
257         _state=__MSG_BAD;
258         log.warn(LogSupport.NOT_IMPLEMENTED);
259     }
260     
261     
262     /* -------------------------------------------------------------- */
263     public void writeHeader(Writer JavaDoc writer)
264         throws IOException JavaDoc
265     {
266         if (_state!=__MSG_EDITABLE)
267             throw new IllegalStateException JavaDoc(__state[_state]+
268                                             " is not EDITABLE");
269         if (_header==null)
270             throw new IllegalStateException JavaDoc("Response is destroyed");
271
272         if (getHttpRequest().getDotVersion()>=0)
273         {
274             _state=__MSG_BAD;
275             writer.write(_version);
276             writer.write(' ');
277             writer.write('0'+((_status/100)%10));
278             writer.write('0'+((_status/10)%10));
279             writer.write('0'+(_status%10));
280             writer.write(' ');
281             writer.write(getReason());
282             writer.write(HttpFields.__CRLF);
283             _header.write(writer);
284         }
285         _state=__MSG_SENDING;
286     }
287     
288     /* -------------------------------------------------------------- */
289     public int getStatus()
290     {
291         return _status;
292     }
293     
294     /* -------------------------------------------------------------- */
295     public void setStatus(int status)
296     {
297         _status=status;
298     }
299     
300     /* -------------------------------------------------------------- */
301     public String JavaDoc getReason()
302     {
303         if (_reason!=null)
304             return _reason;
305         _reason=(String JavaDoc)__statusMsg.get(TypeUtil.newInteger(_status));
306         if (_reason==null)
307             _reason="unknown";
308         return _reason;
309     }
310     
311     /* -------------------------------------------------------------- */
312     public void setReason(String JavaDoc reason)
313     {
314         _reason=reason;
315     }
316     
317
318     /* -------------------------------------------------------------- */
319     public void setStatus(int code,String JavaDoc message)
320     {
321         setStatus(code);
322         Integer JavaDoc code_integer=TypeUtil.newInteger(code);
323         if (message == null)
324         {
325             message = (String JavaDoc)__statusMsg.get(code_integer);
326             if (message==null)
327                 message=""+code;
328             setReason(message);
329         }
330         else
331             setReason(UrlEncoded.encodeString(message));
332     }
333       
334     
335     /* ------------------------------------------------------------- */
336     /** Send Error Response.
337      */

338     public void sendError(int code,String JavaDoc message)
339         throws IOException JavaDoc
340     {
341         setStatus(code,message);
342         
343         // Generate normal error page.
344
HttpRequest request=getHttpRequest();
345         
346         // If we are allowed to have a body
347
if (code!=__204_No_Content &&
348             code!=__304_Not_Modified &&
349             code!=__206_Partial_Content &&
350             code>=200)
351         {
352             if (getHttpContext()!=null)
353             {
354                 Object JavaDoc o=
355                     getHttpContext().getAttribute(HttpContext.__ErrorHandler);
356                 if (o!=null && o instanceof HttpHandler)
357                     ((HttpHandler)o).handle(request.getPath(), null, request, this);
358             }
359         }
360         else if (code!=__206_Partial_Content)
361         {
362             _header.remove(HttpFields.__ContentType);
363             _header.remove(HttpFields.__ContentLength);
364             _characterEncoding=null;
365             _mimeType=null;
366         }
367         
368         commit();
369     }
370     
371     
372     
373     /* ------------------------------------------------------------- */
374     /**
375      * Sends an error response to the client using the specified status
376      * code and no default message.
377      * @param code the status code
378      * @exception IOException If an I/O error has occurred.
379      */

380     public void sendError(int code)
381         throws IOException JavaDoc
382     {
383         sendError(code,null);
384     }
385     
386     /* ------------------------------------------------------------- */
387     /**
388      * Sends a redirect response to the client using the specified redirect
389      * location URL.
390      * @param location the redirect location URL
391      * @exception IOException If an I/O error has occurred.
392      */

393     public void sendRedirect(String JavaDoc location)
394         throws IOException JavaDoc
395     {
396         if (isCommitted())
397             throw new IllegalStateException JavaDoc("Commited");
398         _header.put(HttpFields.__Location,location);
399         setStatus(__302_Moved_Temporarily);
400         commit();
401     }
402
403     /* -------------------------------------------------------------- */
404     /** Add a Set-Cookie field.
405      */

406     public void addSetCookie(String JavaDoc name,
407                              String JavaDoc value)
408     {
409         _header.addSetCookie(new Cookie JavaDoc(name,value));
410     }
411     
412     /* -------------------------------------------------------------- */
413     /** Add a Set-Cookie field.
414      */

415     public void addSetCookie(Cookie JavaDoc cookie)
416     {
417         _header.addSetCookie(cookie);
418     }
419     
420
421     /* ------------------------------------------------------------ */
422     public void completing()
423     {
424         getHttpConnection().completing();
425     }
426     
427     /* ------------------------------------------------------------ */
428     /**
429      * @exception IOException
430      */

431     public void commit()
432         throws IOException JavaDoc
433     {
434         if (!isCommitted())
435             getOutputStream().flush();
436         getHttpConnection().commit();
437     }
438     
439     /* ------------------------------------------------------------ */
440     /** Recycle the response.
441      */

442     void recycle(HttpConnection connection)
443     {
444         super.recycle(connection);
445         _status=__200_OK;
446         _reason=null;
447         _httpContext=null;
448     }
449     
450     /* ------------------------------------------------------------ */
451     /** Destroy the response.
452      * Help the garbage collector by null everything that we can.
453      */

454     public void destroy()
455     {
456         _reason=null;
457         super.destroy();
458     }
459
460 }
461
462
463
464
Popular Tags