Package org.restlet.ext.jetty.internal

Source Code of org.restlet.ext.jetty.internal.JettyCall

/**
* Copyright 2005-2011 Noelios Technologies.
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL 1.0 (the
* "Licenses"). You can select the license that you prefer but you may not use
* this file except in compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.opensource.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.opensource.org/licenses/lgpl-2.1.php
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.opensource.org/licenses/cddl1.php
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.com/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/

package org.restlet.ext.jetty.internal;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;

import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.HttpConnection;
import org.restlet.Response;
import org.restlet.Server;
import org.restlet.data.Parameter;
import org.restlet.data.Status;
import org.restlet.engine.adapter.ServerCall;
import org.restlet.util.Series;

/**
* Call that is used by the Jetty HTTP server connectors.
*
* @author Jerome Louvel
*/
public class JettyCall extends ServerCall {
    /** The wrapped Jetty HTTP connection. */
    private final HttpConnection connection;

    /** Indicates if the request headers were parsed and added. */
    private volatile boolean requestHeadersAdded;

    /**
     * Constructor.
     *
     * @param server
     *            The parent server.
     * @param connection
     *            The wrapped Jetty HTTP connection.
     */
    public JettyCall(Server server, HttpConnection connection) {
        super(server);
        this.connection = connection;
        this.requestHeadersAdded = false;
    }

    /**
     * Closes the end point.
     */
    @Override
    public boolean abort() {
        try {
            getConnection().getEndPoint().close();
        } catch (IOException e) {
        }

        return true;
    }

    @Override
    public void complete() {
        // Flush the response
        try {
            this.connection.flushResponse();
        } catch (IOException ex) {
            getLogger().log(Level.FINE, "Unable to flush the response", ex);
        }

        // Fully complete the response
        try {
            this.connection.completeResponse();
        } catch (IOException ex) {
            getLogger().log(Level.FINE, "Unable to complete the response", ex);
        }
    }

    @Override
    public String getClientAddress() {
        return getConnection().getRequest().getRemoteAddr();
    }

    @Override
    public int getClientPort() {
        return getConnection().getRequest().getRemotePort();
    }

    /**
     * Returns the wrapped Jetty HTTP connection.
     *
     * @return The wrapped Jetty HTTP connection.
     */
    public HttpConnection getConnection() {
        return this.connection;
    }

    /**
     * Returns the request method.
     *
     * @return The request method.
     */
    @Override
    public String getMethod() {
        return getConnection().getRequest().getMethod();
    }

    @Override
    public InputStream getRequestEntityStream(long size) {
        try {
            return getConnection().getRequest().getInputStream();
        } catch (IOException e) {
            getLogger().log(Level.WARNING,
                    "Unable to get request entity stream", e);
            return null;
        }
    }

    /**
     * Returns the list of request headers.
     *
     * @return The list of request headers.
     */
    @Override
    public Series<Parameter> getRequestHeaders() {
        final Series<Parameter> result = super.getRequestHeaders();

        if (!this.requestHeadersAdded) {
            // Copy the headers from the request object
            String headerName;
            String headerValue;
            for (final Enumeration<String> names = getConnection()
                    .getRequestFields().getFieldNames(); names
                    .hasMoreElements();) {
                headerName = names.nextElement();
                for (final Enumeration<String> values = getConnection()
                        .getRequestFields().getValues(headerName); values
                        .hasMoreElements();) {
                    headerValue = values.nextElement();
                    result.add(new Parameter(headerName, headerValue));
                }
            }

            this.requestHeadersAdded = true;
        }

        return result;
    }

    @Override
    public InputStream getRequestHeadStream() {
        // Not available
        return null;
    }

    /**
     * Returns the URI on the request line (most like a relative reference, but
     * not necessarily).
     *
     * @return The URI on the request line.
     */
    @Override
    public String getRequestUri() {
        return getConnection().getRequest().getUri().toString();
    }

    /**
     * Returns the response stream if it exists.
     *
     * @return The response stream if it exists.
     */
    @Override
    public OutputStream getResponseEntityStream() {
        try {
            return getConnection().getResponse().getOutputStream();
        } catch (IOException e) {
            getLogger().log(Level.WARNING,
                    "Unable to get response entity stream", e);
            return null;
        }
    }

    /**
     * Returns the response address.<br>
     * Corresponds to the IP address of the responding server.
     *
     * @return The response address.
     */
    @Override
    public String getServerAddress() {
        return getConnection().getRequest().getLocalAddr();
    }

    @Override
    public String getSslCipherSuite() {
        return (String) getConnection().getRequest().getAttribute(
                "javax.servlet.request.cipher_suite");
    }

    @Override
    public List<Certificate> getSslClientCertificates() {
        final Certificate[] certificateArray = (Certificate[]) getConnection()
                .getRequest().getAttribute(
                        "javax.servlet.request.X509Certificate");
        if (certificateArray != null) {
            return Arrays.asList(certificateArray);
        }

        return null;
    }

    @Override
    public Integer getSslKeySize() {
        Integer keySize = (Integer) getConnection().getRequest().getAttribute(
                "javax.servlet.request.key_size");

        if (keySize == null) {
            keySize = super.getSslKeySize();
        }

        return keySize;
    }

    @Override
    public String getSslSessionId() {
        Object sessionId = getConnection().getRequest().getAttribute(
                "javax.servlet.request.ssl_session_id");

        if (sessionId instanceof String) {
            return (String) sessionId;
        }

        return null;
    }

    /**
     * Indicates if the request was made using a confidential mean.<br>
     *
     * @return True if the request was made using a confidential mean.<br>
     */
    @Override
    public boolean isConfidential() {
        return getConnection().getRequest().isSecure();
    }

    @Override
    public boolean isConnectionBroken(Throwable exception) {
        return (exception instanceof EofException)
                || super.isConnectionBroken(exception);
    }

    @Override
    public void sendResponse(Response response) throws IOException {
        // Add call headers
        Parameter header;
        for (final Iterator<Parameter> iter = getResponseHeaders().iterator(); iter
                .hasNext();) {
            header = iter.next();
            getConnection().getResponse().addHeader(header.getName(),
                    header.getValue());
        }

        // Set the status code in the response. We do this after adding the
        // headers because when we have to rely on the 'sendError' method,
        // the Servlet containers are expected to commit their response.
        if (Status.isError(getStatusCode()) && (response.getEntity() == null)) {
            try {
                getConnection().getResponse().sendError(getStatusCode(),
                        getReasonPhrase());
            } catch (IOException ioe) {
                getLogger().log(Level.WARNING,
                        "Unable to set the response error status", ioe);
            }
        } else {
            // Send the response entity
            getConnection().getResponse().setStatus(getStatusCode());
            super.sendResponse(response);
        }

    }
}
TOP

Related Classes of org.restlet.ext.jetty.internal.JettyCall

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.