KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > orb > http > httpserver > ServeConnection


1 /*
2  * JacORB - a free Java ORB
3  *
4  * Copyright (C) 1999-2004 Gerald Brose
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */

21 package org.jacorb.orb.http.httpserver;
22
23 import java.io.*;
24 import java.net.*;
25 import java.util.*;
26 import java.text.*;
27
28 public class ServeConnection
29     {
30
31     private Socket socket;
32
33     private ServeInputStream in;
34     private ServeOutputStream out;
35
36     private Vector cookies = new Vector(); // !!!
37

38
39     public static final int SC_CONTINUE = 100;
40     public static final int SC_SWITCHING_PROTOCOLS = 101;
41     public static final int SC_OK = 200;
42     public static final int SC_CREATED = 201;
43     public static final int SC_ACCEPTED = 202;
44     public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
45     public static final int SC_NO_CONTENT = 204;
46     public static final int SC_RESET_CONTENT = 205;
47     public static final int SC_PARTIAL_CONTENT = 206;
48     public static final int SC_MULTIPLE_CHOICES = 300;
49     public static final int SC_MOVED_PERMANENTLY = 301;
50     public static final int SC_MOVED_TEMPORARILY = 302;
51     public static final int SC_SEE_OTHER = 303;
52     public static final int SC_NOT_MODIFIED = 304;
53     public static final int SC_USE_PROXY = 305;
54     public static final int SC_BAD_REQUEST = 400;
55     public static final int SC_UNAUTHORIZED = 401;
56     public static final int SC_PAYMENT_REQUIRED = 402;
57     public static final int SC_FORBIDDEN = 403;
58     public static final int SC_NOT_FOUND = 404;
59     public static final int SC_METHOD_NOT_ALLOWED = 405;
60     public static final int SC_NOT_ACCEPTABLE = 406;
61     public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
62     public static final int SC_REQUEST_TIMEOUT = 408;
63     public static final int SC_CONFLICT = 409;
64     public static final int SC_GONE = 410;
65     public static final int SC_LENGTH_REQUIRED = 411;
66     public static final int SC_PRECONDITION_FAILED = 412;
67     public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;
68     public static final int SC_REQUEST_URI_TOO_LONG = 414;
69     public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
70     public static final int SC_INTERNAL_SERVER_ERROR = 500;
71     public static final int SC_NOT_IMPLEMENTED = 501;
72     public static final int SC_BAD_GATEWAY = 502;
73     public static final int SC_SERVICE_UNAVAILABLE = 503;
74     public static final int SC_GATEWAY_TIMEOUT = 504;
75     public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
76
77
78
79     /// Constructor.
80
public ServeConnection( Socket socket,java.io.InputStream JavaDoc _in)
81     {
82     // Save arguments.
83
this.socket = socket;
84     try
85         {
86         // Get the streams.
87
in = new ServeInputStream(_in);
88         out = new ServeOutputStream( socket.getOutputStream(), this );
89         }
90     catch ( IOException e )
91         {
92         problem( "Getting streams: " + e.getMessage(), SC_BAD_REQUEST );
93         }
94
95     parseRequest();
96
97     
98     //closing must be done by BA
99
//try
100
// {
101
// socket.close();
102
// }
103
//catch ( IOException e ) { /* ignore */ }
104

105     }
106
107
108     // Methods from Runnable.
109

110     private String JavaDoc reqMethod = null;
111     private String JavaDoc reqUriPath = null;
112     private String JavaDoc reqProtocol = null;
113     private boolean oneOne; // HTTP/1.1 or better
114
private boolean reqMime;
115     String JavaDoc reqQuery = null;
116     private Vector reqHeaderNames = new Vector();
117     private Vector reqHeaderValues = new Vector();
118
119
120     public void close(){
121     
122     try
123         {
124         socket.close();
125         }
126     catch ( IOException e ) { /* ignore */ }
127     }
128
129     private void parseRequest()
130     {
131     byte[] lineBytes = new byte[4096];
132     int len;
133     String JavaDoc line;
134
135     try
136         {
137         // Read the first line of the request.
138
len = in.readLine( lineBytes, 0, lineBytes.length );
139         if ( len == -1 || len == 0 )
140         {
141         problem( "Empty request", SC_BAD_REQUEST );
142         return;
143         }
144         line = new String JavaDoc( lineBytes, 0, len );
145         String JavaDoc[] tokens = splitStr( line );
146         switch ( tokens.length )
147         {
148         case 2:
149         // Two tokens means the protocol is HTTP/0.9.
150
reqProtocol = "HTTP/0.9";
151         oneOne = false;
152         reqMime = false;
153         break;
154         case 3:
155         reqProtocol = tokens[2];
156         oneOne = ! reqProtocol.toUpperCase().equals( "HTTP/1.0" );
157         reqMime = true;
158         // Read the rest of the lines.
159
while ( true )
160             {
161             len = in.readLine( lineBytes, 0, lineBytes.length );
162             if ( len == -1 || len == 0 )
163             break;
164             line = new String JavaDoc( lineBytes, 0, len );
165             int colonBlank = line.indexOf( ": " );
166             if ( colonBlank != -1 )
167             {
168             String JavaDoc name = line.substring( 0, colonBlank );
169             String JavaDoc value = line.substring( colonBlank + 2 );
170             reqHeaderNames.addElement( name.toLowerCase() );
171             reqHeaderValues.addElement( value );
172             }
173             }
174         break;
175         default:
176         problem( "Malformed request line", SC_BAD_REQUEST );
177         return;
178         }
179         reqMethod = tokens[0];
180         reqUriPath = tokens[1];
181
182         // Check Host: header in HTTP/1.1 requests.
183
if ( oneOne )
184         {
185         String JavaDoc host = getHeader( "host" );
186         if ( host == null )
187             {
188             problem(
189             "Host header missing on HTTP/1.1 request",
190             SC_BAD_REQUEST );
191             return;
192             }
193         // !!!
194
}
195
196         // Split off query string, if any.
197
int qmark = reqUriPath.indexOf( '?' );
198         if ( qmark != -1 )
199         {
200         reqQuery = reqUriPath.substring( qmark + 1 );
201         reqUriPath = reqUriPath.substring( 0, qmark );
202         }
203
204         // Decode %-sequences.
205
reqUriPath = decode( reqUriPath );
206
207          //you can handle the request now
208
}catch ( Exception JavaDoc e )
209         {
210         problem( "Reading request: " + e.getMessage(), SC_BAD_REQUEST );
211         }
212     }
213
214     public void answerRequest(byte[] answer)
215     {
216     // Set default response fields.
217
setStatus( SC_OK );
218     setDateHeader( "Date", System.currentTimeMillis() );
219     setHeader( "Server", "JacORB builtin HTTPServer");
220     setHeader( "Connection", "close" );
221     try
222         {
223         out.write(answer,0,answer.length);
224         out.flush();
225         out.close();
226         }
227     catch ( Exception JavaDoc e )
228         {
229         problem(
230         "unexpected problem running servlet: " + e.toString(),
231         SC_INTERNAL_SERVER_ERROR );
232         }
233     }
234
235     private void problem( String JavaDoc logMessage, int resCode )
236     {
237     try
238         {
239         sendError( resCode );
240         }
241     catch ( IOException e ) { /* ignore */ }
242     }
243
244     private String JavaDoc decode( String JavaDoc str )
245     {
246     StringBuffer JavaDoc result = new StringBuffer JavaDoc();
247     int l = str.length();
248     for ( int i = 0; i < l; ++i )
249         {
250         char c = str.charAt( i );
251         if ( c == '%' && i + 2 < l )
252         {
253         char c1 = str.charAt( i + 1 );
254         char c2 = str.charAt( i + 2 );
255         if ( isHexit( c1 ) && isHexit( c2 ) )
256             {
257             result.append( (char) ( hexit( c1 ) * 16 + hexit( c2 ) ) );
258             i += 2;
259             }
260         else
261             result.append( c );
262         }
263         else
264         result.append( c );
265         }
266     return result.toString();
267     }
268
269     private boolean isHexit( char c )
270     {
271     String JavaDoc legalChars = "0123456789abcdefABCDEF";
272     return ( legalChars.indexOf( c ) != -1 );
273     }
274
275     private int hexit( char c )
276     {
277     if ( c >= '0' && c <= '9' )
278         return c - '0';
279     if ( c >= 'a' && c <= 'f' )
280         return c - 'a' + 10;
281     if ( c >= 'A' && c <= 'F' )
282         return c - 'A' + 10;
283     return 0; // shouldn't happen, we're guarded by isHexit()
284
}
285
286
287     // Methods from ServletRequest.
288

289     /// Returns the size of the request entity data, or -1 if not known.
290
// Same as the CGI variable CONTENT_LENGTH.
291
public int getContentLength()
292     {
293     return getIntHeader( "content-length", -1 );
294     }
295
296     /// Returns the MIME type of the request entity data, or null if
297
// not known.
298
// Same as the CGI variable CONTENT_TYPE.
299
public String JavaDoc getContentType()
300     {
301     return getHeader( "content-type" );
302     }
303
304     /// Returns the protocol and version of the request as a string of
305
// the form <protocol>/<major version>.<minor version>.
306
// Same as the CGI variable SERVER_PROTOCOL.
307
public String JavaDoc getProtocol()
308     {
309     return reqProtocol;
310     }
311
312     /// Returns the scheme of the URL used in this request, for example
313
// "http", "https", or "ftp". Different schemes have different rules
314
// for constructing URLs, as noted in RFC 1738. The URL used to create
315
// a request may be reconstructed using this scheme, the server name
316
// and port, and additional information such as URIs.
317
public String JavaDoc getScheme()
318     {
319     return "http";
320     }
321
322     /// Returns the host name of the server as used in the <host> part of
323
// the request URI.
324
// Same as the CGI variable SERVER_NAME.
325
public String JavaDoc getServerName()
326     {
327     try
328         {
329         return InetAddress.getLocalHost().getHostName();
330         }
331     catch ( UnknownHostException e )
332         {
333         return null;
334         }
335     }
336
337     /// Returns the port number on which this request was received as used in
338
// the <port> part of the request URI.
339
// Same as the CGI variable SERVER_PORT.
340
public int getServerPort()
341     {
342     return socket.getLocalPort();
343     }
344
345     /// Returns the IP address of the agent that sent the request.
346
// Same as the CGI variable REMOTE_ADDR.
347
public String JavaDoc getRemoteAddr()
348     {
349     return socket.getInetAddress().toString();
350     }
351
352     /// Returns the fully qualified host name of the agent that sent the
353
// request.
354
// Same as the CGI variable REMOTE_HOST.
355
public String JavaDoc getRemoteHost()
356     {
357     return socket.getInetAddress().getHostName();
358     }
359
360     /// Applies alias rules to the specified virtual path and returns the
361
// corresponding real path, or null if the translation can not be
362
// performed for any reason. For example, an HTTP servlet would
363
// resolve the path using the virtual docroot, if virtual hosting is
364
// enabled, and with the default docroot otherwise. Calling this
365
// method with the string "/" as an argument returns the document root.
366
public String JavaDoc getRealPath( String JavaDoc path )
367     {
368     return "/"; //serve.getRealPath( path );
369
}
370
371     /// Returns an input stream for reading request data.
372
// @exception IllegalStateException if getReader has already been called
373
// @exception IOException on other I/O-related errors
374
public ServeInputStream getInputStream() throws IOException
375     {
376     return in;
377     }
378
379     /// Returns a buffered reader for reading request data.
380
// @exception UnsupportedEncodingException if the character set encoding isn't supported
381
// @exception IllegalStateException if getInputStream has already been called
382
// @exception IOException on other I/O-related errors
383
public BufferedReader getReader()
384     {
385     // !!!
386
return null;
387     }
388
389     Vector queryNames = null;
390     Vector queryValues = null;
391
392     /// Returns the parameter names for this request.
393
public Enumeration getParameterNames()
394     {
395     if ( queryNames == null )
396         {
397         queryNames = new Vector();
398         queryValues = new Vector();
399         String JavaDoc qs = getQueryString();
400         if ( qs != null )
401         {
402         Enumeration en = new StringTokenizer( qs, "&" );
403         while ( en.hasMoreElements() )
404             {
405             String JavaDoc nv = (String JavaDoc) en.nextElement();
406             int eq = nv.indexOf( '=' );
407             String JavaDoc name, value;
408             if ( eq == -1 )
409             {
410             name = nv;
411             value = "";
412             }
413             else
414             {
415             name = nv.substring( 0, eq );
416             value = nv.substring( eq + 1 );
417             }
418             queryNames.addElement( name );
419             queryValues.addElement( value );
420             }
421         }
422         }
423     return queryNames.elements();
424     }
425
426     /// Returns the value of the specified query string parameter, or null
427
// if not found.
428
// @param name the parameter name
429
public String JavaDoc getParameter( String JavaDoc name )
430     {
431     Enumeration en = getParameterNames();
432     int i = queryNames.indexOf( name );
433     if ( i == -1 )
434         return null;
435     else
436         return (String JavaDoc) queryValues.elementAt( i );
437     }
438
439     /// Returns the values of the specified parameter for the request as an
440
// array of strings, or null if the named parameter does not exist.
441
public String JavaDoc[] getParameterValues( String JavaDoc name )
442     {
443     Vector v = new Vector();
444     Enumeration en = getParameterNames();
445     for ( int i = 0; i < queryNames.size(); ++i )
446         {
447         String JavaDoc n = (String JavaDoc) queryNames.elementAt( i );
448         if ( name.equals( n ) )
449         v.addElement( queryValues.elementAt( i ) );
450         }
451     if ( v.size() == 0 )
452         return null;
453     String JavaDoc[] vArray = new String JavaDoc[v.size()];
454     v.copyInto( vArray );
455     return vArray;
456     }
457     
458     /// Returns the value of the named attribute of the request, or null if
459
// the attribute does not exist. This method allows access to request
460
// information not already provided by the other methods in this interface.
461
public Object JavaDoc getAttribute( String JavaDoc name )
462     {
463     // This server does not implement attributes.
464
return null;
465     }
466
467
468     // Methods from HttpServletRequest.
469

470     /// Gets the array of cookies found in this request.
471
//public Cookie[] getCookies()
472
// {
473
// Cookie[] cookieArray = new Cookie[cookies.size()];
474
// cookies.copyInto( cookieArray );
475
// return cookieArray;
476
// }
477

478     /// Returns the method with which the request was made. This can be "GET",
479
// "HEAD", "POST", or an extension method.
480
// Same as the CGI variable REQUEST_METHOD.
481
public String JavaDoc getMethod()
482     {
483     return reqMethod;
484     }
485
486     /// Returns the full request URI.
487
public String JavaDoc getRequestURI()
488     {
489     String JavaDoc portPart = "";
490     int port = getServerPort();
491     if ( port != 80 )
492         portPart = ":" + port;
493     String JavaDoc queryPart = "";
494     String JavaDoc queryString = getQueryString();
495     if ( queryString != null && queryString.length() > 0 )
496         queryPart = "?" + queryString;
497     return "http://" + getServerName() + portPart + reqUriPath + queryPart;
498     }
499
500     /// Returns the part of the request URI that referred to the servlet being
501
// invoked.
502
// Analogous to the CGI variable SCRIPT_NAME.
503
public String JavaDoc getServletPath()
504     {
505     // In this server, the entire path is regexp-matched against the
506
// servlet pattern, so there's no good way to distinguish which
507
// part refers to the servlet.
508
return reqUriPath;
509     }
510
511     /// Returns optional extra path information following the servlet path, but
512
// immediately preceding the query string. Returns null if not specified.
513
// Same as the CGI variable PATH_INFO.
514
public String JavaDoc getPathInfo()
515     {
516     // In this server, the entire path is regexp-matched against the
517
// servlet pattern, so there's no good way to distinguish which
518
// part refers to the servlet.
519
return null;
520     }
521
522     /// Returns extra path information translated to a real path. Returns
523
// null if no extra path information was specified.
524
// Same as the CGI variable PATH_TRANSLATED.
525
public String JavaDoc getPathTranslated()
526     {
527     // In this server, the entire path is regexp-matched against the
528
// servlet pattern, so there's no good way to distinguish which
529
// part refers to the servlet.
530
return null;
531     }
532
533     /// Returns the query string part of the servlet URI, or null if not known.
534
// Same as the CGI variable QUERY_STRING.
535
public String JavaDoc getQueryString()
536     {
537     return reqQuery;
538     }
539
540     /// Returns the name of the user making this request, or null if not known.
541
// Same as the CGI variable REMOTE_USER.
542
public String JavaDoc getRemoteUser()
543     {
544     // This server does not support authentication, so even if a username
545
// is supplied in the headers we don't want to look at it.
546
return null;
547     }
548
549     /// Returns the authentication scheme of the request, or null if none.
550
// Same as the CGI variable AUTH_TYPE.
551
public String JavaDoc getAuthType()
552     {
553     // This server does not support authentication.
554
return null;
555     }
556
557     /// Returns the value of a header field, or null if not known.
558
// Same as the information passed in the CGI variabled HTTP_*.
559
// @param name the header field name
560
public String JavaDoc getHeader( String JavaDoc name )
561     {
562     int i = reqHeaderNames.indexOf( name.toLowerCase() );
563     if ( i == -1 )
564         return null;
565     return (String JavaDoc) reqHeaderValues.elementAt( i );
566     }
567
568     /// Returns the value of an integer header field.
569
// @param name the header field name
570
// @param def the integer value to return if header not found or invalid
571
public int getIntHeader( String JavaDoc name, int def )
572     {
573     String JavaDoc val = getHeader( name );
574     if ( val == null )
575         return def;
576     try
577         {
578         return Integer.parseInt( val );
579         }
580     catch ( Exception JavaDoc e )
581         {
582         return def;
583         }
584     }
585
586     /// Returns the value of a long header field.
587
// @param name the header field name
588
// @param def the long value to return if header not found or invalid
589
public long getLongHeader( String JavaDoc name, long def )
590     {
591     String JavaDoc val = getHeader( name );
592     if ( val == null )
593         return def;
594     try
595         {
596         return Long.parseLong( val );
597         }
598     catch ( Exception JavaDoc e )
599         {
600         return def;
601         }
602     }
603
604     /// Returns the value of a date header field.
605
// @param name the header field name
606
// @param def the date value to return if header not found or invalid
607
public long getDateHeader( String JavaDoc name, long def )
608     {
609     String JavaDoc val = getHeader( name );
610     if ( val == null )
611         return def;
612     try
613         {
614         return DateFormat.getDateInstance().parse( val ).getTime();
615         }
616     catch ( Exception JavaDoc e )
617         {
618         return def;
619         }
620     }
621
622     /// Returns an Enumeration of the header names.
623
public Enumeration getHeaderNames()
624     {
625     return reqHeaderNames.elements();
626     }
627
628     // Session stuff. Not implemented, but the API is here for compatibility.
629

630     /// Gets the current valid session associated with this request, if
631
// create is false or, if necessary, creates a new session for the
632
// request, if create is true.
633
// <P>
634
// Note: to ensure the session is properly maintained, the servlet
635
// developer must call this method (at least once) before any output
636
// is written to the response.
637
// <P>
638
// Additionally, application-writers need to be aware that newly
639
// created sessions (that is, sessions for which HttpSession.isNew
640
// returns true) do not have any application-specific state.
641
// public HttpSession getSession( boolean create )
642
// {
643
// return null;
644
// }
645

646     /// Gets the session id specified with this request. This may differ
647
// from the actual session id. For example, if the request specified
648
// an id for an invalid session, then this will get a new session with
649
// a new id.
650
public String JavaDoc getRequestedSessionId()
651     {
652     return null;
653     }
654
655     /// Checks whether this request is associated with a session that is
656
// valid in the current session context. If it is not valid, the
657
// requested session will never be returned from the getSession
658
// method.
659
public boolean isRequestedSessionIdValid()
660     {
661     return false;
662     }
663
664     /// Checks whether the session id specified by this request came in as
665
// a cookie. (The requested session may not be one returned by the
666
// getSession method.)
667
public boolean isRequestedSessionIdFromCookie()
668     {
669     return false;
670     }
671
672     /// Checks whether the session id specified by this request came in as
673
// part of the URL. (The requested session may not be the one returned
674
// by the getSession method.)
675
public boolean isRequestedSessionIdFromUrl()
676     {
677     return false;
678     }
679
680
681     // Methods from ServletResponse.
682

683     /// Sets the content length for this response.
684
// @param length the content length
685
public void setContentLength( int length )
686     {
687     setIntHeader( "Content-length", length );
688     }
689
690     /// Sets the content type for this response.
691
// @param type the content type
692
public void setContentType( String JavaDoc type )
693     {
694     setHeader( "Content-type", type );
695     }
696
697     /// Returns an output stream for writing response data.
698
public ServeOutputStream getOutputStream()
699     {
700     return out;
701     }
702
703     /// Returns a print writer for writing response data. The MIME type of
704
// the response will be modified, if necessary, to reflect the character
705
// encoding used, through the charset=... property. This means that the
706
// content type must be set before calling this method.
707
// @exception UnsupportedEncodingException if no such encoding can be provided
708
// @exception IllegalStateException if getOutputStream has been called
709
// @exception IOException on other I/O errors
710
public PrintWriter getWriter() throws IOException
711     {
712     // !!!
713
return null;
714     }
715
716     /// Returns the character set encoding used for this MIME body. The
717
// character encoding is either the one specified in the assigned
718
// content type, or one which the client understands. If no content
719
// type has yet been assigned, it is implicitly set to text/plain.
720
public String JavaDoc getCharacterEncoding()
721     {
722     // !!!
723
return null;
724     }
725
726
727     // Methods from HttpServletResponse.
728

729     /// Adds the specified cookie to the response. It can be called
730
// multiple times to set more than one cookie.
731
// public void addCookie( Cookie cookie )
732
// {
733
// cookies.addElement( cookie );
734
// }
735

736     /// Checks whether the response message header has a field with the
737
// specified name.
738
public boolean containsHeader( String JavaDoc name )
739     {
740     return resHeaderNames.contains( name );
741     }
742
743     private int resCode = -1;
744     private String JavaDoc resMessage = null;
745     private Vector resHeaderNames = new Vector();
746     private Vector resHeaderValues = new Vector();
747
748     /// Sets the status code and message for this response.
749
// @param resCode the status code
750
// @param resMessage the status message
751
public void setStatus( int resCode, String JavaDoc resMessage )
752     {
753     this.resCode = resCode;
754     this.resMessage = resMessage;
755     }
756
757     /// Sets the status code and a default message for this response.
758
// @param resCode the status code
759
public void setStatus( int resCode )
760     {
761     switch ( resCode )
762         {
763         case SC_CONTINUE: setStatus( resCode, "Continue" ); break;
764         case SC_SWITCHING_PROTOCOLS:
765         setStatus( resCode, "Switching protocols" ); break;
766         case SC_OK: setStatus( resCode, "Ok" ); break;
767         case SC_CREATED: setStatus( resCode, "Created" ); break;
768         case SC_ACCEPTED: setStatus( resCode, "Accepted" ); break;
769         case SC_NON_AUTHORITATIVE_INFORMATION:
770         setStatus( resCode, "Non-authoritative" ); break;
771         case SC_NO_CONTENT: setStatus( resCode, "No content" ); break;
772         case SC_RESET_CONTENT: setStatus( resCode, "Reset content" ); break;
773         case SC_PARTIAL_CONTENT:
774         setStatus( resCode, "Partial content" ); break;
775         case SC_MULTIPLE_CHOICES:
776         setStatus( resCode, "Multiple choices" ); break;
777         case SC_MOVED_PERMANENTLY:
778         setStatus( resCode, "Moved permanentently" ); break;
779         case SC_MOVED_TEMPORARILY:
780         setStatus( resCode, "Moved temporarily" ); break;
781         case SC_SEE_OTHER: setStatus( resCode, "See other" ); break;
782         case SC_NOT_MODIFIED: setStatus( resCode, "Not modified" ); break;
783         case SC_USE_PROXY: setStatus( resCode, "Use proxy" ); break;
784         case SC_BAD_REQUEST: setStatus( resCode, "Bad request" ); break;
785         case SC_UNAUTHORIZED: setStatus( resCode, "Unauthorized" ); break;
786         case SC_PAYMENT_REQUIRED:
787         setStatus( resCode, "Payment required" ); break;
788         case SC_FORBIDDEN: setStatus( resCode, "Forbidden" ); break;
789         case SC_NOT_FOUND: setStatus( resCode, "Not found" ); break;
790         case SC_METHOD_NOT_ALLOWED:
791         setStatus( resCode, "Method not allowed" ); break;
792         case SC_NOT_ACCEPTABLE:
793         setStatus( resCode, "Not acceptable" ); break;
794         case SC_PROXY_AUTHENTICATION_REQUIRED:
795         setStatus( resCode, "Proxy auth required" ); break;
796         case SC_REQUEST_TIMEOUT:
797         setStatus( resCode, "Request timeout" ); break;
798         case SC_CONFLICT: setStatus( resCode, "Conflict" ); break;
799         case SC_GONE: setStatus( resCode, "Gone" ); break;
800         case SC_LENGTH_REQUIRED:
801         setStatus( resCode, "Length required" ); break;
802         case SC_PRECONDITION_FAILED:
803         setStatus( resCode, "Precondition failed" ); break;
804         case SC_REQUEST_ENTITY_TOO_LARGE:
805         setStatus( resCode, "Request entity too large" ); break;
806         case SC_REQUEST_URI_TOO_LONG:
807         setStatus( resCode, "Request URI too large" ); break;
808         case SC_UNSUPPORTED_MEDIA_TYPE:
809         setStatus( resCode, "Unsupported media type" ); break;
810         case SC_INTERNAL_SERVER_ERROR:
811         setStatus( resCode, "Internal server error" ); break;
812         case SC_NOT_IMPLEMENTED:
813         setStatus( resCode, "Not implemented" ); break;
814         case SC_BAD_GATEWAY: setStatus( resCode, "Bad gateway" ); break;
815         case SC_SERVICE_UNAVAILABLE:
816         setStatus( resCode, "Service unavailable" ); break;
817         case SC_GATEWAY_TIMEOUT:
818         setStatus( resCode, "Gateway timeout" ); break;
819         case SC_HTTP_VERSION_NOT_SUPPORTED:
820         setStatus( resCode, "HTTP version not supported" ); break;
821         default: setStatus( resCode, "" ); break;
822         }
823     }
824
825     /// Sets the value of a header field.
826
// @param name the header field name
827
// @param value the header field value
828
public void setHeader( String JavaDoc name, String JavaDoc value )
829     {
830     resHeaderNames.addElement( name );
831     resHeaderValues.addElement( value );
832     }
833
834     /// Sets the value of an integer header field.
835
// @param name the header field name
836
// @param value the header field integer value
837
public void setIntHeader( String JavaDoc name, int value )
838     {
839     setHeader( name, Integer.toString( value ) );
840     }
841
842     /// Sets the value of a long header field.
843
// @param name the header field name
844
// @param value the header field long value
845
public void setLongHeader( String JavaDoc name, long value )
846     {
847     setHeader( name, Long.toString( value ) );
848     }
849
850     /// Sets the value of a date header field.
851
// @param name the header field name
852
// @param value the header field date value
853
public void setDateHeader( String JavaDoc name, long value )
854     {
855     setHeader( name, to1123String( new Date( value ) ) );
856     }
857
858     private static final String JavaDoc[] weekdays =
859     { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
860
861     /// Converts a Date into an RFC-1123 string.
862
private static String JavaDoc to1123String( Date date )
863     {
864     // We have to go through some machinations here to get the
865
// correct day of the week in GMT. getDay() gives the day in
866
// local time. getDate() gives the day of the month in local
867
// time. toGMTString() gives a formatted string in GMT. So, we
868
// extract the day of the month from the GMT string, and if it
869
// doesn't match the local one we change the local day of the
870
// week accordingly.
871
//
872
// The Date class sucks.
873
int localDay = date.getDay();
874     int localDate = date.getDate();
875     String JavaDoc gmtStr = date.toGMTString();
876     int blank = gmtStr.indexOf( ' ' );
877     int gmtDate = Integer.parseInt( gmtStr.substring( 0, blank ) );
878     int gmtDay;
879     if ( gmtDate > localDate || ( gmtDate < localDate && gmtDate == 1 ) )
880         gmtDay = ( localDay + 1 ) % 7;
881     else if ( localDate > gmtDate || ( localDate < gmtDate && localDate == 1 ) )
882         gmtDay = ( localDay + 6 ) % 7;
883     else
884         gmtDay = localDay;
885     return weekdays[gmtDay] + ( gmtDate < 10 ? ", 0" : ", " ) + gmtStr;
886     }
887
888     private boolean headersWritten = false;
889
890     /// Writes the status line and message headers for this response to the
891
// output stream.
892
// @exception IOException if an I/O error has occurred
893
void writeHeaders() throws IOException
894     {
895     if ( headersWritten )
896         return;
897     headersWritten = true;
898     if ( reqMime )
899         {
900         out.println( reqProtocol + " " + resCode + " " + resMessage );
901         for ( int i = 0; i < resHeaderNames.size(); ++i )
902         {
903         String JavaDoc name = (String JavaDoc) resHeaderNames.elementAt( i );
904         String JavaDoc value = (String JavaDoc) resHeaderValues.elementAt( i );
905         if ( value != null ) // just in case
906
out.println( name + ": " + value );
907         }
908         out.println( "" );
909         out.flush();
910         }
911     }
912
913     /// Writes an error response using the specified status code and message.
914
// @param resCode the status code
915
// @param resMessage the status message
916
// @exception IOException if an I/O error has occurred
917
public void sendError( int resCode, String JavaDoc resMessage ) throws IOException
918     {
919     setStatus( resCode, resMessage );
920     realSendError();
921     }
922
923     /// Writes an error response using the specified status code and a default
924
// message.
925
// @param resCode the status code
926
// @exception IOException if an I/O error has occurred
927
public void sendError( int resCode ) throws IOException
928     {
929     setStatus( resCode );
930     realSendError();
931     }
932
933     private void realSendError() throws IOException
934     {
935     setContentType( "text/html" );
936     out.println( "<HTML><HEAD>" );
937     out.println( "<TITLE>" + resCode + " " + resMessage + "</TITLE>" );
938     out.println( "</HEAD><BODY BGCOLOR=\"#99cc99\">" );
939     out.println( "<H2>" + resCode + " " + resMessage + "</H2>" );
940     out.println( "<HR>" );
941     out.println( "</BODY></HTML>" );
942     out.flush();
943     }
944
945     /// Sends a redirect message to the client using the specified redirect
946
// location URL.
947
// @param location the redirect location URL
948
// @exception IOException if an I/O error has occurred
949
public void sendRedirect( String JavaDoc location ) throws IOException
950     {
951     setHeader( "Location", location );
952     sendError( SC_MOVED_TEMPORARILY );
953     }
954
955     // URL session-encoding stuff. Not implemented, but the API is here
956
// for compatibility.
957

958     /// Encodes the specified URL by including the session ID in it, or, if
959
// encoding is not needed, returns the URL unchanged. The
960
// implementation of this method should include the logic to determine
961
// whether the session ID needs to be encoded in the URL. For example,
962
// if the browser supports cookies, or session tracking is turned off,
963
// URL encoding is unnecessary.
964
// <P>
965
// All URLs emitted by a Servlet should be run through this method.
966
// Otherwise, URL rewriting cannot be used with browsers which do not
967
// support cookies.
968
public String JavaDoc encodeUrl( String JavaDoc url )
969     {
970     return url;
971     }
972
973     /// Encodes the specified URL for use in the sendRedirect method or, if
974
// encoding is not needed, returns the URL unchanged. The
975
// implementation of this method should include the logic to determine
976
// whether the session ID needs to be encoded in the URL. Because the
977
// rules for making this determination differ from those used to
978
// decide whether to encode a normal link, this method is seperate
979
// from the encodeUrl method.
980
// <P>
981
// All URLs sent to the HttpServletResponse.sendRedirect method should be
982
// run through this method. Otherwise, URL rewriting cannot be used with
983
// browsers which do not support cookies.
984
public String JavaDoc encodeRedirectUrl( String JavaDoc url )
985     {
986     return url;
987     }
988
989    //from Acme.Utils:
990
/// Turns a String into an array of Strings, by using StringTokenizer
991
// to split it up at whitespace.
992
public static String JavaDoc[] splitStr( String JavaDoc str )
993         {
994         StringTokenizer st = new StringTokenizer( str );
995         int n = st.countTokens();
996         String JavaDoc[] strs = new String JavaDoc[n];
997         for ( int i = 0; i < n; ++i )
998             strs[i] = st.nextToken();
999         return strs;
1000        }
1001    }
1002    
1003
1004
1005
1006
1007
1008
1009
1010
1011
Popular Tags