org.openqa.jetty.http.ajp.AJP13Connection.java Source code

Java tutorial

Introduction

Here is the source code for org.openqa.jetty.http.ajp.AJP13Connection.java

Source

// ========================================================================
// $Id: AJP13Connection.java,v 1.38 2006/11/22 20:21:30 gregwilkins Exp $
// Copyright 200-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed 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.openqa.jetty.http.ajp;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.apache.commons.logging.Log;
import org.openqa.jetty.log.LogFactory;
import org.openqa.jetty.http.HttpConnection;
import org.openqa.jetty.http.HttpContext;
import org.openqa.jetty.http.HttpFields;
import org.openqa.jetty.http.HttpMessage;
import org.openqa.jetty.http.HttpRequest;
import org.openqa.jetty.http.HttpResponse;
import org.openqa.jetty.http.Version;
import org.openqa.jetty.util.LineInput;
import org.openqa.jetty.util.LogSupport;
import org.openqa.jetty.util.URI;

/* ------------------------------------------------------------ */
/**
 * @version $Id: AJP13Connection.java,v 1.38 2006/11/22 20:21:30 gregwilkins Exp $
 * @author Greg Wilkins (gregw)
 */
public class AJP13Connection extends HttpConnection {
    private static Log log = LogFactory.getLog(AJP13Connection.class);

    private AJP13Listener _listener;
    private AJP13InputStream _ajpIn;
    private AJP13OutputStream _ajpOut;
    private String _remoteHost;
    private String _remoteAddr;
    private String _serverName;
    private int _serverPort;
    private boolean _isSSL;

    /* ------------------------------------------------------------ */
    public AJP13Connection(AJP13Listener listener, InputStream in, OutputStream out, Socket socket, int bufferSize)
            throws IOException {
        super(listener, null, new AJP13InputStream(in, out, bufferSize), out, socket);

        LineInput lin = (LineInput) getInputStream().getInputStream();
        _ajpIn = (AJP13InputStream) lin.getInputStream();
        _ajpOut = new AJP13OutputStream(getOutputStream().getOutputStream(), bufferSize);
        _ajpOut.setCommitObserver(this);
        getOutputStream().setBufferedOutputStream(_ajpOut);
        _listener = listener;
    }

    /* ------------------------------------------------------------ */
    /**
     * Get the Remote address.
     * 
     * @return the remote address
     */
    public InetAddress getRemoteInetAddress() {
        return null;
    }

    /* ------------------------------------------------------------ */
    public void destroy() {
        if (_ajpIn != null)
            _ajpIn.destroy();
        _ajpIn = null;
        if (_ajpOut != null)
            _ajpOut.destroy();
        _ajpOut = null;
        _remoteHost = null;
        _remoteAddr = null;
        _serverName = null;
    }

    /* ------------------------------------------------------------ */
    /**
     * Get the Remote address.
     * 
     * @return the remote host name
     */
    public String getRemoteAddr() {
        return _remoteAddr;
    }

    /* ------------------------------------------------------------ */
    /**
     * Get the Remote address.
     * 
     * @return the remote host name
     */
    public String getRemoteHost() {
        return _remoteHost;
    }

    /* ------------------------------------------------------------ */
    /**
     * Get the listeners HttpServer . Conveniance method equivalent to
     * getListener().getHost().
     * 
     * @return HttpServer.
     */
    public String getServerName() {
        return _serverName;
    }

    /* ------------------------------------------------------------ */
    /**
     * Get the listeners Port . Conveniance method equivalent to
     * getListener().getPort().
     * 
     * @return HttpServer.
     */
    public int getServerPort() {
        return _serverPort;
    }

    /* ------------------------------------------------------------ */
    /**
     * Get the listeners Default scheme. Conveniance method equivalent to
     * getListener().getDefaultProtocol().
     * 
     * @return HttpServer.
     */
    public String getDefaultScheme() {
        return _isSSL ? HttpMessage.__SSL_SCHEME : super.getDefaultScheme();
    }

    /* ------------------------------------------------------------ */
    public boolean isSSL() {
        return _isSSL;
    }

    /* ------------------------------------------------------------ */
    public boolean handleNext() {
        AJP13RequestPacket packet = null;
        HttpRequest request = getRequest();
        HttpResponse response = getResponse();
        HttpContext context = null;
        boolean gotRequest = false;
        _persistent = true;
        _keepAlive = true;

        try {
            try {
                packet = null;
                packet = _ajpIn.nextPacket();
                if (packet == null)
                    return false;
                if (packet.getDataSize() == 0)
                    return true;
            } catch (IOException e) {
                LogSupport.ignore(log, e);
                return false;
            }

            int type = packet.getByte();
            if (log.isDebugEnabled())
                log.debug("AJP13 type=" + type + " size=" + packet.unconsumedData());

            switch (type) {
            case AJP13Packet.__FORWARD_REQUEST:
                request.setTimeStamp(System.currentTimeMillis());

                request.setState(HttpMessage.__MSG_EDITABLE);
                request.setMethod(packet.getMethod());
                request.setVersion(packet.getString());
                String version = packet.getString();
                try {
                    request.setVersion(version);
                } catch (Exception e) {
                    log.warn("Bad version" + version, e);
                    log.warn(packet.toString());
                }

                String path = packet.getString();
                int sc = path.lastIndexOf(";");
                if (sc < 0)
                    request.setPath(URI.encodePath(path));
                else
                    request.setPath(URI.encodePath(path.substring(0, sc)) + path.substring(sc));

                _remoteAddr = packet.getString();
                _remoteHost = packet.getString();
                _serverName = packet.getString();
                _serverPort = packet.getInt();
                _isSSL = packet.getBoolean();

                // Check keep alive
                _keepAlive = request.getDotVersion() >= 1;

                // Headers
                int h = packet.getInt();
                for (int i = 0; i < h; i++) {
                    String hdr = packet.getHeader();
                    String val = packet.getString();
                    request.addField(hdr, val);
                    if (!_keepAlive && hdr.equalsIgnoreCase(HttpFields.__Connection)
                            && val.equalsIgnoreCase(HttpFields.__KeepAlive))
                        _keepAlive = true;
                }

                // RestishHandler other attributes
                byte attr = packet.getByte();
                while ((0xFF & attr) != 0xFF) {
                    String value = (attr == 11) ? null : packet.getString();
                    switch (attr) {
                    case 11: // key size
                        request.setAttribute("javax.servlet.request.key_size", new Integer(packet.getInt()));
                        break;
                    case 10: // request attribute
                        request.setAttribute(value, packet.getString());
                        break;
                    case 9: // SSL session
                        request.setAttribute("javax.servlet.request.ssl_session", value);
                        break;
                    case 8: // SSL cipher
                        request.setAttribute("javax.servlet.request.cipher_suite", value);
                        break;
                    case 7: // SSL cert
                        // request.setAttribute("javax.servlet.request.X509Certificate",value);
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        InputStream certstream = new ByteArrayInputStream(value.getBytes());
                        X509Certificate cert = (X509Certificate) cf.generateCertificate(certstream);
                        X509Certificate certs[] = { cert };
                        request.setAttribute("javax.servlet.request.X509Certificate", certs);
                        break;
                    case 6: // JVM Route
                        request.setAttribute("org.openqa.jetty.http.ajp.JVMRoute", value);
                        break;
                    case 5: // Query String
                        request.setQuery(value);
                        break;
                    case 4: // AuthType
                        request.setAuthType(value);
                        break;
                    case 3: // Remote User
                        request.setAuthUser(value);
                        break;

                    case 2: // servlet path not implemented
                    case 1: // _context not implemented
                    default:
                        log.warn("Unknown attr: " + attr + "=" + value);
                    }

                    attr = packet.getByte();
                }

                _listener.customizeRequest(this, request);

                gotRequest = true;
                statsRequestStart();
                request.setState(HttpMessage.__MSG_RECEIVED);

                // Complete response
                if (request.getContentLength() == 0 && request.getField(HttpFields.__TransferEncoding) == null)
                    _ajpIn.close();

                // Prepare response
                response.setState(HttpMessage.__MSG_EDITABLE);
                response.setVersion(HttpMessage.__HTTP_1_1);
                response.setDateField(HttpFields.__Date, _request.getTimeStamp());
                if (!Version.isParanoid())
                    response.setField(HttpFields.__Server, Version.getDetail());

                // Service request
                if (log.isDebugEnabled())
                    log.debug("REQUEST:\n" + request);
                context = service(request, response);
                if (log.isDebugEnabled())
                    log.debug("RESPONSE:\n" + response);

                break;

            default:
                if (log.isDebugEnabled())
                    log.debug("Ignored: " + packet);
                _persistent = false;
            }

        } catch (SocketException e) {
            LogSupport.ignore(log, e);
            _persistent = false;
        } catch (Exception e) {
            log.warn(LogSupport.EXCEPTION, e);
            _persistent = false;
            try {
                if (gotRequest)
                    _ajpOut.close();
            } catch (IOException e2) {
                LogSupport.ignore(log, e2);
            }
        } finally {
            // abort if nothing received.
            if (packet == null || !gotRequest)
                return false;

            // flush and end the output
            try {
                // Consume unread input.
                // while(_ajpIn.skip(4096)>0 || _ajpIn.read()>=0);

                // end response
                getOutputStream().close();
                if (!_persistent)
                    _ajpOut.end();

                // Close the outout
                _ajpOut.close();

                // reset streams
                getOutputStream().resetStream();
                getOutputStream().addObserver(this);
                getInputStream().resetStream();
                _ajpIn.resetStream();
                _ajpOut.resetStream();
            } catch (Exception e) {
                log.debug(LogSupport.EXCEPTION, e);
                _persistent = false;
            } finally {
                statsRequestEnd();
                if (context != null)
                    context.log(request, response, -1);
            }
        }
        return _persistent;
    }

    /* ------------------------------------------------------------ */
    protected void firstWrite() throws IOException {
        log.debug("ajp13 firstWrite()");
    }

    /* ------------------------------------------------------------ */
    protected void commit() throws IOException {
        log.debug("ajp13 commit()");
        if (_response.isCommitted())
            return;
        _request.setHandled(true);
        getOutputStream().writeHeader(_response);
    }

    /* ------------------------------------------------------------ */
    protected void setupOutputStream() throws IOException {
        // Nobble the OutputStream for HEAD requests
        if (HttpRequest.__HEAD.equals(getRequest().getMethod()))
            getOutputStream().nullOutput();
    }
}