@@ -21,6 +21,7 @@ package org.sonar.batch; | |||
import com.google.common.collect.ImmutableList; | |||
import com.google.common.collect.Iterables; | |||
import com.google.common.collect.Lists; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.maven.project.MavenProject; | |||
import org.sonar.api.batch.bootstrap.ProjectDefinition; | |||
@@ -31,6 +32,7 @@ import org.sonar.api.utils.SonarException; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Collections; | |||
import java.util.List; | |||
/** | |||
@@ -84,6 +86,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { | |||
} | |||
} | |||
@Override | |||
public List<File> getSourceDirs() { | |||
List<File> unfiltered; | |||
if (pom != null) { | |||
@@ -106,7 +109,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { | |||
if (pom != null) { | |||
pom.getCompileSourceRoots().add(0, dir.getAbsolutePath()); | |||
} else { | |||
def.addSourceDir(dir.getAbsolutePath()); | |||
def.addSourceDirs(dir.getAbsolutePath()); | |||
} | |||
return this; | |||
} | |||
@@ -114,6 +117,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { | |||
/** | |||
* Maven can modify test directories during Sonar execution - see MavenPhaseExecutor. | |||
*/ | |||
@Override | |||
public List<File> getTestDirs() { | |||
List<File> unfiltered; | |||
if (pom != null) { | |||
@@ -136,7 +140,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { | |||
if (pom != null) { | |||
pom.getTestCompileSourceRoots().add(0, dir.getAbsolutePath()); | |||
} else { | |||
def.addTestDir(dir.getAbsolutePath()); | |||
def.addTestDirs(dir.getAbsolutePath()); | |||
} | |||
return this; | |||
} | |||
@@ -168,4 +172,13 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { | |||
return dir; | |||
} | |||
@Override | |||
protected List<File> getInitialSourceFiles() { | |||
return resolvePaths(def.getSourceFiles()); | |||
} | |||
@Override | |||
protected List<File> getInitialTestFiles() { | |||
return resolvePaths(def.getTestFiles()); | |||
} | |||
} |
@@ -62,7 +62,7 @@ public class ProjectDefinition { | |||
} | |||
public void addSourceDir(String path) { | |||
target.addSourceDir(path); | |||
target.addSourceDirs(path); | |||
} | |||
public List<String> getTestDirs() { | |||
@@ -74,7 +74,7 @@ public class ProjectDefinition { | |||
* It can be absolute or relative to project directory. | |||
*/ | |||
public void addTestDir(String path) { | |||
target.addTestDir(path); | |||
target.addTestDirs(path); | |||
} | |||
public List<String> getBinaries() { |
@@ -20,6 +20,7 @@ | |||
package org.sonar.api.batch.bootstrap; | |||
import com.google.common.collect.Lists; | |||
import org.apache.commons.io.FilenameUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.CoreProperties; | |||
@@ -32,13 +33,15 @@ import java.util.Properties; | |||
/** | |||
* Defines project metadata (key, name, source directories, ...). It's generally used by the | |||
* {@link org.sonar.api.batch.bootstrap.ProjectBuilder extension point} | |||
* | |||
* | |||
* @since 2.9 | |||
*/ | |||
public final class ProjectDefinition implements BatchComponent { | |||
public static final String SOURCES_PROPERTY = "sonar.sources"; | |||
public static final String TESTS_PROPERTY = "sonar.tests"; | |||
public static final String SOURCE_DIRS_PROPERTY = "sonar.sources"; | |||
public static final String SOURCE_FILES_PROPERTY = "sonar.sourceFiles"; | |||
public static final String TEST_DIRS_PROPERTY = "sonar.tests"; | |||
public static final String TEST_FILES_PROPERTY = "sonar.testFiles"; | |||
public static final String BINARIES_PROPERTY = "sonar.binaries"; | |||
public static final String LIBRARIES_PROPERTY = "sonar.libraries"; | |||
@@ -132,26 +135,30 @@ public final class ProjectDefinition implements BatchComponent { | |||
} | |||
public List<String> getSourceDirs() { | |||
String sources = properties.getProperty(SOURCES_PROPERTY, ""); | |||
String sources = properties.getProperty(SOURCE_DIRS_PROPERTY, ""); | |||
return Arrays.asList(StringUtils.split(sources, SEPARATOR)); | |||
} | |||
/** | |||
* @param path path to directory with main sources. | |||
* It can be absolute or relative to project directory. | |||
* @param paths paths to directory with main sources. | |||
* They can be absolute or relative to project base directory. | |||
*/ | |||
public ProjectDefinition addSourceDir(String path) { | |||
appendProperty(SOURCES_PROPERTY, path); | |||
public ProjectDefinition addSourceDirs(String... paths) { | |||
for (String path : paths) { | |||
appendProperty(SOURCE_DIRS_PROPERTY, FilenameUtils.normalize(path)); | |||
} | |||
return this; | |||
} | |||
public ProjectDefinition addSourceDir(File path) { | |||
addSourceDir(path.getAbsolutePath()); | |||
public ProjectDefinition addSourceDirs(File... dirs) { | |||
for (File dir : dirs) { | |||
addSourceDirs(dir); | |||
} | |||
return this; | |||
} | |||
public ProjectDefinition setSourceDir(String path) { | |||
properties.setProperty(SOURCES_PROPERTY, path); | |||
properties.setProperty(SOURCE_DIRS_PROPERTY, FilenameUtils.normalize(path)); | |||
return this; | |||
} | |||
@@ -160,20 +167,84 @@ public final class ProjectDefinition implements BatchComponent { | |||
return this; | |||
} | |||
/** | |||
* Adding source files is possible only if no source directories have been set. | |||
* Absolute path or relative path from project base dir. | |||
*/ | |||
public ProjectDefinition addSourceFiles(String... paths) { | |||
for (String path : paths) { | |||
appendProperty(SOURCE_FILES_PROPERTY, FilenameUtils.normalize(path)); | |||
} | |||
return this; | |||
} | |||
/** | |||
* Adding source files is possible only if no source directories have been set. | |||
*/ | |||
public ProjectDefinition addSourceFiles(File... files) { | |||
for (File file : files) { | |||
addSourceFiles(file.getAbsolutePath()); | |||
} | |||
return this; | |||
} | |||
public List<String> getSourceFiles() { | |||
String sources = properties.getProperty(SOURCE_FILES_PROPERTY, ""); | |||
return Arrays.asList(StringUtils.split(sources, SEPARATOR)); | |||
} | |||
public List<String> getTestDirs() { | |||
String sources = properties.getProperty(TESTS_PROPERTY, ""); | |||
String sources = properties.getProperty(TEST_DIRS_PROPERTY, ""); | |||
return Arrays.asList(StringUtils.split(sources, SEPARATOR)); | |||
} | |||
/** | |||
* @param path path to directory with test sources. | |||
* It can be absolute or relative to project directory. | |||
* @param paths path to directory with test sources. | |||
* It can be absolute or relative to project directory. | |||
*/ | |||
public ProjectDefinition addTestDir(String path) { | |||
appendProperty(TESTS_PROPERTY, path); | |||
public ProjectDefinition addTestDirs(String... paths) { | |||
for (String path : paths) { | |||
appendProperty(TEST_DIRS_PROPERTY, FilenameUtils.normalize(path)); | |||
} | |||
return this; | |||
} | |||
public ProjectDefinition addTestDirs(File... dirs) { | |||
for (File dir : dirs) { | |||
addTestDirs(dir.getAbsolutePath()); | |||
} | |||
return this; | |||
} | |||
/** | |||
* Adding source files is possible only if no source directories have been set. | |||
* Absolute path or relative path from project base dir. | |||
*/ | |||
public ProjectDefinition addTestFiles(String... paths) { | |||
for (String path : paths) { | |||
appendProperty(TEST_FILES_PROPERTY, FilenameUtils.normalize(path)); | |||
} | |||
return this; | |||
} | |||
/** | |||
* Adding source files is possible only if no source directories have been set. | |||
*/ | |||
public ProjectDefinition addTestFiles(File... files) { | |||
for (File file : files) { | |||
addTestFiles(file.getAbsolutePath()); | |||
} | |||
return this; | |||
} | |||
public List<String> getTestFiles() { | |||
String sources = properties.getProperty(TEST_FILES_PROPERTY, ""); | |||
return Arrays.asList(StringUtils.split(sources, SEPARATOR)); | |||
} | |||
public List<String> getBinaries() { | |||
String sources = properties.getProperty(BINARIES_PROPERTY, ""); | |||
return Arrays.asList(StringUtils.split(sources, SEPARATOR)); | |||
@@ -181,11 +252,11 @@ public final class ProjectDefinition implements BatchComponent { | |||
/** | |||
* @param path path to directory with compiled source. In case of Java this is directory with class files. | |||
* It can be absolute or relative to project directory. | |||
* It can be absolute or relative to project directory. | |||
* @TODO currently Sonar supports only one such directory due to dependency on MavenProject | |||
*/ | |||
public ProjectDefinition addBinaryDir(String path) { | |||
appendProperty(BINARIES_PROPERTY, path); | |||
appendProperty(BINARIES_PROPERTY, FilenameUtils.normalize(path)); | |||
return this; | |||
} | |||
@@ -196,10 +267,10 @@ public final class ProjectDefinition implements BatchComponent { | |||
/** | |||
* @param path path to file with third-party library. In case of Java this is path to jar file. | |||
* It can be absolute or relative to project directory. | |||
* It can be absolute or relative to project directory. | |||
*/ | |||
public void addLibrary(String path) { | |||
appendProperty(LIBRARIES_PROPERTY, path); | |||
appendProperty(LIBRARIES_PROPERTY, FilenameUtils.normalize(path)); | |||
} | |||
/** |
@@ -20,9 +20,7 @@ | |||
package org.sonar.api.resources; | |||
import com.google.common.base.Predicate; | |||
import com.google.common.collect.ImmutableList; | |||
import com.google.common.collect.Iterables; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.*; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.io.FilenameUtils; | |||
import org.apache.commons.io.filefilter.*; | |||
@@ -37,9 +35,7 @@ import org.sonar.api.utils.WildcardPattern; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.charset.Charset; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.*; | |||
/** | |||
* An implementation of {@link ProjectFileSystem}. | |||
@@ -196,7 +192,7 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { | |||
return !testFiles(lang.getKey()).isEmpty(); | |||
} | |||
private List<InputFile> getFiles(List<File> directories, boolean applyExclusionPatterns, String... langs) { | |||
private List<InputFile> getFiles(List<File> directories, List<File> initialFiles, boolean applyExclusionPatterns, String... langs) { | |||
List<InputFile> result = Lists.newArrayList(); | |||
if (directories == null) { | |||
return result; | |||
@@ -205,13 +201,19 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { | |||
IOFileFilter suffixFilter = getFileSuffixFilter(langs); | |||
WildcardPattern[] exclusionPatterns = getExclusionPatterns(applyExclusionPatterns); | |||
IOFileFilter initialFilesFilter = TrueFileFilter.INSTANCE; | |||
if (initialFiles!=null && !initialFiles.isEmpty()) { | |||
initialFilesFilter = new FileSelectionFilter(initialFiles); | |||
} | |||
for (File dir : directories) { | |||
if (dir.exists()) { | |||
IOFileFilter exclusionFilter = new ExclusionFilter(dir, exclusionPatterns); | |||
IOFileFilter visibleFileFilter = HiddenFileFilter.VISIBLE; | |||
List<IOFileFilter> dirFilters = Lists.newArrayList(visibleFileFilter, suffixFilter, exclusionFilter); | |||
dirFilters.addAll(this.filters); | |||
List<File> files = (List<File>) FileUtils.listFiles(dir, new AndFileFilter(dirFilters), HiddenFileFilter.VISIBLE); | |||
List<IOFileFilter> fileFilters = Lists.newArrayList(visibleFileFilter, suffixFilter, exclusionFilter, initialFilesFilter); | |||
fileFilters.addAll(this.filters); | |||
List<File> files = (List<File>) FileUtils.listFiles(dir, new AndFileFilter(fileFilters), HiddenFileFilter.VISIBLE); | |||
for (File file : files) { | |||
String relativePath = DefaultProjectFileSystem.getRelativePath(file, dir); | |||
result.add(InputFileUtils.create(dir, relativePath)); | |||
@@ -269,6 +271,22 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { | |||
} | |||
} | |||
static class FileSelectionFilter implements IOFileFilter { | |||
private Set<File> files; | |||
public FileSelectionFilter(List<File> f) { | |||
files = Sets.newHashSet(f); | |||
} | |||
public boolean accept(File file) { | |||
return files.contains(file); | |||
} | |||
public boolean accept(File file, String name) { | |||
return accept(file); | |||
} | |||
} | |||
public File writeToWorkingDirectory(String content, String fileName) throws IOException { | |||
return writeToFile(content, getSonarWorkingDirectory(), fileName); | |||
} | |||
@@ -363,13 +381,21 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { | |||
* @since 2.6 | |||
*/ | |||
public List<InputFile> mainFiles(String... langs) { | |||
return getFiles(getSourceDirs(), true, langs); | |||
return getFiles(getSourceDirs(), getInitialSourceFiles(), true, langs); | |||
} | |||
/** | |||
* @since 2.6 | |||
*/ | |||
public List<InputFile> testFiles(String... langs) { | |||
return getFiles(getTestDirs(), false /* FIXME should be true? */, langs); | |||
return getFiles(getTestDirs(), getInitialTestFiles(), false /* FIXME should be true? */, langs); | |||
} | |||
protected List<File> getInitialSourceFiles() { | |||
return Collections.emptyList(); | |||
} | |||
protected List<File> getInitialTestFiles() { | |||
return Collections.emptyList(); | |||
} | |||
} |
@@ -74,19 +74,29 @@ public class ProjectDefinitionTest { | |||
@Test | |||
public void shouldAddDirectories() { | |||
ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties()); | |||
def.addSourceDir("src/main/java"); | |||
def.addSourceDir("src/main/java2"); | |||
def.addTestDir("src/test/java"); | |||
def.addTestDir("src/test/java2"); | |||
def.addSourceDirs("src/main/java", "src/main/java2"); | |||
def.addTestDirs("src/test/java"); | |||
def.addTestDirs("src/test/java2"); | |||
def.addBinaryDir("target/classes"); | |||
def.addBinaryDir("target/classes2"); | |||
def.addLibrary("junit.jar"); | |||
def.addLibrary("mockito.jar"); | |||
assertDirs(def.getSourceDirs(), "src/main/java", "src/main/java2"); | |||
assertDirs(def.getTestDirs(), "src/test/java", "src/test/java2"); | |||
assertDirs(def.getBinaries(), "target/classes", "target/classes2"); | |||
assertDirs(def.getLibraries(), "junit.jar", "mockito.jar"); | |||
assertFiles(def.getSourceDirs(), "src/main/java", "src/main/java2"); | |||
assertFiles(def.getTestDirs(), "src/test/java", "src/test/java2"); | |||
assertFiles(def.getBinaries(), "target/classes", "target/classes2"); | |||
assertFiles(def.getLibraries(), "junit.jar", "mockito.jar"); | |||
} | |||
@Test | |||
public void shouldAddFiles() { | |||
ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties()); | |||
def.addSourceFiles("src/main/java/foo/Bar.java", "src/main/java/hello/World.java"); | |||
def.addTestFiles("src/test/java/foo/BarTest.java", "src/test/java/hello/WorldTest.java"); | |||
assertFiles(def.getSourceFiles(), "src/main/java/foo/Bar.java", "src/main/java/hello/World.java"); | |||
assertFiles(def.getTestFiles(), "src/test/java/foo/BarTest.java", "src/test/java/hello/WorldTest.java"); | |||
} | |||
@Test | |||
@@ -102,10 +112,10 @@ public class ProjectDefinitionTest { | |||
assertThat(child.getParent(), is(root)); | |||
} | |||
private static void assertDirs(List<String> dirs, String... values) { | |||
assertThat(dirs.size(), is(values.length)); | |||
private static void assertFiles(List<String> paths, String... values) { | |||
assertThat(paths.size(), is(values.length)); | |||
for (int i = 0; i < values.length; i++) { | |||
assertThat(dirs.get(i), is(values[i])); | |||
assertThat(paths.get(i), is(values[i])); | |||
} | |||
} | |||
} |
@@ -32,6 +32,7 @@ import org.apache.commons.lang.SystemUtils; | |||
import org.apache.maven.project.MavenProject; | |||
import org.hamcrest.Description; | |||
import org.hamcrest.Matcher; | |||
import org.hamcrest.Matchers; | |||
import org.hamcrest.TypeSafeMatcher; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
@@ -39,6 +40,7 @@ import org.sonar.api.batch.FileFilter; | |||
import org.sonar.api.test.MavenTestUtils; | |||
import java.io.File; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
public class DefaultProjectFileSystemTest { | |||
@@ -205,6 +207,19 @@ public class DefaultProjectFileSystemTest { | |||
assertThat(fsWithFilter.getSourceFiles(), not(hasItem(named("Bar.java")))); | |||
} | |||
@Test | |||
public void testSelectiveFileFilter() { | |||
DefaultProjectFileSystem.FileSelectionFilter filter = new DefaultProjectFileSystem.FileSelectionFilter( | |||
Arrays.asList(new File("foo/Bar.java"), new File("hello/Bar.java"), new File("hello/World.java"))); | |||
assertThat(filter.accept(new File("foo/Bar.java")), Matchers.is(true)); | |||
assertThat(filter.accept(new File("hello/Bar.java")), Matchers.is(true)); | |||
assertThat(filter.accept(new File("hello/World.java")), Matchers.is(true)); | |||
assertThat(filter.accept(new File("foo/Unknown.java")), Matchers.is(false)); | |||
assertThat(filter.accept(new File("foo/bar/Bar.java")), Matchers.is(false)); | |||
assertThat(filter.accept(new File("foo/World.java")), Matchers.is(false)); | |||
} | |||
private DefaultProjectFileSystem newDefaultProjectFileSystem(Project project) { | |||
return (DefaultProjectFileSystem) project.getFileSystem(); | |||
} |