org.eclipse.skalli.model.ext.maven.internal.HttpMavenPomResolverBase.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.skalli.model.ext.maven.internal.HttpMavenPomResolverBase.java

Source

/*******************************************************************************
 * Copyright (c) 2010-2014 SAP AG and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     SAP AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.skalli.model.ext.maven.internal;

import static org.apache.http.HttpStatus.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.UUID;

import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.params.HttpParams;
import org.eclipse.skalli.commons.HttpUtils;
import org.eclipse.skalli.model.ValidationException;
import org.eclipse.skalli.services.destination.Destinations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class HttpMavenPomResolverBase extends MavenPomResolverBase {

    private static final Logger LOG = LoggerFactory.getLogger(HttpMavenPomResolverBase.class);

    /**
     * Calculates the <code>URL</code> corresponding to the parameters <code>scmLocation</code> and <code>relativePath</code>.
     * @throws MalformedURLException in case the <code>URL</code> could not be created
     */
    protected abstract URL resolvePath(String scmLocation, String relativePath) throws MalformedURLException;

    /**
     * Returns an input stream, from which one can directly read the content of the POM.
     * @param entity  the HTTP entity to convert to a stream.
     * @param relativePath  the path of the POM relative to the root of the project's source code.
     * @return an input stream for the content of the POM.
     * @throws IOException  if an i/o problem occured.
     */
    protected abstract InputStream asPomInputStream(HttpEntity entity, String relativePath) throws IOException;

    @Override
    public MavenPom getMavenPom(UUID project, String scmLocation, String relativePath) throws IOException {
        URL url = resolvePath(scmLocation, relativePath);
        if (url == null) {
            throw new IOException(MessageFormat.format(
                    "Failed to calculate an URL for downloading of a POM based on SCM location \"{0}\" and relative path \"{1}\"",
                    scmLocation, relativePath));
        }
        try {
            return parse(url, relativePath, false);
        } catch (Exception e) {
            try {
                parse(url, relativePath, true);
            } catch (Exception e1) {
                LOG.error(MessageFormat.format("Unexpected error occured while logging the response from {0}",
                        url.toExternalForm()), e);
            }

            throw new IOException(MessageFormat.format(
                    "Failed to download POM from {0} (scmLocation=\"{1}\", relativePath =\"{2}\")",
                    url.toExternalForm(), scmLocation, relativePath), e);
        }
    }

    /**
     * @param logResponse = true will return an default empty MavenPom  and log the content read from the
     * url with level Error to LOG; if set to false the method parse is called.
     */
    private MavenPom parse(URL url, String relativePath, boolean logResponse)
            throws IOException, HttpException, ValidationException {
        HttpClient client = Destinations.getClient(url);
        if (client == null) {
            return null;
        }
        HttpParams params = client.getParams();
        HttpClientParams.setRedirecting(params, false); // we want to find 301 MOVED PERMANTENTLY
        HttpResponse response = null;
        try {
            LOG.info("GET " + url); //$NON-NLS-1$
            HttpGet method = new HttpGet(url.toExternalForm());
            response = client.execute(method);
            int status = response.getStatusLine().getStatusCode();
            LOG.info(status + " " + response.getStatusLine().getReasonPhrase()); //$NON-NLS-1$
            if (status == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                if (entity == null) {
                    return null;
                }
                if (!logResponse) {
                    return parse(asPomInputStream(entity, relativePath));
                } else {
                    logResponse(url, entity);
                    return new MavenPom();
                }
            } else {
                String statusText = response.getStatusLine().getReasonPhrase();
                switch (status) {
                case SC_NOT_FOUND:
                    throw new HttpException(MessageFormat.format("{0} not found", url));
                case SC_UNAUTHORIZED:
                    throw new HttpException(MessageFormat.format("{0} found but authentication required: {1} {2}",
                            url, status, statusText));
                case SC_INTERNAL_SERVER_ERROR:
                case SC_SERVICE_UNAVAILABLE:
                case SC_GATEWAY_TIMEOUT:
                case SC_INSUFFICIENT_STORAGE:
                    throw new HttpException(MessageFormat.format(
                            "{0} not found. Host reports a temporary problem: {1} {2}", url, status, statusText));
                case SC_MOVED_PERMANENTLY:
                    throw new HttpException(
                            MessageFormat.format("{0} not found. Resource has been moved permanently to {1}", url,
                                    response.getFirstHeader("Location")));
                default:
                    throw new HttpException(MessageFormat.format("{0} not found. Host responded with {1} {2}", url,
                            status, statusText));
                }
            }
        } finally {
            HttpUtils.consumeQuietly(response);
        }
    }

    private void logResponse(URL url, HttpEntity entity) throws IOException {
        try {
            StringWriter writer = new StringWriter();

            String encoding = null;
            if (entity.getContentEncoding() != null) {
                encoding = entity.getContentEncoding().getValue();
            }
            IOUtils.copy(entity.getContent(), writer, encoding);
            String content = writer.toString();

            StringBuilder sb = new StringBuilder();
            sb.append("Response from ").append(url.toExternalForm()).append(":\n");
            Header contentType = entity.getContentType();
            sb.append("Content-Type: ")
                    .append(contentType == null ? "<not available>" : entity.getContentType().getValue())
                    .append("\n");
            sb.append("Content-Encoding: ").append(encoding == null ? "<not available>" : encoding).append("\n");
            sb.append("\n").append(content);
            LOG.error(sb.toString());
        } catch (IOException e) {
            throw new IOException(MessageFormat.format(
                    "Unexpected exception while trying to consume the response from {0}", url.toExternalForm()), e);
        }
    }
}