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

Java tutorial

Introduction

Here is the source code for org.sonar.plugins.web.markup.validation.MarkupValidator.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.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.List;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.sonar.api.resources.InputFile;
import org.sonar.api.utils.SonarException;
import org.sonar.plugins.web.api.ProjectFileManager;
import org.sonar.plugins.web.markup.constants.MarkupValidatorConstants;

/**
 * Remote Validator using the W3C Markup Validation Service.
 *
 * @see http://validator.w3.org/docs/api.html
 *
 * @author Matthijs Galesloot
 * @since 1.0
 *
 */
public final class MarkupValidator extends RemoteValidationService {

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

    private static final String OUTPUT = "output";

    // suffix for report with soap response
    private static final String REPORT_SUFFIX = ".smv";
    private static final String SOAP12 = "soap12";

    private static final String TEXT_HTML_CONTENT_TYPE = "text/html";

    private static final String UPLOADED_FILE = "uploaded_file";

    private final File buildDir;
    private final String validationUrl;

    public MarkupValidator(Configuration configuration, File buildDir) {
        super(configuration);

        this.buildDir = buildDir;

        this.validationUrl = configuration.getString(MarkupValidatorConstants.VALIDATION_URL,
                MarkupValidatorConstants.DEFAULT_URL);

        if (getWaitBetweenRequests() < 1000L && this.validationUrl.contains(MarkupValidatorConstants.DEFAULT_URL)) {
            LOG.warn("Minimum waiting time between requests is 1000 milliseconds");
            setWaitBetweenRequests(1000L);
        }
    }

    /**
     * Post contents of HTML file to the W3C validation service. In return, receive a Soap response message.
     *
     * @see http://validator.w3.org/docs/api.html
     */
    private void postHtmlContents(InputFile inputfile) {

        HttpPost post = new HttpPost(validationUrl);
        HttpResponse response = null;

        post.addHeader("User-Agent", "sonar-w3c-markup-validation-plugin/1.0");

        try {

            LOG.info("W3C Validate: " + inputfile.getRelativePath());

            // file upload
            MultipartEntity multiPartRequestEntity = new MultipartEntity();
            String charset = CharsetDetector.detect(inputfile.getFile());
            FileBody fileBody = new FileBody(inputfile.getFile(), TEXT_HTML_CONTENT_TYPE, charset);
            multiPartRequestEntity.addPart(UPLOADED_FILE, fileBody);

            // set output format
            multiPartRequestEntity.addPart(OUTPUT, new StringBody(SOAP12));

            post.setEntity(multiPartRequestEntity);
            response = executePostMethod(post);

            // write response to report file
            if (response != null) {
                writeResponse(response, inputfile);
            }

        } catch (UnsupportedEncodingException e) {
            LOG.error(e);
        } finally {
            // release any connection resources used by the method
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException ioe) {
                    LOG.debug(ioe);
                }
            }
        }
    }

    /**
     * Create the path to the report file.
     */
    public File reportFile(InputFile inputfile) {
        return new File(buildDir.getPath() + "/"
                + ProjectFileManager.getRelativePath(inputfile.getFile(), inputfile.getFileBaseDir())
                + REPORT_SUFFIX);
    }

    /**
     * Validate a file with the W3C Markup Validation Service.
     */
    public void validateFile(InputFile inputfile) {
        postHtmlContents(inputfile);
    }

    /**
     * Validate a list of files with the W3C Markup Validation Service
     */
    public void validateFiles(List<InputFile> inputfiles) {

        int n = 0;
        for (InputFile inputfile : inputfiles) {
            // skip analysis if the report already exists
            File reportFile = reportFile(inputfile);
            if (!reportFile.exists()) {
                if (n++ > 0) {
                    waitBetweenValidationRequests();
                }
                validateFile(inputfile);
            }
        }
    }

    private void writeResponse(HttpResponse response, InputFile inputfile) {
        if (response.getStatusLine().getStatusCode() == 200) {
            LOG.info("Validated:" + inputfile.getRelativePath());

            File reportFile = reportFile(inputfile);
            reportFile.getParentFile().mkdirs();
            Writer writer = null;
            try {
                writer = new FileWriter(reportFile);
                IOUtils.copy(response.getEntity().getContent(), writer);
            } catch (IOException e) {
                throw new SonarException(e);
            } finally {
                IOUtils.closeQuietly(writer);
            }
        } else {
            LOG.error("Response " + response.getStatusLine().getStatusCode() + ": "
                    + response.getStatusLine().getReasonPhrase());
            LOG.error("Failed to validate file: " + inputfile.getRelativePath());
        }
    }
}