Package ch.rolandschaer.ascrblr

Source Code of ch.rolandschaer.ascrblr.HttpRequest$Factory

/* Copyright (c) 2007 Roland Sch�r
*
* 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 ch.rolandschaer.ascrblr;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.logging.Logger;

import ch.rolandschaer.ascrblr.util.AuthenticationException;
import ch.rolandschaer.ascrblr.util.NotSupportedOperationException;
import ch.rolandschaer.ascrblr.util.ResourceNotFoundException;
import ch.rolandschaer.ascrblr.util.ServiceException;

public class HttpRequest {

    /** Logger instance. */
    public static final Logger logger = Logger.getLogger(HttpRequest.class
            .getName());

    /** Request type. */
    public enum RequestType {
        QUERY, HANDSHAKE, SUBMISSION, NOTIFY, TUNEIN, STREAM
    }

    /** Indicates if request execution has taken place. */
    private boolean executed = false;

    /** Indicated if request has any input data. */
    private boolean hasInput = false;

    /** Indicates if response has any output data. */
    private boolean hasOutput = false;

    /** HTTP connection instance. */
    private HttpURLConnection httpConn;

    /** Request URL. */
    private URL requestUrl;

    /** The Request type. */
    private RequestType type;

    /**
     * Connection timeout value. A value of -1 means that no value has been
     * configured (JDK default is used)
     */
    private int connectTimeout = -1;

    /**
     * Request timeout value. A value of -1 means that no value has been
     * configured (JDK default is used)
     */
    private int readTimeout = -1;

    /**
     * HttpRequest constructor used by the factory.
     *
     * @param type
     *            <code>RequestType</code>
     * @param requestUrl
     *            String representation of the request URL
     * @throws IOException
     * @throws ServiceException
     */
    private HttpRequest(RequestType type, URL requestUrl) throws IOException,
            ServiceException {

        this.type = type;
        this.requestUrl = requestUrl;
        httpConn = getRequestConnection(requestUrl);

        logger.info(type + " request type found");

        switch (type) {
        case QUERY:
            hasOutput = true;
            break;
        case HANDSHAKE:
            hasOutput = true;
            break;
        case NOTIFY:
            hasOutput = true;
            setRequestMethod("POST");
            break;
        case SUBMISSION:
            hasOutput = true;
            setRequestMethod("POST");
            break;
        case TUNEIN:
            hasOutput = true;
            break;
        case STREAM:
            hasOutput = true;
            break;
        default:
            throw new NotSupportedOperationException("Unknown request type: "
                    + type);

        }

    }

    /**
     * Gets actual <code>HttpURLConnection</code>. The only supported
     * protocol is <code>http://<uri></code>
     *
     * @param requestUrl
     *            String representation of the request URL
     * @return Active <code>HttpURLConnection</code>
     * @throws IOException
     */
    public HttpURLConnection getRequestConnection(URL requestUrl)
            throws IOException {

        if (!requestUrl.getProtocol().startsWith("http")) {
            throw new UnsupportedOperationException("Unsupported protocol:"
                    + requestUrl.getProtocol());
        }
        HttpURLConnection uc = (HttpURLConnection) requestUrl.openConnection();

        uc.setUseCaches(false);
        uc.setInstanceFollowRedirects(true);

        return (HttpURLConnection) uc;

    }

    /**
     * Returns the <code>OutputStream</code> of the active
     * <code>HttpURLConnection</code>.
     *
     * @return <code>OutputStream</code> of active
     *         <code>HttpURLConnection</code>
     * @throws IOException
     */
    public OutputStream getRequestStream() throws IOException {

        if (!hasInput) {
            throw new IllegalStateException(
                    "Request does not have any request data");
        }
        return httpConn.getOutputStream();

    }

    /**
     * Returns the <code>InputStream</code> of the actual
     * <code>HttpURLConnection</code>.
     *
     * @return <code>HttpURLConnection</code> response as
     *         <code>InputStream</code>
     * @throws IOException
     */
    public InputStream getResponseStream() throws IOException {

        if (!executed) {
            throw new IllegalStateException(
                    "Must call execute() before attempting to read response");
        }

        if (!hasOutput) {
            throw new IllegalStateException(
                    "Request dont have any reponse data");
        }

        return httpConn.getInputStream();
    }

    /**
     * Executes the current HTTP request and handles the response. If a read or
     * connection timeout has been defined these values will be set before the
     * request. After a successful request a internal flag <code>executed</code>
     * will be set to <code>true</code>.
     *
     * @throws IOException
     * @throws ServiceException
     */
    public void execute() throws IOException, ServiceException {

        if (readTimeout > 0) {
            httpConn.setReadTimeout(readTimeout);
        }

        if (connectTimeout > 0) {
            httpConn.setConnectTimeout(connectTimeout);
        }

        logger.info(httpConn.getRequestMethod() + " "
                + httpConn.getURL().toExternalForm());
        httpConn.connect();

        handleResponse();

        executed = true;

    }

    /**
     * Set request method. Default request method is "GET".
     *
     * @param method
     *            HTTP request method string (POST, GET , UPDATE etc.)
     * @throws ProtocolException
     */
    private void setRequestMethod(String method) throws ProtocolException {

        httpConn.setRequestMethod(method);

    }

    /**
     * Adds a request header property to the actual request specified by a
     * key-value pair. Already defined properties with the same key will not be
     * overridden.
     *
     * @param key
     *            Request keyword (e.g. accept)
     * @param value
     *            Associated value
     */
    public void setHeader(String key, String value) {

        httpConn.addRequestProperty(key, value);

    }

    /**
     * Set a read timeout value in milliseconds.
     *
     * @param timeout
     *            Read timeout value in milliseconds
     */
    public void setReadTimeout(int timeout) {
        if (timeout < 0) {
            throw new IllegalArgumentException("Timeout can not be negative.");
        }

        readTimeout = timeout;
    }

    /**
     * Set a connection timeout value.
     *
     * @param timeout
     *            Connection timeout value in milliseconds
     */
    public void setConnectTimeout(int timeout) {
        if (timeout < 0) {
            throw new IllegalArgumentException("Timeout can not be negative.");
        }

        connectTimeout = timeout;
    }

    /**
     * Handles HTTP response. If the returned response code is larger or equal
     * than 300 error handling is done.
     *
     * @throws IOException
     * @throws ServiceException
     */
    private void handleResponse() throws IOException, ServiceException {

        if (httpConn.getResponseCode() >= 300) {
            handleErrorResponse();
        }

    }

    /**
     * Handles error responses by the returned HTTP connection response code.
     *
     * @throws IOException
     * @throws ServiceException
     */
    private void handleErrorResponse() throws IOException, ServiceException {

        logger.info("Handling error response " + httpConn.getResponseCode());

        switch (httpConn.getResponseCode()) {

        case HttpURLConnection.HTTP_NOT_FOUND:
            throw new ResourceNotFoundException(httpConn);

        case HttpURLConnection.HTTP_BAD_GATEWAY:
            throw new ResourceNotFoundException(httpConn);

        case HttpURLConnection.HTTP_FORBIDDEN:
            throw new AuthenticationException(httpConn);

        default:
            throw new ServiceException(httpConn);
        }

    }

    /**
     * Request factory which creates new <code>HttpRequest</code> instances.
     */
    public static class Factory {

        /**
         * Get a new <code>HttpRequest</code>.
         *
         * @param type
         * @param requestUrl
         * @return
         * @throws IOException ?
         * @throws ServiceException ?
         */
        public final HttpRequest getRequest(RequestType type, URL requestUrl)
                throws IOException, ServiceException {
            return new HttpRequest(type, requestUrl);
        }

    }

}
TOP

Related Classes of ch.rolandschaer.ascrblr.HttpRequest$Factory

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.