org.esigate.HttpErrorPage.java Source code

Java tutorial

Introduction

Here is the source code for org.esigate.HttpErrorPage.java

Source

/* 
 * 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.esigate;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import org.apache.commons.io.output.StringBuilderWriter;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.util.EntityUtils;
import org.esigate.http.BasicCloseableHttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Exception thrown when an error occurred retrieving a resource.
 * <p>
 * This exception can include a HTTP response (with error page body) or a String body.
 * 
 * @author Francois-Xavier Bonnet
 * @author Nicolas Richeton
 */
public class HttpErrorPage extends Exception {
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = LoggerFactory.getLogger(HttpErrorPage.class);
    private final CloseableHttpResponse httpResponse;

    private static HttpEntity toMemoryEntity(String content) {
        return new StringEntity(content, "UTF-8");
    }

    private static HttpEntity toMemoryEntity(Exception exception) {
        StringBuilderWriter out = new StringBuilderWriter(Parameters.DEFAULT_BUFFER_SIZE);
        PrintWriter pw = new PrintWriter(out);
        exception.printStackTrace(pw);
        String content = out.toString();
        try {
            return toMemoryEntity(content);
        } finally {
            pw.close();
        }
    }

    private static HttpEntity toMemoryEntity(HttpEntity httpEntity) {
        if (httpEntity == null) {
            return null;
        }
        HttpEntity memoryEntity;
        try {
            byte[] content = EntityUtils.toByteArray(httpEntity);
            ByteArrayEntity byteArrayEntity = new ByteArrayEntity(content, ContentType.get(httpEntity));
            Header contentEncoding = httpEntity.getContentEncoding();
            if (contentEncoding != null) {
                byteArrayEntity.setContentEncoding(contentEncoding);
            }
            memoryEntity = byteArrayEntity;
        } catch (IOException e) {
            StringBuilderWriter out = new StringBuilderWriter(Parameters.DEFAULT_BUFFER_SIZE);
            PrintWriter pw = new PrintWriter(out);
            e.printStackTrace(pw);
            pw.close();
            memoryEntity = new StringEntity(out.toString(), ContentType.getOrDefault(httpEntity));
        }
        return memoryEntity;
    }

    /**
     * Create an HTTP error page exception from an Http response.
     * 
     * @param httpResponse
     *            backend response.
     */
    public HttpErrorPage(CloseableHttpResponse httpResponse) {
        super(httpResponse.getStatusLine().getStatusCode() + " " + httpResponse.getStatusLine().getReasonPhrase());
        this.httpResponse = httpResponse;
        // Consume the entity and replace it with an in memory Entity
        httpResponse.setEntity(toMemoryEntity(httpResponse.getEntity()));
    }

    /**
     * Create an HTTP response from a String content wich will be used as the response entity.
     * 
     * @param statusCode
     * @param statusMessage
     * @param content
     */
    public HttpErrorPage(int statusCode, String statusMessage, String content) {
        super(statusCode + " " + statusMessage);
        this.httpResponse = HttpErrorPage.generateHttpResponse(statusCode, statusMessage);
        this.httpResponse.setEntity(toMemoryEntity(content));
    }

    /**
     * Create an HTTP response from an exception. This exception stack trace will be showed to the end user.
     * 
     * @param statusCode
     * @param statusMessage
     * @param exception
     */
    public HttpErrorPage(int statusCode, String statusMessage, Exception exception) {
        super(statusCode + " " + statusMessage, exception);
        this.httpResponse = HttpErrorPage.generateHttpResponse(statusCode, statusMessage);
        this.httpResponse.setEntity(toMemoryEntity(exception));
    }

    /**
     * Get HTTP response enclosed in this exception.
     * 
     * @return HTTP response
     */
    public CloseableHttpResponse getHttpResponse() {
        return this.httpResponse;
    }

    public static CloseableHttpResponse generateHttpResponse(Exception exception) {
        if (exception instanceof HttpHostConnectException) {
            return generateHttpResponse(HttpStatus.SC_BAD_GATEWAY, "Connection refused");
        } else if (exception instanceof ConnectionPoolTimeoutException) {
            return generateHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Connection pool timeout");
        } else if (exception instanceof ConnectTimeoutException) {
            return generateHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Connect timeout");
        } else if (exception instanceof SocketTimeoutException) {
            return generateHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Socket timeout");
        } else if (exception instanceof SocketException) {
            return generateHttpResponse(HttpStatus.SC_BAD_GATEWAY, "Socket Exception");
        } else if (exception instanceof ClientProtocolException) {
            String message = exception.getMessage();
            if (message == null && exception.getCause() != null) {
                message = exception.getCause().getMessage();
            }
            return generateHttpResponse(HttpStatus.SC_BAD_GATEWAY, "Protocol error: " + message);
        } else {
            LOG.error("Error retrieving URL", exception);
            return generateHttpResponse(HttpStatus.SC_BAD_GATEWAY, "Error retrieving URL");
        }
    }

    public static CloseableHttpResponse generateHttpResponse(int statusCode, String statusText) {
        CloseableHttpResponse result = BasicCloseableHttpResponse
                .adapt(new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, statusCode, statusText)));
        result.setEntity(toMemoryEntity(statusText));
        return result;
    }

}