Save This Page
Home » openejb-3.1.2-src » org.apache » openejb » server » httpd » [javadoc | source]
    1   /**
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.openejb.server.httpd;
   18   
   19   import java.io.ByteArrayOutputStream;
   20   import java.io.DataOutput;
   21   import java.io.DataOutputStream;
   22   import java.io.IOException;
   23   import java.io.InputStream;
   24   import java.io.OutputStream;
   25   import java.io.PrintWriter;
   26   import java.net.URL;
   27   import java.net.URLConnection;
   28   import java.util.HashMap;
   29   import java.util.Map;
   30   import java.util.Properties;
   31   import java.util.StringTokenizer;
   32   
   33   /** This class takes care of HTTP Responses.  It sends data back to the browser.
   34    */
   35   public class HttpResponseImpl implements HttpResponse {
   36   
   37       /** Response string */
   38       private String responseString = "OK";
   39   
   40       /** Code */
   41       private int code = 200;
   42   
   43       /** Response headers */
   44       private final Map<String,String> headers = new HashMap<String,String>();
   45   
   46       /** Response body */
   47       private byte[] body = new byte[0];
   48   
   49       /** the writer for the response */
   50       private transient PrintWriter writer;
   51       /** the raw body */
   52       private transient ByteArrayOutputStream baos;
   53   
   54       /** the HTTP version */
   55       public static final String HTTP_VERSION = "HTTP/1.1";
   56       /** a line feed character */
   57       public static final String CRLF = "\r\n";
   58       /** a space character */
   59       public static final String SP = " ";
   60       /** a colon and space */
   61       public static final String CSP = ": ";
   62       /** the server to send data from */
   63       public static String server;
   64   
   65       private HttpRequestImpl request;
   66       private URLConnection content;
   67   
   68       protected void setRequest(HttpRequestImpl request){
   69           this.request = request;
   70       }
   71   
   72       /** sets a header to be sent back to the browser
   73        * @param name the name of the header
   74        * @param value the value of the header
   75        */
   76       public void setHeader(String name, String value){
   77           headers.put(name, value);
   78       }
   79   
   80       /** Gets a header based on the name passed in
   81        * @param name The name of the header
   82        * @return the value of the header
   83        */
   84       public String getHeader(String name){
   85           return headers.get(name);
   86       }
   87   
   88       /** Gets the PrintWriter to send data to the browser
   89        * @return the PrintWriter to send data to the browser
   90        */
   91       public PrintWriter getPrintWriter(){
   92           return writer;
   93       }
   94   
   95       /** gets the OutputStream to send data to the browser
   96        * @return the OutputStream to send data to the browser
   97        */
   98       public OutputStream getOutputStream(){
   99           return baos;
  100       }
  101   
  102       public void flushBuffer() throws IOException {
  103           // there is really no way to flush
  104       }
  105   
  106       /** sets the HTTP response code to be sent to the browser.  These codes are:
  107        *
  108        * OPTIONS = 0
  109        * GET     = 1
  110        * HEAD    = 2
  111        * POST    = 3
  112        * PUT     = 4
  113        * DELETE  = 5
  114        * TRACE   = 6
  115        * CONNECT = 7
  116        * UNSUPPORTED = 8
  117        * @param code the code to be sent to the browser
  118        */
  119       public void setCode(int code){
  120           this.code = code;
  121       }
  122   
  123       /** gets the HTTP response code
  124        * @return the HTTP response code
  125        */
  126       public int getCode(){
  127           return code;
  128       }
  129   
  130       /** sets the content type to be sent back to the browser
  131        * @param type the type to be sent to the browser (i.e. "text/html")
  132        */
  133       public void setContentType(String type){
  134           setHeader("Content-Type", type);
  135       }
  136   
  137       /** gets the content type that will be sent to the browser
  138        * @return the content type (i.e. "text/html")
  139        */
  140       public String getContentType(){
  141           return getHeader("Content-Type");
  142       }
  143   
  144       /** Sets the response string to be sent to the browser
  145        * @param responseString the response string
  146        */
  147       public void setResponseString(String responseString){
  148          this.responseString = responseString;
  149       }
  150   
  151       /** resets the data to be sent to the browser */
  152       public void reset(){
  153           initBody();
  154       }
  155   
  156       /** resets the data to be sent to the browser with the response code and response
  157        * string
  158        * @param code the code to be sent to the browser
  159        * @param responseString the response string to be sent to the browser
  160        */
  161       public void reset(int code, String responseString){
  162           setCode(code);
  163           setResponseString(responseString);
  164           initBody();
  165       }
  166   
  167       /*------------------------------------------------------------*/
  168       /*  Methods for writing out a response                        */
  169       /*------------------------------------------------------------*/
  170       /** creates a new instance of HttpResponseImpl with default values */
  171       protected HttpResponseImpl(){
  172           this(200, "OK", "text/html");
  173       }
  174   
  175       /** Creates a new HttpResponseImpl with user provided parameters
  176        * @param code the HTTP Response code, see <a href="http://www.ietf.org/rfc/rfc2616.txt">http://www.ietf.org/rfc/rfc2616.txt</a>
  177        * for these codes
  178        * @param responseString the response string to be sent back
  179        * @param contentType the content type to be sent back
  180        */
  181       protected HttpResponseImpl(int code, String responseString, String contentType){
  182           this.responseString = responseString;
  183           this.code = code;
  184   
  185           // Default headers
  186           setHeader("Server", getServerName());
  187           setHeader("Connection","close");
  188           setHeader("Content-Type",contentType);
  189   
  190           // create the body.
  191           initBody();
  192       }
  193   
  194       /** Takes care of sending the response line, headers and body
  195        *
  196        * HTTP/1.1 200 OK
  197        * Server: Netscape-Enterprise/3.6 SP3
  198        * Date: Thu, 07 Jun 2001 17:30:42 GMT
  199        * Content-Type: text/html
  200        * Connection: close
  201        * @param output the output to send the response to
  202        * @throws java.io.IOException if an exception is thrown
  203        */
  204       protected void writeMessage(OutputStream output) throws IOException{
  205           ByteArrayOutputStream baos = new ByteArrayOutputStream();
  206       	DataOutputStream out = new DataOutputStream(baos);
  207           //DataOutput log = new DataOutputStream(System.out);
  208           //System.out.println("\nRESPONSE");
  209           closeMessage();
  210   //        writeResponseLine(log);
  211   //        writeHeaders(log);
  212   //        writeBody(log);
  213           writeResponseLine(out);
  214           writeHeaders(out);
  215           writeBody(out);
  216           out.flush();
  217           output.write(baos.toByteArray());
  218           output.flush();
  219       }
  220   
  221        /** initalizes the body */
  222       private void initBody(){
  223           baos = new ByteArrayOutputStream();
  224           writer = new PrintWriter( baos );
  225       }
  226   
  227       /** Creates a string version of the response similar to:
  228        *
  229        * HTTP/1.1 200 OK
  230        * @return the string value of this HttpResponseImpl
  231        */
  232       public String toString(){
  233           StringBuffer buf = new StringBuffer(40);
  234   
  235           buf.append(HTTP_VERSION);
  236           buf.append(SP);
  237           buf.append(code);
  238           buf.append(SP);
  239           buf.append(responseString);
  240   
  241           return buf.toString();
  242       }
  243   
  244       /** closes the message sent to the browser
  245        */
  246       private void closeMessage() {
  247           setContentLengthHeader();
  248           setCookieHeader();
  249       }
  250   
  251   
  252       private void setContentLengthHeader() {
  253           if (content == null){
  254               writer.flush();
  255               writer.close();
  256               body = baos.toByteArray();
  257               setHeader("Content-Length", body.length+"");
  258           } else {
  259               setHeader("Content-Length", content.getContentLength()+"");
  260           }
  261       }
  262   
  263       private void setCookieHeader() {
  264           if (request == null || request.getSession() == null) return;
  265   
  266           HttpSession session = request.getSession(false);
  267   
  268           if (session == null) return;
  269   
  270           StringBuffer cookie = new StringBuffer();
  271           cookie.append(HttpRequestImpl.EJBSESSIONID);
  272           cookie.append('=');
  273           cookie.append(session.getId());
  274           cookie.append("; Path=/");
  275   
  276           headers.put(HttpRequest.HEADER_SET_COOKIE, cookie.toString());
  277       }
  278   
  279       /** Writes a response line similar to this:
  280        *
  281        * HTTP/1.1 200 OK
  282        *
  283        * to the browser
  284        * @param out the output stream to write the response line to
  285        * @throws java.io.IOException if an exception is thrown
  286        */
  287       private void writeResponseLine(DataOutput out) throws IOException{
  288           out.writeBytes(HTTP_VERSION);
  289           out.writeBytes(SP);
  290           out.writeBytes(code+"");
  291           out.writeBytes(SP);
  292           out.writeBytes(responseString);
  293           out.writeBytes(CRLF);
  294       }
  295   
  296       /** writes the headers out to the browser
  297        * @param out the output stream to be sent to the browser
  298        * @throws java.io.IOException if an exception is thrown
  299        */
  300       private void writeHeaders(DataOutput out) throws IOException{
  301           for (Map.Entry<String, String> entry : headers.entrySet()) {
  302               out.writeBytes(""+entry.getKey());
  303               out.writeBytes(CSP);
  304               out.writeBytes(""+entry.getValue());
  305               out.writeBytes(CRLF);
  306           }
  307       }
  308   
  309       /** writes the body out to the browser
  310        * @param out the output stream that writes to the browser
  311        * @throws java.io.IOException if an exception is thrown
  312        */
  313       private void writeBody(DataOutput out) throws IOException{
  314           out.writeBytes(CRLF);
  315           if (content == null){
  316               out.write(body);
  317           } else {
  318               InputStream in = content.getInputStream();
  319               byte buf[] = new byte[1024];
  320   
  321               int i;
  322               while ((i = in.read(buf)) != -1) {
  323                    out.write(buf, 0, i);
  324               }
  325           }
  326       }
  327   
  328       /** gets the name of the server being used
  329        * @return the name of the server
  330        */
  331       public String getServerName(){
  332           if (server == null) {
  333               String version = "???";
  334               String os = "(unknown os)";
  335   
  336               try {
  337                   Properties versionInfo = new Properties();
  338                   versionInfo.load( new URL( "resource:/openejb-version.properties" ).openConnection().getInputStream() );
  339                   version = versionInfo.getProperty( "version" );
  340                   os = System.getProperty("os.name")+"/"+System.getProperty("os.version")+" ("+System.getProperty("os.arch")+")";
  341               } catch (IOException e) {
  342               }
  343   
  344               server = "OpenEJB/" +version+ " "+os;
  345           }
  346           return server;
  347       }
  348   
  349   
  350       /** This could be improved at some day in the future
  351        * to also include a stack trace of the exceptions
  352        * @param message the error message to be sent
  353        * @return the HttpResponseImpl that this error belongs to
  354        */
  355       protected static HttpResponseImpl createError(String message){
  356           return createError(message, null);
  357       }
  358   
  359       /** creates an error with user defined variables
  360        * @param message the message of the error
  361        * @param t a Throwable to print a stack trace to
  362        * @return the HttpResponseImpl that this error belongs to
  363        */
  364       protected static HttpResponseImpl createError(String message, Throwable t){
  365           HttpResponseImpl res = new HttpResponseImpl(500, "Internal Server Error", "text/html");
  366           PrintWriter body = res.getPrintWriter();
  367   
  368           body.println("<html>");
  369           body.println("<body>");
  370           body.println("<h3>Internal Server Error</h3>");
  371           body.println("<br><br>");
  372           System.out.println("ERROR");
  373           if (message != null) {
  374               StringTokenizer msg = new StringTokenizer(message, "\n\r");
  375   
  376               while (msg.hasMoreTokens()) {
  377                   body.print( msg.nextToken() );
  378                   body.println("<br>");
  379               }
  380           }
  381   
  382           if (t != null) {
  383               try{
  384                   body.println("<br><br>");
  385                   body.println("Stack Trace:<br>");
  386                   ByteArrayOutputStream baos = new ByteArrayOutputStream();
  387                   PrintWriter writer = new PrintWriter( baos );
  388                   t.printStackTrace(writer);
  389                   writer.flush();
  390                   writer.close();
  391                   message = new String(baos.toByteArray());
  392                   StringTokenizer msg = new StringTokenizer(message, "\n\r");
  393   
  394                   while (msg.hasMoreTokens()) {
  395                       body.print( msg.nextToken() );
  396                       body.println("<br>");
  397                   }
  398               } catch (Exception e){
  399               }
  400           }
  401   
  402           body.println("</body>");
  403           body.println("</html>");
  404   
  405           return res;
  406       }
  407   
  408       /** Creates a forbidden response to be sent to the browser using IP authentication
  409        * @param ip the ip that is forbidden
  410        * @return the HttpResponseImpl that this error belongs to
  411        */
  412       protected static HttpResponseImpl createForbidden(String ip){
  413           HttpResponseImpl res = new HttpResponseImpl(403, "Forbidden", "text/html");
  414           PrintWriter body = res.getPrintWriter();
  415   
  416           body.println("<html>");
  417           body.println("<body>");
  418           body.println("<h3>Forbidden</h3>");
  419           body.println("<br><br>");
  420           // Add more text here
  421           // IP not allowed, etc.
  422           body.println("IP address: " + ip + " is not registered on this server, please contact your system administrator.");
  423           body.println("</body>");
  424           body.println("</html>");
  425   
  426           return res;
  427       }
  428   
  429       /** writes this object out to a file
  430        * @param out the ObjectOutputStream to write to
  431        * @throws java.io.IOException if an exception is thrown
  432        */
  433       private void writeObject(java.io.ObjectOutputStream out) throws IOException{
  434           /** Response string */
  435           out.writeObject( responseString );
  436   
  437           /** Code */
  438           out.writeInt( code );
  439   
  440           /** Response headers */
  441           out.writeObject( headers );
  442   
  443           /** Response body */
  444           writer.flush();
  445           body = baos.toByteArray();
  446           //System.out.println("[] body "+body.length );
  447           out.writeObject( body );
  448       }
  449   
  450       /** Reads in a serilized HttpResponseImpl object from a file
  451        * @param in the input to read the object from
  452        * @throws java.io.IOException if an exception is thrown
  453        * @throws ClassNotFoundException if an exception is thrown
  454        */
  455       @SuppressWarnings({"unchecked"})
  456       private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
  457           /** Response string */
  458           this.responseString = (String)in.readObject();
  459   
  460           /** Code */
  461           this.code = in.readInt();
  462   
  463           /** Response headers */
  464           Map headers = (Map) in.readObject();
  465           this.headers.clear();
  466           this.headers.putAll(headers);
  467   
  468           /** Response body */
  469           body = (byte[]) in.readObject();
  470           //System.out.println("[] body "+body.length );
  471           baos = new ByteArrayOutputStream();
  472           baos.write( body );
  473           writer = new PrintWriter( baos );
  474   
  475       }
  476       /**
  477        * @param content The content to set.
  478        */
  479       public void setContent(URLConnection content) {
  480           this.content = content;
  481       }
  482   
  483       public void setStatusCode(int code) {
  484           this.setCode(code);
  485       }
  486   
  487       public int getStatusCode() {
  488           return this.getCode();
  489       }
  490   
  491       public void setStatusMessage(String responseString) {
  492           this.setResponseString(responseString);
  493       }
  494   }

Save This Page
Home » openejb-3.1.2-src » org.apache » openejb » server » httpd » [javadoc | source]