languages();
-
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
index 42cb48fac6d..da1dcccfe49 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
@@ -19,6 +19,7 @@
*/
package org.sonar.api.batch;
+import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.design.Dependency;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
@@ -26,7 +27,6 @@ import org.sonar.api.measures.Metric;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;
-import org.sonar.api.scan.filesystem.InputFile;
import java.util.Collection;
import java.util.Date;
@@ -42,7 +42,6 @@ public interface SensorContext {
* Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed.
*
* @return false if the resource is excluded
- * @since 2.6
* @since 4.2 Resource indexing is done by the platform for all physical resources. This method should only be used to index methods/paragraphs (see SONAR-5006)
*/
boolean index(Resource resource);
@@ -53,19 +52,20 @@ public interface SensorContext {
* @param resource the resource to index. Not nullable
* @param parentReference a reference to the parent. If null, the the resource is indexed as a direct child of project.
* @return false if the parent is not indexed or if the resource is excluded
- * @since 2.6
* @since 4.2 Resource indexing is done by the platform for all physical resources. This method should only be used to index methods/paragraphs (see SONAR-5006)
*/
boolean index(Resource resource, Resource parentReference);
/**
* Returns true if the referenced resource is indexed and excluded.
+ *
* @since 2.6
*/
boolean isExcluded(Resource reference);
/**
* Returns true if the referenced resource is indexed.
+ *
* @since 2.6
*/
boolean isIndexed(Resource reference, boolean acceptExcluded);
@@ -142,13 +142,6 @@ public interface SensorContext {
*/
Measure saveMeasure(Resource resource, Metric metric, Double value);
- /**
- * Experimental.
- * Add or update a measure on an InputFile.
- * @since 4.2
- */
- Measure saveMeasure(InputFile inputFile, Metric metric, Double value);
-
/**
* Add or update a measure.
*
@@ -158,13 +151,6 @@ public interface SensorContext {
*/
Measure saveMeasure(Resource resource, Measure measure);
- /**
- * Experimental.
- * Add or update a measure on an InputFile.
- * @since 4.2
- */
- Measure saveMeasure(InputFile inputFile, Measure measure);
-
// ----------- RULE VIOLATIONS --------------
/**
@@ -203,8 +189,7 @@ public interface SensorContext {
/**
* Save the source code of a file. The file must be have been indexed before.
*
- * @throws org.sonar.api.resources.DuplicatedSourceException
- * if the source has already been set on this resource
+ * @throws org.sonar.api.resources.DuplicatedSourceException if the source has already been set on this resource
* @since 1.10. Returns a boolean since 2.6.
* @deprecated since 4.2 Source import is done by the platform
*/
@@ -249,4 +234,13 @@ public interface SensorContext {
*/
void deleteEvent(Event event);
+ /**
+ * @since 4.2
+ */
+ Measure saveMeasure(InputFile inputFile, Metric metric, Double value);
+
+ /**
+ * @since 4.2
+ */
+ Measure saveMeasure(InputFile inputFile, Measure measure);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java
new file mode 100644
index 00000000000..a659ad27f10
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java
@@ -0,0 +1,39 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import org.apache.commons.io.FilenameUtils;
+
+/**
+ * @since 4.2
+ */
+class AbsolutePathPredicate implements FilePredicate {
+
+ private final String path;
+
+ AbsolutePathPredicate(String path) {
+ this.path = FilenameUtils.normalize(path, true);
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return path.equals(f.absolutePath());
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java
new file mode 100644
index 00000000000..f1221c1fe2c
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import javax.annotation.Nullable;
+
+/**
+ * @since 4.2
+ */
+class AndPredicate implements FilePredicate {
+
+ private final Iterable predicates;
+
+ AndPredicate(@Nullable Iterable predicates) {
+ this.predicates = predicates;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ for (FilePredicate predicate : predicates) {
+ if (!predicate.apply(f)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java
new file mode 100644
index 00000000000..5cc7b7ae9e1
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java
@@ -0,0 +1,29 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+/**
+ * Determines if a file must be kept in search results. See {@link org.sonar.api.batch.fs.FileSystem}
+ * and {@link org.sonar.api.batch.fs.FilePredicates}.
+ * @since 4.2
+ */
+public interface FilePredicate {
+ boolean apply(InputFile inputFile);
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java
new file mode 100644
index 00000000000..877666c733b
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java
@@ -0,0 +1,152 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import com.google.common.collect.Lists;
+import org.sonar.api.batch.fs.internal.PathPattern;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Factory of {@link org.sonar.api.batch.fs.FilePredicate}
+ *
+ * @since 4.2
+ */
+public class FilePredicates {
+ private static final FilePredicate ALWAYS_TRUE = new AlwaysTruePredicate();
+
+ private FilePredicates() {
+ // only static stuff
+ }
+
+ /**
+ * Returns a predicate that always evaluates to true
+ */
+ public static FilePredicate all() {
+ return ALWAYS_TRUE;
+ }
+
+ /**
+ * Warning - not efficient because absolute path is not indexed yet.
+ */
+ public static FilePredicate hasAbsolutePath(String s) {
+ return new AbsolutePathPredicate(s);
+ }
+
+ /**
+ * TODO document that non-normalized path and Windows-style path are supported
+ */
+ public static FilePredicate hasRelativePath(String s) {
+ return new RelativePathPredicate(s);
+ }
+
+ public static FilePredicate matchesPathPattern(String inclusionPattern) {
+ return new PathPatternPredicate(PathPattern.create(inclusionPattern));
+ }
+
+ public static FilePredicate matchesPathPatterns(String[] inclusionPatterns) {
+ FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length];
+ for (int i = 0; i < inclusionPatterns.length; i++) {
+ predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i]));
+ }
+ return and(predicates);
+ }
+
+ public static FilePredicate doesNotMatchPathPattern(String exclusionPattern) {
+ return not(matchesPathPattern(exclusionPattern));
+ }
+
+ public static FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) {
+ return not(matchesPathPatterns(exclusionPatterns));
+ }
+
+ public static FilePredicate hasPath(String s) {
+ File file = new File(s);
+ if (file.isAbsolute()) {
+ return hasAbsolutePath(s);
+ }
+ return hasRelativePath(s);
+ }
+
+ public static FilePredicate is(File ioFile) {
+ if (ioFile.isAbsolute()) {
+ return hasAbsolutePath(ioFile.getAbsolutePath());
+ }
+ return hasRelativePath(ioFile.getPath());
+ }
+
+ public static FilePredicate hasLanguage(String language) {
+ return new LanguagePredicate(language);
+ }
+
+ public static FilePredicate hasLanguages(Collection languages) {
+ List list = Lists.newArrayList();
+ for (String language : languages) {
+ list.add(hasLanguage(language));
+ }
+ return or(list);
+ }
+
+ public static FilePredicate hasStatus(InputFile.Status status) {
+ return new StatusPredicate(status);
+ }
+
+ public static FilePredicate hasType(InputFile.Type type) {
+ return new TypePredicate(type);
+ }
+
+ public static FilePredicate not(FilePredicate p) {
+ return new NotPredicate(p);
+ }
+
+ public static FilePredicate or(Iterable or) {
+ return new OrPredicate(or);
+ }
+
+ public static FilePredicate or(FilePredicate... or) {
+ return new OrPredicate(Arrays.asList(or));
+ }
+
+ public static FilePredicate or(FilePredicate first, FilePredicate second) {
+ return new OrPredicate(Arrays.asList(first, second));
+ }
+
+ public static FilePredicate and(Iterable and) {
+ return new AndPredicate(and);
+ }
+
+ public static FilePredicate and(FilePredicate... and) {
+ return new AndPredicate(Arrays.asList(and));
+ }
+
+ public static FilePredicate and(FilePredicate first, FilePredicate second) {
+ return new AndPredicate(Arrays.asList(first, second));
+ }
+
+ private static class AlwaysTruePredicate implements FilePredicate {
+ @Override
+ public boolean apply(InputFile inputFile) {
+ return true;
+ }
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java
new file mode 100644
index 00000000000..7d285af934f
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java
@@ -0,0 +1,92 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import org.sonar.api.BatchComponent;
+
+import javax.annotation.CheckForNull;
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.Set;
+
+/**
+ * The unit tests needing an instance of FileSystem can use the implementation
+ * {@link org.sonar.api.batch.fs.internal.DefaultFileSystem} and the related {@link org.sonar.api.scan.filesystem.internal.DefaultInputFile}:
+ *
+ * FileSystem fs = new DefaultFileSystem();
+ * fs.add(new DefaultInputFile("src/foo/bar.php"));
+ *
+ *
+ * @since 4.2
+ */
+public interface FileSystem extends BatchComponent {
+
+ /**
+ * Absolute base directory of module
+ */
+ File baseDir();
+
+ /**
+ * Default encoding of input files. If it's not defined, then
+ * the platform default encoding is returned
+ */
+ Charset encoding();
+
+ /**
+ * Absolute work directory. It can be used to
+ * store third-party analysis reports.
+ *
+ * The work directory can be located outside {@link #baseDir()}.
+ */
+ File workDir();
+
+ /**
+ * @see org.sonar.api.batch.fs.FilePredicates
+ */
+ @CheckForNull
+ InputFile inputFile(FilePredicate predicate);
+
+ /**
+ * Input files matching the given attributes. Return all the files if the parameter
+ * attributes
is empty.
+ * @see org.sonar.api.batch.fs.FilePredicates
+ */
+ Iterable inputFiles(FilePredicate predicate);
+
+ /**
+ * Returns true if at least one {@link org.sonar.api.batch.fs.InputFile} matches
+ * the given attributes. This method can be faster than checking if {@link #inputFiles(org.sonar.api.batch.fs.FilePredicate...)}
+ * has elements. If the parameter attributes
is empty, then returns true
+ * if at least one input file exists.
+ * @see org.sonar.api.batch.fs.FilePredicates
+ */
+ boolean hasFiles(FilePredicate predicate);
+
+ /**
+ * Files matching the given attributes.
+ * @see org.sonar.api.batch.fs.FilePredicates
+ */
+ Iterable files(FilePredicate predicate);
+
+ /**
+ * Languages detected in all the files, whatever their type (main code or test)
+ */
+ Set languages();
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java
new file mode 100644
index 00000000000..fb37090325d
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java
@@ -0,0 +1,87 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * This layer over {@link java.io.File} adds information useful for code analyzers.
+ *
+ * @since 4.2
+ */
+public interface InputFile extends Serializable {
+
+ enum Type {
+ MAIN, TEST
+ }
+
+ /**
+ * Status regarding previous analysis
+ */
+ enum Status {
+ SAME, CHANGED, ADDED
+ }
+
+ /**
+ * Path relative to module base directory. Path is unique and identifies file
+ * within given {@link FileSystem}
.
+ * File separator is the forward slash ('/'), even on Microsoft Windows.
+ *
+ * Returns src/main/java/com/Foo.java
if module base dir is
+ * /absolute/path/to/module
and if file is
+ * /absolute/path/to/module/src/main/java/com/Foo.java
.
+ *
+ * Relative path is not null and is normalized ('foo/../foo' is replaced by 'foo').
+ */
+ String relativePath();
+
+ /**
+ * Normalized absolute path. File separator is forward slash ('/'), even on Microsoft Windows.
+ *
+ * This is not canonical path. Symbolic links are not resolved. For example if /project/src links
+ * to /tmp/src and basedir is /project, then this method returns /project/src/index.php. Use
+ * {@code file().getCanonicalPath()} to resolve symbolic link.
+ */
+ String absolutePath();
+
+ /**
+ * The underlying absolute {@link java.io.File}
+ */
+ File file();
+
+ /**
+ * Language, for example "java" or "php". It's automatically guessed when it is not
+ * set by project configuration.
+ */
+ String language();
+
+ /**
+ * Does it contain main or test code ?
+ */
+ Type type();
+
+ /**
+ * Status regarding previous analysis
+ */
+ Status status();
+
+ int lines();
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java
new file mode 100644
index 00000000000..d9bdac27857
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java
@@ -0,0 +1,33 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import org.sonar.api.BatchExtension;
+
+/**
+ * Extension point to complete the list of files to ignore during inspection
+ * @since 4.2
+ */
+public interface InputFileFilter extends BatchExtension {
+
+ // TODO requires a context (FileSystem) ?
+ boolean accept(InputFile f);
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java
new file mode 100644
index 00000000000..9ab1578b33a
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java
@@ -0,0 +1,36 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+/**
+ * @since 4.2
+ */
+class LanguagePredicate implements FilePredicate {
+ private final String language;
+
+ LanguagePredicate(String language) {
+ this.language = language;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return language.equals(f.language());
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java
new file mode 100644
index 00000000000..5a83803bab0
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java
@@ -0,0 +1,38 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+/**
+ * @since 4.2
+ */
+class NotPredicate implements FilePredicate {
+
+ private final FilePredicate predicate;
+
+ NotPredicate(FilePredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return !predicate.apply(f);
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java
new file mode 100644
index 00000000000..af364527a2a
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import javax.annotation.Nullable;
+
+/**
+ * @since 4.2
+ */
+class OrPredicate implements FilePredicate {
+
+ private final Iterable predicates;
+
+ OrPredicate(@Nullable Iterable predicates) {
+ this.predicates = predicates;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ for (FilePredicate predicate : predicates) {
+ if (predicate.apply(f)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java
new file mode 100644
index 00000000000..2a342026352
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java
@@ -0,0 +1,40 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import org.sonar.api.batch.fs.internal.PathPattern;
+
+/**
+ * @since 4.2
+ */
+class PathPatternPredicate implements FilePredicate {
+
+ private final PathPattern pattern;
+
+ PathPatternPredicate(PathPattern pattern) {
+ this.pattern = pattern;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return pattern.match(f);
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java
new file mode 100644
index 00000000000..98453eb4a58
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+import org.apache.commons.io.FilenameUtils;
+import org.sonar.api.batch.fs.internal.RelativePathIndex;
+
+/**
+ * @since 4.2
+ */
+class RelativePathPredicate implements FilePredicate, UniqueIndexPredicate {
+
+ private final String path;
+
+ RelativePathPredicate(String path) {
+ this.path = FilenameUtils.normalize(path, true);
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return path.equals(f.relativePath());
+ }
+
+ @Override
+ public Object value() {
+ return path;
+ }
+
+ @Override
+ public String indexId() {
+ return RelativePathIndex.ID;
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java
new file mode 100644
index 00000000000..c80b4830f7b
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java
@@ -0,0 +1,38 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+/**
+ * @since 4.2
+ */
+class StatusPredicate implements FilePredicate {
+
+ private final InputFile.Status status;
+
+ StatusPredicate(InputFile.Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return status == f.status();
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java
new file mode 100644
index 00000000000..84be0a29e15
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java
@@ -0,0 +1,39 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+/**
+ * @since 4.2
+ */
+class TypePredicate implements FilePredicate {
+
+ private final InputFile.Type type;
+
+ TypePredicate(InputFile.Type type) {
+ this.type = type;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return type == f.type();
+ }
+
+}
+
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java
new file mode 100644
index 00000000000..693722d101f
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java
@@ -0,0 +1,31 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs;
+
+/**
+ * @since 4.2
+ */
+public interface UniqueIndexPredicate {
+
+ String indexId();
+
+ Object value();
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
new file mode 100644
index 00000000000..4754c1aebb1
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
@@ -0,0 +1,225 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.io.Charsets;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.UniqueIndexPredicate;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * @since 4.2
+ */
+public class DefaultFileSystem implements FileSystem {
+
+ private final Cache cache;
+ private final Set languages = Sets.newTreeSet();
+ private File baseDir, workDir;
+ private Charset encoding = Charsets.UTF_8;
+ private boolean isDefaultJvmEncoding = false;
+
+ /**
+ * Only for testing
+ */
+ public DefaultFileSystem() {
+ this.cache = new MapCache();
+ }
+
+ protected DefaultFileSystem(Cache cache) {
+ this.cache = cache;
+ }
+
+ public DefaultFileSystem setBaseDir(File d) {
+ Preconditions.checkNotNull(d, "Base directory can't be null");
+ this.baseDir = d.getAbsoluteFile();
+ return this;
+ }
+
+ /**
+ * Marked as nullable only for the tests that do not call {@link #setBaseDir(java.io.File)}
+ */
+ @Override
+ @CheckForNull
+ public File baseDir() {
+ return baseDir;
+ }
+
+ public DefaultFileSystem setEncoding(Charset e) {
+ this.encoding = e;
+ return this;
+ }
+
+ @Override
+ public Charset encoding() {
+ return encoding;
+ }
+
+ public boolean isDefaultJvmEncoding() {
+ return isDefaultJvmEncoding;
+ }
+
+ public void setIsDefaultJvmEncoding(boolean b) {
+ this.isDefaultJvmEncoding = b;
+ }
+
+ public DefaultFileSystem setWorkDir(File d) {
+ this.workDir = d.getAbsoluteFile();
+ return this;
+ }
+
+ /**
+ * Marked as nullable only for the tests that do not call {@link #setWorkDir(java.io.File)}
+ */
+ @Override
+ @CheckForNull
+ public File workDir() {
+ return workDir;
+ }
+
+ @Override
+ public InputFile inputFile(FilePredicate predicate) {
+ if (predicate instanceof UniqueIndexPredicate) {
+ return cache.inputFile((UniqueIndexPredicate) predicate);
+ }
+ try {
+ Iterable files = inputFiles(predicate);
+ return Iterables.getOnlyElement(files);
+ } catch (NoSuchElementException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public Iterable inputFiles(FilePredicate predicate) {
+ return Iterables.filter(cache.inputFiles(), new GuavaPredicate(predicate));
+ }
+
+ @Override
+ public boolean hasFiles(FilePredicate predicate) {
+ return Iterables.indexOf(cache.inputFiles(), new GuavaPredicate(predicate)) >= 0;
+ }
+
+ @Override
+ public Iterable files(FilePredicate predicate) {
+ return Iterables.transform(inputFiles(predicate), new Function() {
+ @Override
+ public File apply(@Nullable InputFile input) {
+ return input == null ? null : input.file();
+ }
+ });
+ }
+
+ public void add(InputFile inputFile) {
+ cache.add(inputFile);
+ if (inputFile.language() != null) {
+ languages.add(inputFile.language());
+ }
+ }
+
+ @Override
+ public Set languages() {
+ return languages;
+ }
+
+ public static abstract class Cache {
+ protected abstract Iterable inputFiles();
+
+ @CheckForNull
+ protected abstract InputFile inputFile(UniqueIndexPredicate predicate);
+
+ protected abstract void doAdd(InputFile inputFile);
+
+ protected abstract void doIndex(String indexId, Object value, InputFile inputFile);
+
+ final void add(InputFile inputFile) {
+ doAdd(inputFile);
+ for (FileIndex index : FileIndex.ALL) {
+ doIndex(index.id(), index.valueOf(inputFile), inputFile);
+ }
+ }
+ }
+
+ /**
+ * Used only for testing
+ */
+ private static class MapCache extends Cache {
+ private final List files = Lists.newArrayList();
+ private final Map> fileMap = Maps.newHashMap();
+
+ @Override
+ public Iterable inputFiles() {
+ return Lists.newArrayList(files);
+ }
+
+ @Override
+ public InputFile inputFile(UniqueIndexPredicate predicate) {
+ Map