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 com.puppycrawl.tools.checkstyle.ConfigurationLoader;
023import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
024import com.puppycrawl.tools.checkstyle.PropertiesExpander;
025import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
026import org.apache.commons.io.IOUtils;
027import org.apache.commons.lang.CharEncoding;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030import org.sonar.api.BatchExtension;
031import org.sonar.api.CoreProperties;
032import org.sonar.api.Property;
033import org.sonar.api.config.Settings;
034import org.sonar.api.profiles.RulesProfile;
035import org.sonar.api.resources.InputFileUtils;
036import org.sonar.api.resources.Java;
037import org.sonar.api.resources.ProjectFileSystem;
038import org.sonar.api.utils.SonarException;
039
040import java.io.File;
041import java.io.FileOutputStream;
042import java.io.IOException;
043import java.io.OutputStreamWriter;
044import java.io.Writer;
045import java.nio.charset.Charset;
046import java.util.List;
047import java.util.Locale;
048import java.util.Properties;
049
050@org.sonar.api.Properties({
051  @Property(
052    key = CheckstyleConfiguration.PROPERTY_GENERATE_XML,
053    defaultValue = "false",
054    name = "Generate XML Report",
055    project = false, global = false
056  )
057})
058public class CheckstyleConfiguration implements BatchExtension {
059
060  private static final Logger LOG = LoggerFactory.getLogger(CheckstyleConfiguration.class);
061  public static final String PROPERTY_GENERATE_XML = "sonar.checkstyle.generateXml";
062
063  private final CheckstyleProfileExporter confExporter;
064  private final RulesProfile profile;
065  private final Settings conf;
066  private final ProjectFileSystem fileSystem;
067
068  public CheckstyleConfiguration(Settings conf, CheckstyleProfileExporter confExporter, RulesProfile profile, ProjectFileSystem fileSystem) {
069    this.conf = conf;
070    this.confExporter = confExporter;
071    this.profile = profile;
072    this.fileSystem = fileSystem;
073  }
074
075  public File getXMLDefinitionFile() {
076    Writer writer = null;
077    File xmlFile = new File(fileSystem.getSonarWorkingDirectory(), "checkstyle.xml");
078    try {
079      writer = new OutputStreamWriter(new FileOutputStream(xmlFile, false), CharEncoding.UTF_8);
080      confExporter.exportProfile(profile, writer);
081      writer.flush();
082      return xmlFile;
083
084    } catch (IOException e) {
085      throw new SonarException("Fail to save the Checkstyle configuration to " + xmlFile.getPath(), e);
086
087    } finally {
088      IOUtils.closeQuietly(writer);
089    }
090  }
091
092  public List<File> getSourceFiles() {
093    return InputFileUtils.toFiles(fileSystem.mainFiles(Java.KEY));
094  }
095
096  public File getTargetXMLReport() {
097    if (conf.getBoolean(PROPERTY_GENERATE_XML)) {
098      return new File(fileSystem.getSonarWorkingDirectory(), "checkstyle-result.xml");
099    }
100    return null;
101  }
102
103  public com.puppycrawl.tools.checkstyle.api.Configuration getCheckstyleConfiguration() throws CheckstyleException {
104    File xmlConfig = getXMLDefinitionFile();
105
106    LOG.info("Checkstyle configuration: " + xmlConfig.getAbsolutePath());
107    com.puppycrawl.tools.checkstyle.api.Configuration configuration = toCheckstyleConfiguration(xmlConfig);
108    defineCharset(configuration);
109    return configuration;
110  }
111
112  static com.puppycrawl.tools.checkstyle.api.Configuration toCheckstyleConfiguration(File xmlConfig) throws CheckstyleException {
113    return ConfigurationLoader.loadConfiguration(xmlConfig.getAbsolutePath(), new PropertiesExpander(new Properties()));
114  }
115
116  private void defineCharset(com.puppycrawl.tools.checkstyle.api.Configuration configuration) {
117    com.puppycrawl.tools.checkstyle.api.Configuration[] modules = configuration.getChildren();
118    for (com.puppycrawl.tools.checkstyle.api.Configuration module : modules) {
119      if (("Checker".equals(module.getName()) || "com.puppycrawl.tools.checkstyle.Checker".equals(module.getName())) && (module instanceof DefaultConfiguration)) {
120        Charset charset = getCharset();
121        LOG.info("Checkstyle charset: " + charset.name());
122        ((DefaultConfiguration) module).addAttribute("charset", charset.name());
123      }
124    }
125  }
126
127  public Locale getLocale() {
128    return new Locale(conf.getString(CoreProperties.CORE_VIOLATION_LOCALE_PROPERTY));
129  }
130
131  public Charset getCharset() {
132    Charset charset = fileSystem.getSourceCharset();
133    if (charset == null) {
134      charset = Charset.forName(System.getProperty("file.encoding", CharEncoding.UTF_8));
135    }
136    return charset;
137  }
138}