001/* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020package org.sonar.plugins.checkstyle; 021 022import java.io.File; 023import java.io.OutputStream; 024import java.util.Locale; 025 026import com.puppycrawl.tools.checkstyle.Checker; 027import com.puppycrawl.tools.checkstyle.PackageNamesLoader; 028import com.puppycrawl.tools.checkstyle.XMLLogger; 029import org.apache.commons.io.FileUtils; 030import org.apache.commons.io.IOUtils; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033import org.sonar.api.BatchExtension; 034import org.sonar.api.batch.ProjectClasspath; 035import org.sonar.api.utils.SonarException; 036import org.sonar.api.utils.TimeProfiler; 037 038public class CheckstyleExecutor implements BatchExtension { 039 private static final Logger LOG = LoggerFactory.getLogger(CheckstyleExecutor.class); 040 041 private CheckstyleConfiguration configuration; 042 private ClassLoader projectClassloader; 043 private CheckstyleAuditListener listener; 044 045 public CheckstyleExecutor(CheckstyleConfiguration configuration, CheckstyleAuditListener listener, ProjectClasspath classpath) { 046 this.configuration = configuration; 047 this.listener = listener; 048 this.projectClassloader = classpath.getClassloader(); 049 } 050 051 CheckstyleExecutor(CheckstyleConfiguration configuration, CheckstyleAuditListener listener, ClassLoader projectClassloader) { 052 this.configuration = configuration; 053 this.listener = listener; 054 this.projectClassloader = projectClassloader; 055 } 056 057 /** 058 * Execute Checkstyle and return the generated XML report. 059 */ 060 public void execute() { 061 TimeProfiler profiler = new TimeProfiler().start("Execute Checkstyle " + CheckstyleVersion.getVersion()); 062 ClassLoader initialClassLoader = Thread.currentThread().getContextClassLoader(); 063 Thread.currentThread().setContextClassLoader(PackageNamesLoader.class.getClassLoader()); 064 065 Checker checker = null; 066 OutputStream xmlOutput = null; 067 try { 068 069 checker = new Checker(); 070 checker.setClassloader(projectClassloader); 071 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader()); 072 checker.addListener(listener); 073 074 File xmlReport = configuration.getTargetXMLReport(); 075 if (xmlReport != null) { 076 LOG.info("Checkstyle output report: " + xmlReport.getAbsolutePath()); 077 xmlOutput = FileUtils.openOutputStream(xmlReport); 078 checker.addListener(new XMLLogger(xmlOutput, true)); 079 } 080 081 checker.setCharset(configuration.getCharset().name()); 082 configureLocale(checker); 083 checker.configure(configuration.getCheckstyleConfiguration()); 084 checker.process(configuration.getSourceFiles()); 085 086 profiler.stop(); 087 088 } catch (Exception e) { 089 throw new SonarException("Can not execute Checkstyle", e); 090 091 } finally { 092 if (checker != null) { 093 checker.destroy(); 094 } 095 IOUtils.closeQuietly(xmlOutput); 096 Thread.currentThread().setContextClassLoader(initialClassLoader); 097 } 098 } 099 100 private void configureLocale(Checker checker) { 101 Locale locale = configuration.getLocale(); 102 checker.setLocaleLanguage(locale.getLanguage()); 103 checker.setLocaleCountry(locale.getCountry()); 104 } 105 106}