All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openejb.webadmin.httpd.HttpResponseImpl Maven / Gradle / Ivy

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.openejb.webadmin.httpd;

import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.openejb.webadmin.HttpRequest;
import org.apache.openejb.webadmin.HttpResponse;
import org.apache.openejb.webadmin.HttpSession;
import org.apache.openejb.util.JarUtils;
import org.apache.openejb.util.OpenEjbVersion;

/** This class takes care of HTTP Responses.  It sends data back to the browser.
 * @author David Blevins
 * @author Tim Urberg
 */
public class HttpResponseImpl implements HttpResponse {

    /** Response string */
    private String responseString = "OK";

    /** Code */
    private int code = 200;

    /** Response headers */
    private HashMap headers;

    /** Response body */
    private byte[] body = new byte[0];

    /** the writer for the response */
    private transient PrintWriter writer;
    /** the raw body */
    private transient ByteArrayOutputStream baos;

    /** the HTTP version */
    public static final String HTTP_VERSION = "HTTP/1.1";
    /** a line feed character */
    public static final String CRLF = "\r\n";
    /** a space character */
    public static final String SP = " ";
    /** a colon and space */
    public static final String CSP = ": ";
    /** the server to send data from */
    public static String server;

    private HttpRequestImpl request;
    private URLConnection content;

    protected void setRequest(HttpRequestImpl request){
        this.request = request;
    }

    /** sets a header to be sent back to the browser
     * @param name the name of the header
     * @param value the value of the header
     */
    public void setHeader(String name, String value){
        headers.put(name, value);
    }

    /** Gets a header based on the name passed in
     * @param name The name of the header
     * @return the value of the header
     */
    public String getHeader(String name){
        return (String) headers.get(name);
    }

    /** Gets the PrintWriter to send data to the browser
     * @return the PrintWriter to send data to the browser
     */
    public PrintWriter getPrintWriter(){
        return writer;
    }

    /** gets the OutputStream to send data to the browser
     * @return the OutputStream to send data to the browser
     */
    public OutputStream getOutputStream(){
        return baos;
    }

    /** sets the HTTP response code to be sent to the browser.  These codes are:
     *
     * OPTIONS = 0
     * GET     = 1
     * HEAD    = 2
     * POST    = 3
     * PUT     = 4
     * DELETE  = 5
     * TRACE   = 6
     * CONNECT = 7
     * UNSUPPORTED = 8
     * @param code the code to be sent to the browser
     */
    public void setCode(int code){
        this.code = code;
    }

    /** gets the HTTP response code
     * @return the HTTP response code
     */
    public int getCode(){
        return code;
    }

    /** sets the content type to be sent back to the browser
     * @param type the type to be sent to the browser (i.e. "text/html")
     */
    public void setContentType(String type){
        setHeader("Content-Type", type);
    }

    /** gets the content type that will be sent to the browser
     * @return the content type (i.e. "text/html")
     */
    public String getContentType(){
        return getHeader("Content-Type");
    }

    /** Sets the response string to be sent to the browser
     * @param responseString the response string
     */
    public void setResponseString(String responseString){
       this.responseString = responseString;
    }

    /** Sets the response string to be sent to the browser
     * @return the response string
     */
    public String getResponseString(){
        return responseString;
    }

    /** resets the data to be sent to the browser */
    public void reset(){
        initBody();
    }

    /** resets the data to be sent to the browser with the response code and response
     * string
     * @param code the code to be sent to the browser
     * @param responseString the response string to be sent to the browser
     */
    public void reset(int code, String responseString){
        setCode(code);
        setResponseString(responseString);
        initBody();
    }

    /*------------------------------------------------------------*/
    /*  Methods for writing out a response                        */
    /*------------------------------------------------------------*/
    /** creates a new instance of HttpResponseImpl with default values */
    protected HttpResponseImpl(){
        this(200, "OK", "text/html");
    }

    /** Creates a new HttpResponseImpl with user provided parameters
     * @param code the HTTP Response code, see http://www.ietf.org/rfc/rfc2616.txt
     * for these codes
     * @param responseString the response string to be sent back
     * @param contentType the content type to be sent back
     */
    protected HttpResponseImpl(int code, String responseString, String contentType){
        this.responseString = responseString;
        this.headers = new HashMap();
        this.code = code;

        // Default headers
        setHeader("Server", getServerName());
        setHeader("Connection","close");
        setHeader("Content-Type",contentType);

        // create the body.
        initBody();
    }

    /** Takes care of sending the response line, headers and body
     *
     * HTTP/1.1 200 OK
     * Server: Netscape-Enterprise/3.6 SP3
     * Date: Thu, 07 Jun 2001 17:30:42 GMT
     * Content-Type: text/html
     * Connection: close
     * @param output the output to send the response to
     * @throws IOException if an exception is thrown
     */
    protected void writeMessage(OutputStream output) throws IOException{
        DataOutput out = new DataOutputStream(output);
        DataOutput log = new DataOutputStream(System.out);
        //System.out.println("\nRESPONSE");
        closeMessage();
        //writeResponseLine(log);
//        writeHeaders(log);
//        writeBody(log);
        writeResponseLine(out);
        writeHeaders(out);
        writeBody(out);
    }

     /** initalizes the body */
    private void initBody(){
        baos = new ByteArrayOutputStream();
        writer = new PrintWriter( baos );
    }

    /** Creates a string version of the response similar to:
     *
     * HTTP/1.1 200 OK
     * @return the string value of this HttpResponseImpl
     */
    public String toString(){
        StringBuffer buf = new StringBuffer(40);

        buf.append(HTTP_VERSION);
        buf.append(SP);
        buf.append(code+"");
        buf.append(SP);
        buf.append(responseString);

        return buf.toString();
    }

    /** closes the message sent to the browser
     * @throws IOException if an exception is thrown
     */
    private void closeMessage() throws IOException{
        setContentLengthHeader();
        setCookieHeader();
    }


    private void setContentLengthHeader() {
        if (content == null){
            writer.flush();
            writer.close();
            body = baos.toByteArray();
            setHeader("Content-Length", body.length+"");
        } else {
            setHeader("Content-Length", content.getContentLength()+"");
        }
    }

    private void setCookieHeader() {
        if (request == null || request.getSession() == null) return;

        HttpSession session = request.getSession(false);

        if (session == null) return;

        StringBuffer cookie = new StringBuffer();
        cookie.append(HttpRequestImpl.EJBSESSIONID);
        cookie.append('=');
        cookie.append(session.getId());
        cookie.append("; Path=/");

        headers.put(HttpRequest.HEADER_SET_COOKIE, cookie.toString());
    }

    /** Writes a response line similar to this:
     *
     * HTTP/1.1 200 OK
     *
     * to the browser
     * @param out the output stream to write the response line to
     * @throws IOException if an exception is thrown
     */
    private void writeResponseLine(DataOutput out) throws IOException{
        out.writeBytes(HTTP_VERSION);
        out.writeBytes(SP);
        out.writeBytes(code+"");
        out.writeBytes(SP);
        out.writeBytes(responseString);
        out.writeBytes(CRLF);
    }

    /** writes the headers out to the browser
     * @param out the output stream to be sent to the browser
     * @throws IOException if an exception is thrown
     */
    private void writeHeaders(DataOutput out) throws IOException{
        Iterator it =  headers.entrySet().iterator();

        while (it.hasNext()){
            Map.Entry entry = (Map.Entry)it.next();
            out.writeBytes(""+entry.getKey());
            out.writeBytes(CSP);
            out.writeBytes(""+entry.getValue());
            out.writeBytes(CRLF);
        }
    }

    /** writes the body out to the browser
     * @param out the output stream that writes to the browser
     * @throws IOException if an exception is thrown
     */
    private void writeBody(DataOutput out) throws IOException{
        out.writeBytes(CRLF);
        if (content == null){
            out.write(body);
        } else {
            InputStream in = content.getInputStream();
            byte buf[] = new byte[1024];
            for(int i = 0; (i = in.read(buf)) != -1; out.write(buf, 0, i));
        }
    }

    /** gets the name of the server being used
     * @return the name of the server
     */
    public String getServerName(){
        if (server == null) {
            String version = "???";
            String os = "(unknown os)";

            OpenEjbVersion openejbInfo = OpenEjbVersion.get();

            version = openejbInfo.getVersion();
            os = System.getProperty("os.name")+"/"+System.getProperty("os.version")+" ("+System.getProperty("os.arch")+")";

            server = "OpenEJB/" +version+ " "+os;
        }
        return server;
    }


    /** This could be improved at some day in the future
     * to also include a stack trace of the exceptions
     * @param message the error message to be sent
     * @return the HttpResponseImpl that this error belongs to
     */
    protected static HttpResponseImpl createError(String message){
        return createError(message, null);
    }

    /** creates an error with user defined variables
     * @param message the message of the error
     * @param t a Throwable to print a stack trace to
     * @return the HttpResponseImpl that this error belongs to
     */
    protected static HttpResponseImpl createError(String message, Throwable t){
        HttpResponseImpl res = new HttpResponseImpl(500, "Internal Server Error", "text/html");
        java.io.PrintWriter body = res.getPrintWriter();

        body.println("");
        body.println("");
        body.println("

Internal Server Error

"); body.println("

"); if (message != null) { StringTokenizer msg = new StringTokenizer(message, "\n\r"); while (msg.hasMoreTokens()) { body.print( msg.nextToken() ); body.println("
"); } } if (t != null) { try{ body.println("

"); body.println("Stack Trace:
"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter writer = new PrintWriter( baos ); t.printStackTrace(writer); writer.flush(); writer.close(); message = new String(baos.toByteArray()); StringTokenizer msg = new StringTokenizer(message, "\n\r"); while (msg.hasMoreTokens()) { body.print( msg.nextToken() ); body.println("
"); } } catch (Exception e){ } } body.println(""); body.println(""); return res; } /** Creates a forbidden response to be sent to the browser using IP authentication * @param ip the ip that is forbidden * @return the HttpResponseImpl that this error belongs to */ protected static HttpResponseImpl createForbidden(String ip){ HttpResponseImpl res = new HttpResponseImpl(403, "Forbidden", "text/html"); java.io.PrintWriter body = res.getPrintWriter(); body.println(""); body.println(""); body.println("

Forbidden

"); body.println("

"); // Add more text here // IP not allowed, etc. body.println("IP address: " + ip + " is not registered on this server, please contact your system administrator."); body.println(""); body.println(""); return res; } /** writes this object out to a file * @param out the ObjectOutputStream to write to * @throws IOException if an exception is thrown */ private void writeObject(java.io.ObjectOutputStream out) throws IOException{ /** Response string */ out.writeObject( responseString ); /** Code */ out.writeInt( code ); /** Response headers */ out.writeObject( headers ); /** Response body */ writer.flush(); body = baos.toByteArray(); //System.out.println("[] body "+body.length ); out.writeObject( body ); } /** Reads in a serilized HttpResponseImpl object from a file * @param in the input to read the object from * @throws IOException if an exception is thrown * @throws ClassNotFoundException if an exception is thrown */ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{ /** Response string */ this.responseString = (String)in.readObject(); /** Code */ this.code = in.readInt(); /** Response headers */ this.headers = (HashMap) in.readObject(); /** Response body */ body = (byte[]) in.readObject(); //System.out.println("[] body "+body.length ); baos = new ByteArrayOutputStream(); baos.write( body ); writer = new PrintWriter( baos ); } /** * @param content The content to set. */ public void setContent(URLConnection content) { this.content = content; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy