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

Home » openejb-3.1.2-src » org.apache » openejb » webadmin » httpd » [javadoc | source]