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 */
020 package org.sonar.plugins.findbugs;
021
022 import org.apache.commons.io.FileUtils;
023 import org.apache.commons.io.IOUtils;
024 import org.apache.commons.lang.StringUtils;
025 import org.sonar.api.BatchExtension;
026 import org.sonar.api.CoreProperties;
027 import org.sonar.api.batch.ProjectClasspath;
028 import org.sonar.api.profiles.RulesProfile;
029 import org.sonar.api.resources.Project;
030 import org.sonar.api.utils.SonarException;
031 import org.sonar.plugins.findbugs.xml.ClassFilter;
032 import org.sonar.plugins.findbugs.xml.FindBugsFilter;
033 import org.sonar.plugins.findbugs.xml.Match;
034
035 import java.io.*;
036 import java.util.ArrayList;
037 import java.util.List;
038
039 /**
040 * @since 2.4
041 */
042 public class FindbugsConfiguration implements BatchExtension {
043
044 private Project project;
045 private RulesProfile profile;
046 private FindbugsProfileExporter exporter;
047 private ProjectClasspath projectClasspath;
048
049 public FindbugsConfiguration(Project project, RulesProfile profile, FindbugsProfileExporter exporter, ProjectClasspath classpath) {
050 this.project = project;
051 this.profile = profile;
052 this.exporter = exporter;
053 this.projectClasspath = classpath;
054 }
055
056 public File getTargetXMLReport() {
057 if (project.getConfiguration().getBoolean(FindbugsConstants.GENERATE_XML_KEY, FindbugsConstants.GENERATE_XML_DEFAULT_VALUE)) {
058 return new File(project.getFileSystem().getSonarWorkingDirectory(), "findbugs-result.xml");
059 }
060 return null;
061 }
062
063 public edu.umd.cs.findbugs.Project getFindbugsProject() {
064 File classesDir = project.getFileSystem().getBuildOutputDir();
065 if (classesDir == null || !classesDir.exists()) {
066 throw new SonarException("Findbugs needs sources to be compiled. "
067 + "Please build project before executing sonar and check the location of compiled classes.");
068 }
069
070 edu.umd.cs.findbugs.Project findbugsProject = new edu.umd.cs.findbugs.Project();
071 for (File dir : project.getFileSystem().getSourceDirs()) {
072 findbugsProject.addSourceDir(dir.getAbsolutePath());
073 }
074 findbugsProject.addFile(classesDir.getAbsolutePath());
075 for (File file : projectClasspath.getElements()) {
076 if (!file.equals(classesDir)) {
077 findbugsProject.addAuxClasspathEntry(file.getAbsolutePath());
078 }
079 }
080 findbugsProject.addAuxClasspathEntry(annotationsLib.getAbsolutePath());
081 findbugsProject.addAuxClasspathEntry(jsr305Lib.getAbsolutePath());
082 findbugsProject.setCurrentWorkingDirectory(project.getFileSystem().getBuildDir());
083 return findbugsProject;
084 }
085
086 public File saveIncludeConfigXml() throws IOException {
087 StringWriter conf = new StringWriter();
088 exporter.exportProfile(profile, conf);
089 return project.getFileSystem().writeToWorkingDirectory(conf.toString(), "findbugs-include.xml");
090 }
091
092 public File saveExcludeConfigXml() throws IOException {
093 FindBugsFilter findBugsFilter = new FindBugsFilter();
094 if (project.getExclusionPatterns() != null) {
095 for (String exclusion : project.getExclusionPatterns()) {
096 ClassFilter classFilter = new ClassFilter(FindbugsAntConverter.antToJavaRegexpConvertor(exclusion));
097 findBugsFilter.addMatch(new Match(classFilter));
098 }
099 }
100 return project.getFileSystem().writeToWorkingDirectory(findBugsFilter.toXml(), "findbugs-exclude.xml");
101 }
102
103 public List<File> getExcludesFilters() {
104 List<File> result = new ArrayList<File>();
105 String[] filters = project.getConfiguration().getStringArray(FindbugsConstants.EXCLUDES_FILTERS_PROPERTY);
106 for (String excludesFilterPath : filters) {
107 excludesFilterPath = StringUtils.trim(excludesFilterPath);
108 if (StringUtils.isNotBlank(excludesFilterPath)) {
109 result.add(project.getFileSystem().resolvePath(excludesFilterPath));
110 }
111 }
112 return result;
113 }
114
115 public String getEffort() {
116 return StringUtils.lowerCase(project.getConfiguration().getString(CoreProperties.FINDBUGS_EFFORT_PROPERTY,
117 CoreProperties.FINDBUGS_EFFORT_DEFAULT_VALUE));
118 }
119
120 public long getTimeout() {
121 return project.getConfiguration().getLong(CoreProperties.FINDBUGS_TIMEOUT_PROPERTY, CoreProperties.FINDBUGS_TIMEOUT_DEFAULT_VALUE);
122 }
123
124 private File jsr305Lib;
125 private File annotationsLib;
126
127 /**
128 * Invoked by PicoContainer to extract additional FindBugs libraries into temporary files.
129 */
130 public void start() {
131 jsr305Lib = copyLib("/jsr305-" + FindbugsVersion.getVersion() + ".jar");
132 annotationsLib = copyLib("/annotations-" + FindbugsVersion.getVersion() + ".jar");
133 }
134
135 /**
136 * Invoked by PicoContainer to remove temporary files.
137 */
138 public void stop() {
139 jsr305Lib.delete();
140 annotationsLib.delete();
141 }
142
143 private File copyLib(String name) {
144 try {
145 InputStream is = getClass().getResourceAsStream(name);
146 File temp = File.createTempFile("findbugs", ".jar");
147 OutputStream os = FileUtils.openOutputStream(temp);
148 IOUtils.copy(is, os);
149 return temp;
150 } catch (IOException e) {
151 throw new SonarException(e);
152 }
153 }
154 }