org.sonar.plugins.web.markup.validation.RemoteValidationService.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.plugins.web.markup.validation.RemoteValidationService.java

Source

/*
 * Sonar W3C Markup Validation Plugin
 * Copyright (C) 2010 Matthijs Galesloot
 * dev@sonar.codehaus.org
 *
 * 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.sonar.plugins.web.markup.validation;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.sonar.api.utils.SonarException;
import org.sonar.plugins.web.markup.constants.MarkupValidatorConstants;

/**
 * RemoteValidationService provides a framework for validators using a remote service.
 *
 * @author Matthijs Galesloot
 * @since 1.0
 */
public abstract class RemoteValidationService {

    private static final long DEFAULT_PAUSE_BETWEEN_VALIDATIONS = 1000L;

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

    private HttpClient client;

    private final Configuration configuration;

    private Long waitBetweenRequests; // MILLISECONDS

    public RemoteValidationService(Configuration configuration) {
        this.configuration = configuration;

        waitBetweenRequests = configuration.getLong(MarkupValidatorConstants.PAUSE_BETWEEN_VALIDATIONS,
                DEFAULT_PAUSE_BETWEEN_VALIDATIONS);
    }

    /**
     * Execute post method to the remote validation service. On errors, the post is tried 3 times with a waiting time of 1 second.
     */
    protected HttpResponse executePostMethod(HttpPost post) {

        int retries = 3;

        for (int i = 0; i < retries; i++) {
            HttpResponse response = null;
            try {
                response = getClient().execute(post);
                if (response.getStatusLine().getStatusCode() == 200
                        || response.getStatusLine().getStatusCode() == 302) {
                    return response;
                } else {
                    try {
                        EntityUtils.consume(response.getEntity());
                    } catch (IOException e) {
                        // ignore
                    }

                    LOG.warn("Bad http response: " + response.getStatusLine().getStatusCode()
                            + ", retrying after 1 second...");
                    sleep(waitBetweenRequests);
                }
            } catch (UnknownHostException e) {
                if (useProxy()) {
                    LOG.warn("Unknown host, retry without proxy...");
                    client.getConnectionManager().shutdown();
                    client = new DefaultHttpClient();
                }
            } catch (IOException e) {
                throw new SonarException(e);
            }
        }
        return null;
    }

    private HttpClient getClient() {
        if (client == null) {
            client = new DefaultHttpClient();
            if (useProxy()) {
                LOG.debug("Proxy " + getProxyHost() + ":" + getProxyPort());
                HttpHost proxy = new HttpHost(getProxyHost(), getProxyPort());
                client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
            }
        }
        return client;
    }

    protected String getProperty(File file, String property) {
        File propertiesFile = new File(file.getPath() + ".txt");

        if (propertiesFile.exists()) {
            Properties properties = new Properties();

            InputStream in = null;
            try {
                in = new FileInputStream(propertiesFile);
                properties.load(in);
                if (properties.containsKey(property)) {
                    return properties.getProperty(property);
                }
            } catch (IOException e) {
                return null;
            } finally {
                IOUtils.closeQuietly(in);
            }
        }
        return null;
    }

    /**
     * Returns the proxy host.
     *
     * @return proxy host
     */
    private String getProxyHost() {
        return configuration.getString(MarkupValidatorConstants.PROXY_HOST, null);
    }

    /**
     * Returns the proxy port.
     */
    private int getProxyPort() {
        return configuration.getInt(MarkupValidatorConstants.PROXY_PORT, -1);
    }

    protected Long getWaitBetweenRequests() {
        return waitBetweenRequests;
    }

    protected void setWaitBetweenRequests(Long waitBetweenRequests) {
        this.waitBetweenRequests = waitBetweenRequests;
    }

    protected void sleep(long sleepInterval) {
        try {
            Thread.sleep(sleepInterval);
        } catch (InterruptedException ie) {
            throw new SonarException(ie);
        }
    }

    /**
     * Returns whether or not to use a proxy.
     *
     * @return true/false
     */
    private boolean useProxy() {
        return getProxyHost() != null && getProxyPort() > 0;
    }

    protected void waitBetweenValidationRequests() {
        sleep(waitBetweenRequests);
    }
}