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.scan.filesystem;
021
022 import com.google.common.collect.Iterables;
023 import com.google.common.collect.Lists;
024 import org.apache.commons.io.FileUtils;
025 import org.apache.commons.lang.CharEncoding;
026 import org.apache.maven.project.MavenProject;
027 import org.sonar.api.batch.fs.FilePredicate;
028 import org.sonar.api.resources.InputFile;
029 import org.sonar.api.resources.Java;
030 import org.sonar.api.resources.Language;
031 import org.sonar.api.resources.Project;
032 import org.sonar.api.resources.ProjectFileSystem;
033 import org.sonar.api.resources.Resource;
034 import org.sonar.api.scan.filesystem.PathResolver;
035 import org.sonar.api.utils.SonarException;
036
037 import javax.annotation.Nullable;
038 import java.io.File;
039 import java.io.IOException;
040 import java.nio.charset.Charset;
041 import java.util.Arrays;
042 import java.util.List;
043
044 /**
045 * Adapter for keeping the backward-compatibility of the deprecated component {@link org.sonar.api.resources.ProjectFileSystem}
046 *
047 * @since 3.5
048 */
049 public class ProjectFileSystemAdapter implements ProjectFileSystem {
050
051 private final DefaultModuleFileSystem target;
052 private final PathResolver pathResolver = new PathResolver();
053 private final MavenProject pom;
054
055 public ProjectFileSystemAdapter(DefaultModuleFileSystem target, Project project, @Nullable MavenProject pom) {
056 this.target = target;
057 this.pom = pom;
058
059 // previously MavenProjectBuilder was responsible for creation of ProjectFileSystem
060 project.setFileSystem(this);
061 }
062
063 public ProjectFileSystemAdapter(DefaultModuleFileSystem target, Project project) {
064 this(target, project, null);
065 }
066
067 public void start() {
068 // used to avoid NPE in Project#getFileSystem()
069 }
070
071 public Charset getSourceCharset() {
072 return target.sourceCharset();
073 }
074
075 public File getBasedir() {
076 return target.baseDir();
077 }
078
079 public File getBuildDir() {
080 File dir = target.buildDir();
081 if (dir == null) {
082 // emulate build dir to keep backward-compatibility
083 dir = new File(getSonarWorkingDirectory(), "build");
084 }
085 return dir;
086 }
087
088 public File getBuildOutputDir() {
089 File dir = Iterables.getFirst(target.binaryDirs(), null);
090 if (dir == null) {
091 // emulate binary dir
092 dir = new File(getBuildDir(), "classes");
093 }
094
095 return dir;
096 }
097
098 public List<File> getSourceDirs() {
099 return target.sourceDirs();
100 }
101
102 public ProjectFileSystem addSourceDir(File dir) {
103 target.addSourceDir(dir);
104 return this;
105 }
106
107 public List<File> getTestDirs() {
108 return target.testDirs();
109 }
110
111 public ProjectFileSystem addTestDir(File dir) {
112 target.addTestDir(dir);
113 return this;
114 }
115
116 public File getReportOutputDir() {
117 if (pom != null) {
118 return resolvePath(pom.getReporting().getOutputDirectory());
119 }
120 // emulate Maven report output dir
121 return new File(getBuildDir(), "site");
122 }
123
124 public File getSonarWorkingDirectory() {
125 return target.workingDir();
126 }
127
128 public File resolvePath(String path) {
129 File file = new File(path);
130 if (!file.isAbsolute()) {
131 try {
132 file = new File(getBasedir(), path).getCanonicalFile();
133 } catch (IOException e) {
134 throw new SonarException("Unable to resolve path '" + path + "'", e);
135 }
136 }
137 return file;
138 }
139
140 public List<File> getSourceFiles(Language... langs) {
141 return Lists.newArrayList(target.files(target.predicates().and(
142 target.predicates().hasType(org.sonar.api.batch.fs.InputFile.Type.MAIN),
143 newHasLanguagesPredicate(langs))));
144 }
145
146 public List<File> getJavaSourceFiles() {
147 return getSourceFiles(Java.INSTANCE);
148 }
149
150 public boolean hasJavaSourceFiles() {
151 return !getJavaSourceFiles().isEmpty();
152 }
153
154 public List<File> getTestFiles(Language... langs) {
155 return Lists.newArrayList(target.files(target.predicates().and(
156 target.predicates().hasType(org.sonar.api.batch.fs.InputFile.Type.TEST),
157 newHasLanguagesPredicate(langs))));
158 }
159
160 public boolean hasTestFiles(Language lang) {
161 return target.hasFiles(target.predicates().and(
162 target.predicates().hasType(org.sonar.api.batch.fs.InputFile.Type.TEST),
163 target.predicates().hasLanguage(lang.getKey())));
164 }
165
166 public File writeToWorkingDirectory(String content, String fileName) throws IOException {
167 File file = new File(target.workingDir(), fileName);
168 FileUtils.writeStringToFile(file, content, CharEncoding.UTF_8);
169 return file;
170 }
171
172 public File getFileFromBuildDirectory(String filename) {
173 File file = new File(getBuildDir(), filename);
174 return file.exists() ? file : null;
175 }
176
177 public Resource toResource(File file) {
178 if (file == null || !file.exists()) {
179 return null;
180 }
181 String relativePath = pathResolver.relativePath(getBasedir(), file);
182 if (relativePath == null) {
183 return null;
184 }
185 return file.isFile() ? org.sonar.api.resources.File.create(relativePath) : org.sonar.api.resources.Directory.create(relativePath);
186 }
187
188 public List<InputFile> mainFiles(String... langs) {
189 return Lists.newArrayList((Iterable) target.inputFiles(target.predicates().and(
190 target.predicates().hasType(org.sonar.api.batch.fs.InputFile.Type.MAIN),
191 target.predicates().hasLanguages(Arrays.asList(langs))
192 )));
193
194 }
195
196 public List<InputFile> testFiles(String... langs) {
197 return Lists.newArrayList((Iterable) target.inputFiles(target.predicates().and(
198 target.predicates().hasType(org.sonar.api.batch.fs.InputFile.Type.TEST),
199 target.predicates().hasLanguages(Arrays.asList(langs))
200 )));
201 }
202
203 private FilePredicate newHasLanguagesPredicate(Language... languages) {
204 List<FilePredicate> list = Lists.newArrayList();
205 for (Language language : languages) {
206 list.add(target.predicates().hasLanguage(language.getKey()));
207 }
208 return target.predicates().or(list);
209 }
210 }