001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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 License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.batch.scan2;
021
022 import org.apache.commons.io.FileUtils;
023 import org.apache.commons.io.IOUtils;
024 import org.slf4j.Logger;
025 import org.slf4j.LoggerFactory;
026 import org.sonar.api.batch.bootstrap.ProjectDefinition;
027 import org.sonar.api.batch.fs.FileSystem;
028 import org.sonar.api.batch.fs.InputFile;
029 import org.sonar.api.batch.sensor.issue.Issue;
030 import org.sonar.api.batch.sensor.measure.Measure;
031 import org.sonar.api.config.Settings;
032 import org.sonar.api.utils.ZipUtils;
033 import org.sonar.api.utils.text.JsonWriter;
034
035 import java.io.File;
036 import java.io.FileWriter;
037 import java.io.IOException;
038 import java.util.Properties;
039
040 public final class AnalysisPublisher {
041
042 private static final Logger LOG = LoggerFactory.getLogger(AnalysisPublisher.class);
043 private final Settings settings;
044 private final FileSystem fs;
045 private final AnalyzerMeasureCache measureCache;
046 private final ProjectDefinition def;
047 private final AnalyzerIssueCache issueCache;
048
049 public AnalysisPublisher(ProjectDefinition def, Settings settings, FileSystem fs,
050 AnalyzerMeasureCache measureCache,
051 AnalyzerIssueCache analyzerIssueCache) {
052 this.def = def;
053 this.settings = settings;
054 this.fs = fs;
055 this.measureCache = measureCache;
056 this.issueCache = analyzerIssueCache;
057 }
058
059 public void execute() {
060 if (settings.getBoolean("sonar.skipPublish")) {
061 LOG.debug("Publishing of results is skipped");
062 return;
063 }
064 File exportDir = prepareExportDir();
065
066 exportAnalysisProperties(exportDir);
067
068 exportSourceFiles(exportDir);
069
070 exportMeasures(exportDir);
071
072 exportIssues(exportDir);
073
074 createZip(exportDir);
075
076 }
077
078 private void createZip(File exportDir) {
079 File exportZip = new File(fs.workDir(), def.getKey() + "-export.zip");
080 try {
081 ZipUtils.zipDir(exportDir, exportZip);
082 FileUtils.deleteDirectory(exportDir);
083 } catch (IOException e) {
084 throw unableToExport(e);
085 }
086 LOG.info("Results packaged in " + exportZip);
087 }
088
089 private IllegalStateException unableToExport(IOException e) {
090 return new IllegalStateException("Unable to export result of analyzis", e);
091 }
092
093 private void exportIssues(File exportDir) {
094 File issuesFile = new File(exportDir, "issues.json");
095 FileWriter issueWriter = null;
096 try {
097 issueWriter = new FileWriter(issuesFile);
098 JsonWriter jsonWriter = JsonWriter.of(issueWriter);
099 jsonWriter
100 .beginObject().name("issues")
101 .beginArray();
102 for (Issue issue : issueCache.byModule(def.getKey())) {
103 jsonWriter.beginObject()
104 .prop("repository", issue.ruleKey().repository())
105 .prop("rule", issue.ruleKey().rule());
106 if (issue.inputPath() != null) {
107 jsonWriter.prop("path", issue.inputPath().relativePath());
108 }
109 jsonWriter.prop("message", issue.message())
110 .prop("effortToFix", issue.effortToFix())
111 .prop("line", issue.line())
112 .prop("severity", issue.severity())
113 .endObject();
114 }
115 jsonWriter.endArray()
116 .endObject()
117 .close();
118 } catch (IOException e) {
119 throw unableToExport(e);
120 } finally {
121 IOUtils.closeQuietly(issueWriter);
122 }
123 }
124
125 private void exportMeasures(File exportDir) {
126 File measuresFile = new File(exportDir, "measures.json");
127 FileWriter measureWriter = null;
128 try {
129 measureWriter = new FileWriter(measuresFile);
130 JsonWriter jsonWriter = JsonWriter.of(measureWriter);
131 jsonWriter
132 .beginObject().name("measures")
133 .beginArray();
134 for (Measure<?> measure : measureCache.byModule(def.getKey())) {
135 jsonWriter.beginObject()
136 .prop("metricKey", measure.metric().key());
137 InputFile inputFile = measure.inputFile();
138 if (inputFile != null) {
139 jsonWriter.prop("filePath", inputFile.relativePath());
140 }
141 jsonWriter.prop("value", String.valueOf(measure.value()))
142 .endObject();
143 }
144 jsonWriter.endArray()
145 .endObject()
146 .close();
147 } catch (IOException e) {
148 throw unableToExport(e);
149 } finally {
150 IOUtils.closeQuietly(measureWriter);
151 }
152 }
153
154 private void exportSourceFiles(File exportDir) {
155 File sourceDir = new File(exportDir, "sources");
156 for (InputFile inputFile : fs.inputFiles(fs.predicates().all())) {
157 File dest = new File(sourceDir, inputFile.relativePath());
158 try {
159 FileUtils.copyFile(inputFile.file(), dest);
160 } catch (IOException e) {
161 throw unableToExport(e);
162 }
163 }
164 }
165
166 private void exportAnalysisProperties(File exportDir) {
167 File propsFile = new File(exportDir, "analysis.properties");
168 Properties props = new Properties();
169 props.putAll(settings.getProperties());
170 FileWriter writer = null;
171 try {
172 writer = new FileWriter(propsFile);
173 props.store(writer, "SonarQube batch");
174 } catch (IOException e) {
175 throw unableToExport(e);
176 } finally {
177 IOUtils.closeQuietly(writer);
178 }
179 }
180
181 private File prepareExportDir() {
182 File exportDir = new File(fs.workDir(), "export");
183 try {
184 if (exportDir.exists()) {
185 FileUtils.forceDelete(exportDir);
186 }
187 FileUtils.forceMkdir(exportDir);
188 } catch (IOException e) {
189 throw unableToExport(e);
190 }
191 return exportDir;
192 }
193 }