private static final String DOMAIN = "Management";
public List<Metric> getMetrics() {
- return ImmutableList.of(
- new Metric.Builder("burned_budget", "Burned budget", Metric.ValueType.FLOAT)
- .setDirection(Metric.DIRECTION_NONE)
- .setQualitative(false)
- .setDomain(DOMAIN)
- .setUserManaged(true)
- .create(),
- new Metric.Builder("business_value", "Business value", Metric.ValueType.FLOAT)
- .setDirection(Metric.DIRECTION_BETTER)
- .setQualitative(true)
- .setDomain(DOMAIN)
- .setUserManaged(true)
- .create(),
- new Metric.Builder("team_size", "Team size", Metric.ValueType.INT)
- .setDirection(Metric.DIRECTION_NONE)
- .setQualitative(false)
- .setDomain(DOMAIN)
- .setUserManaged(true)
- .create());
+ return ImmutableList.<Metric>of(
+ new Metric.Builder("burned_budget", "Burned budget", Metric.ValueType.FLOAT)
+ .setDirection(Metric.DIRECTION_NONE)
+ .setQualitative(false)
+ .setDomain(DOMAIN)
+ .setUserManaged(true)
+ .create(),
+ new Metric.Builder("business_value", "Business value", Metric.ValueType.FLOAT)
+ .setDirection(Metric.DIRECTION_BETTER)
+ .setQualitative(true)
+ .setDomain(DOMAIN)
+ .setUserManaged(true)
+ .create(),
+ new Metric.Builder("team_size", "Team size", Metric.ValueType.INT)
+ .setDirection(Metric.DIRECTION_NONE)
+ .setQualitative(false)
+ .setDomain(DOMAIN)
+ .setUserManaged(true)
+ .create());
}
}
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.index.ComponentDataCache;
public void analyse(Project project, SensorContext context) {
Map<String, String> map = Maps.newHashMap();
for (InputFile inputFile : fileCache.byModule(project.key())) {
- String hash = ((DefaultInputFile) inputFile).hash();
+ String hash = ((DeprecatedDefaultInputFile) inputFile).hash();
if (hash != null) {
map.put(inputFile.relativePath(), hash);
}
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.resources.Project;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.scan.filesystem.InputFileCache;
@Test
public void store_file_hashes() throws Exception {
when(fileCache.byModule("struts")).thenReturn(Lists.<InputFile>newArrayList(
- new DefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
- new DefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
+ new DeprecatedDefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
+ new DeprecatedDefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
SensorContext sensorContext = mock(SensorContext.class);
sensor.analyse(project, sensorContext);
public void store_file_hashes_for_branches() throws Exception {
project = new Project("struts", "branch-2.x", "Struts 2.x");
when(fileCache.byModule("struts:branch-2.x")).thenReturn(Lists.<InputFile>newArrayList(
- new DefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
- new DefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
+ new DeprecatedDefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
+ new DeprecatedDefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
SensorContext sensorContext = mock(SensorContext.class);
sensor.analyse(project, sensorContext);
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.SonarException;
TokenizerBridge bridge = new TokenizerBridge(mapping.getTokenizer(), fs.encoding().name(), getBlockSize(project, languageKey));
for (InputFile inputFile : sourceFiles) {
LOG.debug("Populating index from {}", inputFile);
- String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+ String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
List<Block> blocks = bridge.chunk(resourceEffectiveKey, inputFile.file());
index.insert(inputFile, blocks);
}
try {
for (InputFile inputFile : sourceFiles) {
LOG.debug("Detection of duplications for {}", inputFile);
- String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+ String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
Iterable<CloneGroup> filtered;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
for (InputFile inputFile : sourceFiles) {
LOG.debug("Populating index from {}", inputFile);
- String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+ String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
List<Statement> statements;
try {
for (InputFile inputFile : sourceFiles) {
LOG.debug("Detection of duplications for {}", inputFile);
- String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+ String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.test.IsMeasure;
import org.sonar.duplications.index.CloneGroup;
public TemporaryFolder temp = new TemporaryFolder();
SensorContext context = mock(SensorContext.class);
- DefaultInputFile inputFile;
+ DeprecatedDefaultInputFile inputFile;
@Before
public void before() throws IOException {
- inputFile = new DefaultInputFile("src/main/java/Foo.java");
+ inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java");
inputFile.setFile(temp.newFile("Foo.java"));
}
@Test
public void shouldEscapeXmlEntities() throws IOException {
- InputFile csharpFile = new DefaultInputFile("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs")
+ InputFile csharpFile = new DeprecatedDefaultInputFile("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs")
.setFile(temp.newFile("SubsRedsDelivery.cs"));
List<CloneGroup> groups = Arrays.asList(newCloneGroup(
new ClonePart("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs", 0, 5, 204),
<modules>
<module>sonar-application</module>
<module>sonar-batch</module>
+ <module>sonar-batch-plugin-api</module>
<module>sonar-batch-maven-compat</module>
<module>sonar-check-api</module>
<module>sonar-colorizer</module>
<artifactId>sonar-plugin-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-batch-plugin-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-update-center-common</artifactId>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar</artifactId>
+ <version>4.4-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sonar-batch-plugin-api</artifactId>
+ <packaging>jar</packaging>
+
+ <name>SonarQube :: Batch Plugin API</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest-assert</artifactId>
+ </dependency>
+ </dependencies>
+
+
+</project>
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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);
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.util.Collection;
+
+/**
+ * Factory of {@link org.sonar.api.batch.fs.FilePredicate}
+ *
+ * @since 4.2
+ */
+public interface FilePredicates {
+ /**
+ * Returns a predicate that always evaluates to true
+ */
+ FilePredicate all();
+
+ /**
+ * Returns a predicate that always evaluates to false
+ */
+ FilePredicate none();
+
+ /**
+ * Warning - not efficient because absolute path is not indexed yet.
+ */
+ FilePredicate hasAbsolutePath(String s);
+
+ /**
+ * TODO document that non-normalized path and Windows-style path are supported
+ */
+ FilePredicate hasRelativePath(String s);
+
+ FilePredicate matchesPathPattern(String inclusionPattern);
+
+ FilePredicate matchesPathPatterns(String[] inclusionPatterns);
+
+ FilePredicate doesNotMatchPathPattern(String exclusionPattern);
+
+ FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns);
+
+ FilePredicate hasPath(String s);
+
+ FilePredicate is(File ioFile);
+
+ FilePredicate hasLanguage(String language);
+
+ FilePredicate hasLanguages(Collection<String> languages);
+
+ FilePredicate hasLanguages(String... languages);
+
+ FilePredicate hasStatus(InputFile.Status status);
+
+ FilePredicate hasType(InputFile.Type type);
+
+ FilePredicate not(FilePredicate p);
+
+ FilePredicate or(Collection<FilePredicate> or);
+
+ FilePredicate or(FilePredicate... or);
+
+ FilePredicate or(FilePredicate first, FilePredicate second);
+
+ FilePredicate and(Collection<FilePredicate> and);
+
+ FilePredicate and(FilePredicate... and);
+
+ FilePredicate and(FilePredicate first, FilePredicate second);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.BatchComponent;
+
+import javax.annotation.CheckForNull;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.SortedSet;
+
+/**
+ * The {@link FileSystem} manages all the source files to be analyzed.
+ * <p/>
+ * This is not an extension point so it must not be implemented by plugins. It must be injected as a
+ * constructor parameter :
+ * <pre>
+ * public class MySensor implements Sensor {
+ * private final FileSystem fs;
+ *
+ * public MySensor(FileSystem fs) {
+ * this.fs = fs;
+ * }
+ * }
+ * </pre>
+ *
+ * <h2>How to use in unit tests</h2>
+ * 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.batch.fs.internal.DefaultInputFile},
+ * for example :
+ * <pre>
+ * DefaultFileSystem fs = new DefaultFileSystem();
+ * fs.add(new DefaultInputFile("src/foo/bar.php"));
+ * </pre>
+ *
+ * @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.
+ * <p/>
+ * The work directory can be located outside {@link #baseDir()}.
+ */
+ File workDir();
+
+ /**
+ * Factory of {@link FilePredicate}
+ */
+ FilePredicates predicates();
+
+ /**
+ * Returns the single element matching the predicate. If more than one elements match
+ * the predicate, then {@link IllegalArgumentException} is thrown. Returns {@code null}
+ * if no files match.
+ *
+ * <p/>
+ * How to use :
+ * <pre>
+ * InputFile file = fs.inputFile(fs.predicates().hasRelativePath("src/Foo.php"));
+ * </pre>
+ *
+ * @see #predicates()
+ */
+ @CheckForNull
+ InputFile inputFile(FilePredicate predicate);
+
+ /**
+ * Input files matching the given attributes. Return all the files if the parameter
+ * <code>attributes</code> is empty.
+ * <p/>
+ * <b>Important</b> - result is an {@link java.lang.Iterable} to benefit from streaming and decreasing
+ * memory consumption. It should be iterated only once, else copy it into a list :
+ * {@code com.google.common.collect.Lists.newArrayList(inputFiles(predicate))}
+ * <p/>
+ * How to use :
+ * <pre>
+ * FilePredicates p = fs.predicates();
+ * Iterable<InputFile> files = fs.inputFiles(p.and(p.hasLanguage("java"), p.hasType(InputFile.Type.MAIN)));
+ * </pre>
+ *
+ * @see #predicates()
+ */
+ Iterable<InputFile> inputFiles(FilePredicate predicate);
+
+ /**
+ * Returns true if at least one {@link org.sonar.api.batch.fs.InputFile} matches
+ * the given predicate. This method can be faster than checking if {@link #inputFiles(org.sonar.api.batch.fs.FilePredicate)}
+ * has elements.
+ * @see #predicates()
+ */
+ boolean hasFiles(FilePredicate predicate);
+
+ /**
+ * Files matching the given predicate.
+ * @see #predicates()
+ */
+ Iterable<File> files(FilePredicate predicate);
+
+ /**
+ * Languages detected in all files, whatever their type (main or test)
+ */
+ SortedSet<String> languages();
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 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 <code>{@link FileSystem}</code>. File separator is the forward
+ * slash ('/'), even on Microsoft Windows.
+ * <p/>
+ * Returns <code>src/main/java/com/Foo.java</code> if module base dir is
+ * <code>/path/to/module</code> and if file is
+ * <code>/path/to/module/src/main/java/com/Foo.java</code>.
+ * <p/>
+ * 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.
+ * <p/>
+ * 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 if it is not
+ * set in project settings.
+ */
+ String language();
+
+ /**
+ * Does it contain main or test code ?
+ */
+ Type type();
+
+ /**
+ * Status regarding previous analysis
+ */
+ Status status();
+
+ /**
+ * Number of physical lines. This method supports all end-of-line characters. Returns
+ * zero if the file is empty.
+ */
+ int lines();
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.BatchExtension;
+
+/**
+ * Extension point to exclude some files from inspection
+ * @since 4.2
+ */
+public interface InputFileFilter extends BatchExtension {
+
+ // TODO requires a context (FileSystem) ?
+ boolean accept(InputFile f);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.FilenameUtils;
+
+/**
+ * @since 4.2
+ */
+class AbsolutePathPredicate implements FilePredicate {
+
+ private final String path;
+
+ AbsolutePathPredicate(String path) {
+ this.path = FilenameUtils.normalize(path);
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return path.equals(f.absolutePath());
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.util.Collection;
+
+/**
+ * @since 4.2
+ */
+class AndPredicate implements FilePredicate {
+
+ private final Collection<FilePredicate> predicates;
+
+ AndPredicate(Collection<FilePredicate> predicates) {
+ this.predicates = predicates;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ for (FilePredicate predicate : predicates) {
+ if (!predicate.apply(f)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.io.File;
+import java.util.ArrayList;
+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 DefaultFilePredicates implements FilePredicates {
+ /**
+ * Client code should use {@link org.sonar.api.batch.fs.FileSystem#predicates()} to get an instance
+ */
+ DefaultFilePredicates() {
+ }
+
+ /**
+ * Returns a predicate that always evaluates to true
+ */
+ public FilePredicate all() {
+ return TruePredicate.TRUE;
+ }
+
+ /**
+ * Returns a predicate that always evaluates to false
+ */
+ public FilePredicate none() {
+ return FalsePredicate.FALSE;
+ }
+
+ /**
+ * Warning - not efficient because absolute path is not indexed yet.
+ */
+ public FilePredicate hasAbsolutePath(String s) {
+ return new AbsolutePathPredicate(s);
+ }
+
+ /**
+ * TODO document that non-normalized path and Windows-style path are supported
+ */
+ public FilePredicate hasRelativePath(String s) {
+ return new RelativePathPredicate(s);
+ }
+
+ public FilePredicate matchesPathPattern(String inclusionPattern) {
+ return new PathPatternPredicate(PathPattern.create(inclusionPattern));
+ }
+
+ public FilePredicate matchesPathPatterns(String[] inclusionPatterns) {
+ if (inclusionPatterns.length == 0) {
+ return TruePredicate.TRUE;
+ }
+ FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length];
+ for (int i = 0; i < inclusionPatterns.length; i++) {
+ predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i]));
+ }
+ return or(predicates);
+ }
+
+ public FilePredicate doesNotMatchPathPattern(String exclusionPattern) {
+ return not(matchesPathPattern(exclusionPattern));
+ }
+
+ public FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) {
+ if (exclusionPatterns.length == 0) {
+ return TruePredicate.TRUE;
+ }
+ return not(matchesPathPatterns(exclusionPatterns));
+ }
+
+ public FilePredicate hasPath(String s) {
+ File file = new File(s);
+ if (file.isAbsolute()) {
+ return hasAbsolutePath(s);
+ }
+ return hasRelativePath(s);
+ }
+
+ public FilePredicate is(File ioFile) {
+ if (ioFile.isAbsolute()) {
+ return hasAbsolutePath(ioFile.getAbsolutePath());
+ }
+ return hasRelativePath(ioFile.getPath());
+ }
+
+ public FilePredicate hasLanguage(String language) {
+ return new LanguagePredicate(language);
+ }
+
+ public FilePredicate hasLanguages(Collection<String> languages) {
+ List<FilePredicate> list = new ArrayList<FilePredicate>();
+ for (String language : languages) {
+ list.add(hasLanguage(language));
+ }
+ return or(list);
+ }
+
+ public FilePredicate hasLanguages(String... languages) {
+ List<FilePredicate> list = new ArrayList<FilePredicate>();
+ for (String language : languages) {
+ list.add(hasLanguage(language));
+ }
+ return or(list);
+ }
+
+ public FilePredicate hasStatus(InputFile.Status status) {
+ return new StatusPredicate(status);
+ }
+
+ public FilePredicate hasType(InputFile.Type type) {
+ return new TypePredicate(type);
+ }
+
+ public FilePredicate not(FilePredicate p) {
+ return new NotPredicate(p);
+ }
+
+ public FilePredicate or(Collection<FilePredicate> or) {
+ return new OrPredicate(or);
+ }
+
+ public FilePredicate or(FilePredicate... or) {
+ return new OrPredicate(Arrays.asList(or));
+ }
+
+ public FilePredicate or(FilePredicate first, FilePredicate second) {
+ return new OrPredicate(Arrays.asList(first, second));
+ }
+
+ public FilePredicate and(Collection<FilePredicate> and) {
+ return new AndPredicate(and);
+ }
+
+ public FilePredicate and(FilePredicate... and) {
+ return new AndPredicate(Arrays.asList(and));
+ }
+
+ public FilePredicate and(FilePredicate first, FilePredicate second) {
+ return new AndPredicate(Arrays.asList(first, second));
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.Preconditions;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @since 4.2
+ */
+public class DefaultFileSystem implements FileSystem {
+
+ private final Cache cache;
+ private final SortedSet<String> languages = new TreeSet<String>();
+ private File baseDir, workDir;
+ private Charset encoding;
+ private final FilePredicates predicates = new DefaultFilePredicates();
+
+ /**
+ * 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;
+ }
+
+ @Override
+ public File baseDir() {
+ return baseDir;
+ }
+
+ public DefaultFileSystem setEncoding(@Nullable Charset e) {
+ this.encoding = e;
+ return this;
+ }
+
+ @Override
+ public Charset encoding() {
+ return encoding == null ? Charset.defaultCharset() : encoding;
+ }
+
+ public boolean isDefaultJvmEncoding() {
+ return encoding == null;
+ }
+
+ public DefaultFileSystem setWorkDir(File d) {
+ this.workDir = d.getAbsoluteFile();
+ return this;
+ }
+
+ @Override
+ public File workDir() {
+ return workDir;
+ }
+
+ @Override
+ public InputFile inputFile(FilePredicate predicate) {
+ doPreloadFiles();
+ if (predicate instanceof RelativePathPredicate) {
+ return cache.inputFile((RelativePathPredicate) predicate);
+ }
+ Iterable<InputFile> files = inputFiles(predicate);
+ Iterator<InputFile> iterator = files.iterator();
+ if (!iterator.hasNext()) {
+ return null;
+ }
+ InputFile first = iterator.next();
+ if (!iterator.hasNext()) {
+ return first;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("expected one element but was: <" + first);
+ for (int i = 0; i < 4 && iterator.hasNext(); i++) {
+ sb.append(", " + iterator.next());
+ }
+ if (iterator.hasNext()) {
+ sb.append(", ...");
+ }
+ sb.append('>');
+
+ throw new IllegalArgumentException(sb.toString());
+
+ }
+
+ @Override
+ public Iterable<InputFile> inputFiles(FilePredicate predicate) {
+ doPreloadFiles();
+ return filter(cache.inputFiles(), predicate);
+ }
+
+ @Override
+ public boolean hasFiles(FilePredicate predicate) {
+ doPreloadFiles();
+ for (InputFile element : cache.inputFiles()) {
+ if (predicate.apply(element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Iterable<File> files(FilePredicate predicate) {
+ doPreloadFiles();
+ Collection<File> result = new ArrayList<File>();
+ for (InputFile element : inputFiles(predicate)) {
+ if (predicate.apply(element)) {
+ result.add(element.file());
+ }
+ }
+ return result;
+ }
+
+ public static Collection<InputFile> filter(Iterable<InputFile> target, FilePredicate predicate) {
+ Collection<InputFile> result = new ArrayList<InputFile>();
+ for (InputFile element : target) {
+ if (predicate.apply(element)) {
+ result.add(element);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Adds InputFile to the list and registers its language, if present.
+ */
+ public DefaultFileSystem add(InputFile inputFile) {
+ cache.add(inputFile);
+ if (inputFile.language() != null) {
+ languages.add(inputFile.language());
+ }
+ return this;
+ }
+
+ /**
+ * Adds a language to the list. To be used only for unit tests that need to use {@link #languages()} without
+ * using {@link #add(org.sonar.api.batch.fs.InputFile)}.
+ */
+ public DefaultFileSystem addLanguages(String language, String... others) {
+ languages.add(language);
+ Collections.addAll(languages, others);
+ return this;
+ }
+
+ @Override
+ public SortedSet<String> languages() {
+ doPreloadFiles();
+ return languages;
+ }
+
+ @Override
+ public FilePredicates predicates() {
+ return predicates;
+ }
+
+ /**
+ * This method is called before each search of files.
+ */
+ protected void doPreloadFiles() {
+ // nothing to do by default
+ }
+
+ public static abstract class Cache {
+ protected abstract Iterable<InputFile> inputFiles();
+
+ @CheckForNull
+ protected abstract InputFile inputFile(RelativePathPredicate predicate);
+
+ protected abstract void doAdd(InputFile inputFile);
+
+ final void add(InputFile inputFile) {
+ doAdd(inputFile);
+ }
+ }
+
+ /**
+ * Used only for testing
+ */
+ private static class MapCache extends Cache {
+ private final Map<String, InputFile> fileMap = new HashMap<String, InputFile>();
+
+ @Override
+ public Iterable<InputFile> inputFiles() {
+ return new ArrayList<InputFile>(fileMap.values());
+ }
+
+ @Override
+ public InputFile inputFile(RelativePathPredicate predicate) {
+ return fileMap.get(predicate.path());
+ }
+
+ @Override
+ protected void doAdd(InputFile inputFile) {
+ fileMap.put(inputFile.relativePath(), inputFile);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.FilenameUtils;
+
+import javax.annotation.CheckForNull;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @since 4.2
+ */
+public class DefaultInputFile implements InputFile, Serializable {
+
+ private final String relativePath;
+ private String absolutePath;
+ private String language;
+ private Type type = Type.MAIN;
+ private Status status;
+ private String hash;
+ private int lines;
+ private String key;
+
+ public DefaultInputFile(String relativePath) {
+ this.relativePath = FilenameUtils.normalize(relativePath);
+ }
+
+ @Override
+ public String relativePath() {
+ return relativePath;
+ }
+
+ /**
+ * Marked as nullable just for the unit tests that do not call {@link #setFile(java.io.File)}
+ * previously.
+ */
+ @Override
+ @CheckForNull
+ public String absolutePath() {
+ return absolutePath;
+ }
+
+ @Override
+ public File file() {
+ if (absolutePath == null) {
+ throw new IllegalStateException("Can not return the java.io.File because absolute path is not set (see method setFile(java.io.File))");
+ }
+ return new File(absolutePath);
+ }
+
+ /**
+ * Marked as nullable just for the unit tests that do not call {@link #setLanguage(String)}
+ * previously.
+ */
+ @CheckForNull
+ @Override
+ public String language() {
+ return language;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Marked as nullable just for the unit tests that do not previously call
+ * {@link #setStatus(org.sonar.api.batch.fs.InputFile.Status)}
+ */
+ @CheckForNull
+ @Override
+ public Status status() {
+ return status;
+ }
+
+ /**
+ * Digest hash of the file. Marked as nullable just for the unit tests
+ * that do not previously call {@link #setHash(String)}
+ */
+ @CheckForNull
+ public String hash() {
+ return hash;
+ }
+
+ @Override
+ public int lines() {
+ return lines;
+ }
+
+ /**
+ * Component key. It's marked as nullable just for the unit tests that
+ * do not previously call {@link #setKey(String)}.
+ */
+ @CheckForNull
+ public String key() {
+ return key;
+ }
+
+ public DefaultInputFile setAbsolutePath(String s) {
+ this.absolutePath = FilenameUtils.normalize(s);
+ return this;
+ }
+
+ public DefaultInputFile setLanguage(String language) {
+ this.language = language;
+ return this;
+ }
+
+ public DefaultInputFile setFile(File file) {
+ setAbsolutePath(file.getAbsolutePath());
+ return this;
+ }
+
+ public DefaultInputFile setType(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ public DefaultInputFile setStatus(Status status) {
+ this.status = status;
+ return this;
+ }
+
+ public DefaultInputFile setHash(String hash) {
+ this.hash = hash;
+ return this;
+ }
+
+ public DefaultInputFile setLines(int lines) {
+ this.lines = lines;
+ return this;
+ }
+
+ public DefaultInputFile setKey(String s) {
+ this.key = s;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DefaultInputFile)) {
+ return false;
+ }
+
+ DefaultInputFile that = (DefaultInputFile) o;
+ return relativePath.equals(that.relativePath);
+ }
+
+ @Override
+ public int hashCode() {
+ return relativePath.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "[relative=" + relativePath + ", abs=" + absolutePath + "]";
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+class FalsePredicate implements FilePredicate {
+
+ static final FilePredicate FALSE = new FalsePredicate();
+
+ @Override
+ public boolean apply(InputFile inputFile) {
+ return false;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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());
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * @since 4.2
+ */
+class OrPredicate implements FilePredicate {
+
+ private final Collection<FilePredicate> predicates;
+
+ OrPredicate(Collection<FilePredicate> predicates) {
+ if (predicates.isEmpty()) {
+ this.predicates = Arrays.asList(TruePredicate.TRUE);
+ } else {
+ this.predicates = predicates;
+ }
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ for (FilePredicate predicate : predicates) {
+ if (predicate.apply(f)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.FilenameUtils;
+import org.sonar.batch.api.internal.StringUtils;
+import org.sonar.batch.api.internal.WildcardPattern;
+
+public abstract class PathPattern {
+
+ final WildcardPattern pattern;
+
+ PathPattern(String pattern) {
+ this.pattern = WildcardPattern.create(pattern);
+ }
+
+ public abstract boolean match(InputFile inputFile);
+
+ public abstract boolean match(InputFile inputFile, boolean caseSensitiveFileExtension);
+
+ public static PathPattern create(String s) {
+ String trimmed = StringUtils.trim(s);
+ if (StringUtils.startsWithIgnoreCase(trimmed, "file:")) {
+ return new AbsolutePathPattern(StringUtils.substring(trimmed, "file:".length()));
+ }
+ return new RelativePathPattern(trimmed);
+ }
+
+ public static PathPattern[] create(String[] s) {
+ PathPattern[] result = new PathPattern[s.length];
+ for (int i = 0; i < s.length; i++) {
+ result[i] = create(s[i]);
+ }
+ return result;
+ }
+
+ private static class AbsolutePathPattern extends PathPattern {
+ private AbsolutePathPattern(String pattern) {
+ super(pattern);
+ }
+
+ @Override
+ public boolean match(InputFile inputFile) {
+ return match(inputFile, true);
+ }
+
+ @Override
+ public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
+ String path = inputFile.absolutePath();
+ if (!caseSensitiveFileExtension) {
+ String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
+ if (StringUtils.isNotBlank(extension)) {
+ path = StringUtils.removeEndIgnoreCase(path, extension);
+ path = path + extension;
+ }
+ }
+ return pattern.match(path);
+ }
+
+ @Override
+ public String toString() {
+ return "file:" + pattern.toString();
+ }
+ }
+
+ /**
+ * Path relative to module basedir
+ */
+ private static class RelativePathPattern extends PathPattern {
+ private RelativePathPattern(String pattern) {
+ super(pattern);
+ }
+
+ @Override
+ public boolean match(InputFile inputFile) {
+ return match(inputFile, true);
+ }
+
+ @Override
+ public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
+ String path = inputFile.relativePath();
+ if (!caseSensitiveFileExtension) {
+ String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
+ if (StringUtils.isNotBlank(extension)) {
+ path = StringUtils.removeEndIgnoreCase(path, extension);
+ path = path + extension;
+ }
+ }
+ return path != null && pattern.match(path);
+ }
+
+ @Override
+ public String toString() {
+ return pattern.toString();
+ }
+ }
+
+ static String sanitizeExtension(String suffix) {
+ return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.FilenameUtils;
+
+/**
+ * @since 4.2
+ */
+public class RelativePathPredicate implements FilePredicate {
+
+ private final String path;
+
+ RelativePathPredicate(String path) {
+ this.path = FilenameUtils.normalize(path);
+ }
+
+ public String path() {
+ return path;
+ }
+
+ @Override
+ public boolean apply(InputFile f) {
+ return path.equals(f.relativePath());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+class TruePredicate implements FilePredicate {
+
+ static final FilePredicate TRUE = new TruePredicate();
+
+ @Override
+ public boolean apply(InputFile inputFile) {
+ return true;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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();
+ }
+
+}
+
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.fs.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.fs;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api;
+
+/**
+ * Dependency Injection : all the classes implementing this interface are available in the batch IoC container.
+ * Just add a parameter to the constructor of your component.
+ *
+ * @since 4.4
+ */
+public interface BatchComponent {
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api;
+
+
+/**
+ * Batch extension point.
+ *
+ * @since 4.4
+ */
+public interface BatchExtension extends BatchComponent {
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Define instantiation strategy of batch extensions. If an extension is not annotated, then default value
+ * is {@link #PER_PROJECT}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface InstantiationStrategy {
+
+ /**
+ * Shared extension. Lifecycle is the full analysis.
+ */
+ String PER_BATCH = "PER_BATCH";
+
+ /**
+ * Created and initialized for each project and sub-project (a project is a module in Maven terminology).
+ */
+ String PER_PROJECT = "PER_PROJECT";
+
+ String value();
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.analyzer;
+
+import org.sonar.batch.api.BatchExtension;
+
+/**
+ * <p>
+ * An Analyzer is invoked once during the analysis of a project. The analyzer can parse a flat file, connect to a web server... Analyzers are
+ * used to add measure and issues at file level.
+ * </p>
+ *
+ * <p>
+ * For example the Cobertura Analyzer parses Cobertura report and saves the first-level of measures on files.
+ * </p>
+ *
+ * @since 4.4
+ */
+public interface Analyzer extends BatchExtension {
+
+ /**
+ * Describe what this analyzer is doing.
+ * @return
+ */
+ AnalyzerDescriptor describe();
+
+ /**
+ * The method that is going to be run when the analyzer is called
+ *
+ * @param context the context
+ */
+ void analyse(AnalyzerContext context);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.analyzer;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.analyzer.issue.AnalyzerIssue;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.api.measures.Metric;
+
+import javax.annotation.CheckForNull;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * @since 4.4
+ */
+public interface AnalyzerContext {
+
+ // ----------- MEASURES --------------
+
+ /**
+ * Find a project measure.
+ */
+ @CheckForNull
+ AnalyzerMeasure<?> getMeasure(String metricKey);
+
+ /**
+ * Find a project measure.
+ */
+ @CheckForNull
+ <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric);
+
+ /**
+ * Find a file measure.
+ */
+ @CheckForNull
+ AnalyzerMeasure<?> getMeasure(InputFile file, String metricKey);
+
+ /**
+ * Find a file measure.
+ */
+ @CheckForNull
+ <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric);
+
+ /**
+ * Add a measure.
+ */
+ void addMeasure(AnalyzerMeasure<?> measure);
+
+ // ----------- ISSUES --------------
+
+ /**
+ * Add an issue.
+ */
+ void addIssue(AnalyzerIssue issue);
+
+ /**
+ * Add a list of issues.
+ */
+ void addIssues(Collection<AnalyzerIssue> issues);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.analyzer;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.measures.Metric;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class AnalyzerDescriptor {
+
+ private final String name;
+ private final Metric<?>[] dependsOn;
+ private final Metric<?>[] provides;
+ private final String[] languages;
+ private final InputFile.Type[] types;
+
+ private AnalyzerDescriptor(Builder builder) {
+ this.name = builder.name;
+ this.dependsOn = builder.dependsOn != null ? builder.dependsOn : new Metric<?>[0];
+ this.provides = builder.provides != null ? builder.provides : new Metric<?>[0];
+ this.languages = builder.languages != null ? builder.languages : new String[0];
+ this.types = builder.types;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public Metric<?>[] dependsOn() {
+ return dependsOn;
+ }
+
+ public Metric<?>[] provides() {
+ return provides;
+ }
+
+ public Collection<String> languages() {
+ return Arrays.asList(languages);
+ }
+
+ public InputFile.Type[] types() {
+ return types;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private String name;
+ private Metric<?>[] dependsOn;
+ private Metric<?>[] provides;
+ private String[] languages;
+ private InputFile.Type[] types;
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder dependsOn(Metric<?>... metrics) {
+ this.dependsOn = metrics;
+ return this;
+ }
+
+ public Builder provides(Metric<?>... metrics) {
+ this.provides = metrics;
+ return this;
+ }
+
+ public Builder runOnLanguages(String... languageKeys) {
+ this.languages = languageKeys;
+ return this;
+ }
+
+ public Builder runOnTypes(InputFile.Type... types) {
+ this.types = types;
+ return this;
+ }
+
+ public AnalyzerDescriptor build() {
+ return new AnalyzerDescriptor(this);
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.analyzer.issue;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.internal.Preconditions;
+import org.sonar.batch.api.rules.RuleKey;
+
+import javax.annotation.Nullable;
+
+/**
+ * Issue reported by an {@link Analyzer}
+ *
+ * @since 4.4
+ */
+public class AnalyzerIssue {
+
+ private final InputFile inputFile;
+ private final RuleKey ruleKey;
+ private final String message;
+ private final Integer line;
+ private final Double effortToFix;
+
+ private AnalyzerIssue(Builder builder) {
+ this.inputFile = builder.file;
+ this.ruleKey = builder.ruleKey;
+ this.message = builder.message;
+ this.line = builder.line;
+ this.effortToFix = builder.effortToFix;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Nullable
+ public InputFile inputFile() {
+ return inputFile;
+ }
+
+ public RuleKey ruleKey() {
+ return ruleKey;
+ }
+
+ public String message() {
+ return message;
+ }
+
+ public Integer line() {
+ return line;
+ }
+
+ @Nullable
+ public Double effortToFix() {
+ return effortToFix;
+ }
+
+ public static class Builder {
+
+ private Boolean onProject = null;
+ private InputFile file;
+ private RuleKey ruleKey;
+ private String message;
+ private Integer line;
+ private Double effortToFix;
+
+ public AnalyzerIssue build() {
+ return new AnalyzerIssue(this);
+ }
+
+ public Builder ruleKey(RuleKey ruleKey) {
+ this.ruleKey = ruleKey;
+ return this;
+ }
+
+ public Builder onFile(InputFile file) {
+ Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+ Preconditions.checkNotNull(file, "InputFile should be non null");
+ this.file = file;
+ this.onProject = false;
+ return this;
+ }
+
+ public Builder onProject() {
+ Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+ this.file = null;
+ this.onProject = true;
+ return this;
+ }
+
+ public Builder atLine(int line) {
+ this.line = line;
+ return this;
+ }
+
+ public Builder effortToFix(@Nullable Double effortToFix) {
+ this.effortToFix = effortToFix;
+ return this;
+ }
+
+ public Builder message(String message) {
+ this.message = message;
+ return this;
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.analyzer.issue;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.analyzer.measure;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.Preconditions;
+import org.sonar.batch.api.measures.Metric;
+
+import javax.annotation.Nullable;
+
+import java.io.Serializable;
+
+public class AnalyzerMeasure<G extends Serializable> implements Serializable {
+
+ private final InputFile inputFile;
+ private final String metricKey;
+ private final G value;
+
+ private AnalyzerMeasure(Builder<G> builder) {
+ Preconditions.checkNotNull(builder.value, "Measure value can't be null");
+ Preconditions.checkNotNull(builder.metricKey, "Measure metricKey can't be null");
+ this.inputFile = builder.file;
+ this.metricKey = builder.metricKey;
+ this.value = builder.value;
+ }
+
+ @Nullable
+ public InputFile inputFile() {
+ return inputFile;
+ }
+
+ public String metricKey() {
+ return metricKey;
+ }
+
+ public Serializable value() {
+ return value;
+ }
+
+ public static <G extends Serializable> Builder<G> builder() {
+ return new Builder<G>();
+ }
+
+ public static class Builder<G extends Serializable> {
+
+ private Boolean onProject = null;
+ private InputFile file;
+ private String metricKey;
+ private G value;
+
+ public Builder<G> onFile(InputFile file) {
+ Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+ Preconditions.checkNotNull(file, "InputFile should be non null");
+ this.file = file;
+ this.onProject = false;
+ return this;
+ }
+
+ public Builder<G> onProject() {
+ Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+ this.file = null;
+ this.onProject = true;
+ return this;
+ }
+
+ private Builder<G> metricKey(String metricKey) {
+ Preconditions.checkState(metricKey != null, "Metric already defined");
+ this.metricKey = metricKey;
+ return this;
+ }
+
+ public Builder<G> forMetric(Metric<G> metric) {
+ return metricKey(metric.key());
+ }
+
+ public Builder<G> withValue(G value) {
+ Preconditions.checkState(value != null, "Measure value already defined");
+ Preconditions.checkNotNull(value, "Measure value can't be null");
+ this.value = value;
+ return this;
+ }
+
+ public AnalyzerMeasure<G> build() {
+ return new AnalyzerMeasure<G>(this);
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof AnalyzerMeasure)) {
+ return false;
+ }
+ AnalyzerMeasure<?> other = (AnalyzerMeasure<?>) obj;
+ return metricKey.equals(other.metricKey)
+ && value.equals(other.value)
+ && (inputFile == null ? other.inputFile == null : inputFile.equals(other.inputFile));
+ }
+
+ @Override
+ public int hashCode() {
+ return metricKey.hashCode()
+ + value.hashCode()
+ + (inputFile != null ? inputFile.hashCode() : 0);
+ }
+
+ @Override
+ public String toString() {
+ return "AnalyzerMeasure[" + (inputFile != null ? "inputFile=" + inputFile.toString() : "onProject")
+ + ",metricKey=" + metricKey + ",value=" + value + "]";
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.analyzer.measure;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.analyzer;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.internal;
+
+import java.io.File;
+
+/**
+ * Copied from commons io
+ *
+ */
+public class FilenameUtils {
+
+ public static final char EXTENSION_SEPARATOR = '.';
+
+ private static final char UNIX_SEPARATOR = '/';
+
+ /**
+ * The Windows separator character.
+ */
+ private static final char WINDOWS_SEPARATOR = '\\';
+
+ /**
+ * The system separator character.
+ */
+ private static final char SYSTEM_SEPARATOR = File.separatorChar;
+
+ /**
+ * The separator character that is the opposite of the system separator.
+ */
+ private static final char OTHER_SEPARATOR;
+ static {
+ if (isSystemWindows()) {
+ OTHER_SEPARATOR = UNIX_SEPARATOR;
+ } else {
+ OTHER_SEPARATOR = WINDOWS_SEPARATOR;
+ }
+ }
+
+ static boolean isSystemWindows() {
+ return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR;
+ }
+
+ public static String normalize(String filename) {
+ return doNormalize(filename, UNIX_SEPARATOR, true);
+ }
+
+ private static String doNormalize(String filename, char separator, boolean keepSeparator) {
+ if (filename == null) {
+ return null;
+ }
+ int size = filename.length();
+ if (size == 0) {
+ return filename;
+ }
+ int prefix = getPrefixLength(filename);
+ if (prefix < 0) {
+ return null;
+ }
+
+ char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy
+ filename.getChars(0, filename.length(), array, 0);
+
+ // fix separators throughout
+ char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR;
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == otherSeparator) {
+ array[i] = separator;
+ }
+ }
+
+ // add extra separator on the end to simplify code below
+ boolean lastIsDirectory = true;
+ if (array[size - 1] != separator) {
+ array[size++] = separator;
+ lastIsDirectory = false;
+ }
+
+ // adjoining slashes
+ for (int i = prefix + 1; i < size; i++) {
+ if (array[i] == separator && array[i - 1] == separator) {
+ System.arraycopy(array, i, array, i - 1, size - i);
+ size--;
+ i--;
+ }
+ }
+
+ // dot slash
+ for (int i = prefix + 1; i < size; i++) {
+ if (array[i] == separator && array[i - 1] == '.' &&
+ (i == prefix + 1 || array[i - 2] == separator)) {
+ if (i == size - 1) {
+ lastIsDirectory = true;
+ }
+ System.arraycopy(array, i + 1, array, i - 1, size - i);
+ size -= 2;
+ i--;
+ }
+ }
+
+ // double dot slash
+ outer: for (int i = prefix + 2; i < size; i++) {
+ if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' &&
+ (i == prefix + 2 || array[i - 3] == separator)) {
+ if (i == prefix + 2) {
+ return null;
+ }
+ if (i == size - 1) {
+ lastIsDirectory = true;
+ }
+ int j;
+ for (j = i - 4; j >= prefix; j--) {
+ if (array[j] == separator) {
+ // remove b/../ from a/b/../c
+ System.arraycopy(array, i + 1, array, j + 1, size - i);
+ size -= i - j;
+ i = j + 1;
+ continue outer;
+ }
+ }
+ // remove a/../ from a/../c
+ System.arraycopy(array, i + 1, array, prefix, size - i);
+ size -= i + 1 - prefix;
+ i = prefix + 1;
+ }
+ }
+
+ if (size <= 0) { // should never be less than 0
+ return "";
+ }
+ if (size <= prefix) { // should never be less than prefix
+ return new String(array, 0, size);
+ }
+ if (lastIsDirectory && keepSeparator) {
+ return new String(array, 0, size); // keep trailing separator
+ }
+ return new String(array, 0, size - 1); // lose trailing separator
+ }
+
+ public static int getPrefixLength(String filename) {
+ if (filename == null) {
+ return -1;
+ }
+ int len = filename.length();
+ if (len == 0) {
+ return 0;
+ }
+ char ch0 = filename.charAt(0);
+ if (ch0 == ':') {
+ return -1;
+ }
+ if (len == 1) {
+ if (ch0 == '~') {
+ return 2; // return a length greater than the input
+ }
+ return isSeparator(ch0) ? 1 : 0;
+ } else {
+ if (ch0 == '~') {
+ int posUnix = filename.indexOf(UNIX_SEPARATOR, 1);
+ int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1);
+ if (posUnix == -1 && posWin == -1) {
+ return len + 1; // return a length greater than the input
+ }
+ posUnix = posUnix == -1 ? posWin : posUnix;
+ posWin = posWin == -1 ? posUnix : posWin;
+ return Math.min(posUnix, posWin) + 1;
+ }
+ char ch1 = filename.charAt(1);
+ if (ch1 == ':') {
+ ch0 = Character.toUpperCase(ch0);
+ if (ch0 >= 'A' && ch0 <= 'Z') {
+ if (len == 2 || isSeparator(filename.charAt(2)) == false) {
+ return 2;
+ }
+ return 3;
+ }
+ return -1;
+
+ } else if (isSeparator(ch0) && isSeparator(ch1)) {
+ int posUnix = filename.indexOf(UNIX_SEPARATOR, 2);
+ int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2);
+ if (posUnix == -1 && posWin == -1 || posUnix == 2 || posWin == 2) {
+ return -1;
+ }
+ posUnix = posUnix == -1 ? posWin : posUnix;
+ posWin = posWin == -1 ? posUnix : posWin;
+ return Math.min(posUnix, posWin) + 1;
+ } else {
+ return isSeparator(ch0) ? 1 : 0;
+ }
+ }
+ }
+
+ private static boolean isSeparator(char ch) {
+ return ch == UNIX_SEPARATOR || ch == WINDOWS_SEPARATOR;
+ }
+
+ public static String getExtension(String filename) {
+ if (filename == null) {
+ return null;
+ }
+ int index = indexOfExtension(filename);
+ if (index == -1) {
+ return "";
+ } else {
+ return filename.substring(index + 1);
+ }
+ }
+
+ public static int indexOfExtension(String filename) {
+ if (filename == null) {
+ return -1;
+ }
+ int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
+ int lastSeparator = indexOfLastSeparator(filename);
+ return lastSeparator > extensionPos ? -1 : extensionPos;
+ }
+
+ public static int indexOfLastSeparator(String filename) {
+ if (filename == null) {
+ return -1;
+ }
+ int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
+ int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
+ return Math.max(lastUnixPos, lastWindowsPos);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.internal;
+
+import javax.annotation.Nullable;
+
+/**
+ * Copied from Guava
+ */
+public final class Preconditions {
+ private Preconditions() {
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the
+ * calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(boolean expression) {
+ if (!expression) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the
+ * calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessage the exception message to use if the check fails; will
+ * be converted to a string using {@link String#valueOf(Object)}
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(
+ boolean expression, @Nullable Object errorMessage) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the
+ * calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessageTemplate a template for the exception message should the
+ * check fail. The message is formed by replacing each {@code %s}
+ * placeholder in the template with an argument. These are matched by
+ * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+ * Unmatched arguments will be appended to the formatted message in square
+ * braces. Unmatched placeholders will be left as-is.
+ * @param errorMessageArgs the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}.
+ * @throws IllegalArgumentException if {@code expression} is false
+ * @throws NullPointerException if the check fails and either {@code
+ * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+ * this happen)
+ */
+ public static void checkArgument(boolean expression,
+ @Nullable String errorMessageTemplate,
+ @Nullable Object... errorMessageArgs) {
+ if (!expression) {
+ throw new IllegalArgumentException(
+ format(errorMessageTemplate, errorMessageArgs));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling
+ * instance, but not involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(boolean expression) {
+ if (!expression) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling
+ * instance, but not involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessage the exception message to use if the check fails; will
+ * be converted to a string using {@link String#valueOf(Object)}
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(
+ boolean expression, @Nullable Object errorMessage) {
+ if (!expression) {
+ throw new IllegalStateException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling
+ * instance, but not involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessageTemplate a template for the exception message should the
+ * check fail. The message is formed by replacing each {@code %s}
+ * placeholder in the template with an argument. These are matched by
+ * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+ * Unmatched arguments will be appended to the formatted message in square
+ * braces. Unmatched placeholders will be left as-is.
+ * @param errorMessageArgs the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}.
+ * @throws IllegalStateException if {@code expression} is false
+ * @throws NullPointerException if the check fails and either {@code
+ * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+ * this happen)
+ */
+ public static void checkState(boolean expression,
+ @Nullable String errorMessageTemplate,
+ @Nullable Object... errorMessageArgs) {
+ if (!expression) {
+ throw new IllegalStateException(
+ format(errorMessageTemplate, errorMessageArgs));
+ }
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling
+ * method is not null.
+ *
+ * @param reference an object reference
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ public static <T> T checkNotNull(T reference) {
+ if (reference == null) {
+ throw new NullPointerException();
+ }
+ return reference;
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling
+ * method is not null.
+ *
+ * @param reference an object reference
+ * @param errorMessage the exception message to use if the check fails; will
+ * be converted to a string using {@link String#valueOf(Object)}
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ public static <T> T checkNotNull(T reference, @Nullable Object errorMessage) {
+ if (reference == null) {
+ throw new NullPointerException(String.valueOf(errorMessage));
+ }
+ return reference;
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling
+ * method is not null.
+ *
+ * @param reference an object reference
+ * @param errorMessageTemplate a template for the exception message should the
+ * check fail. The message is formed by replacing each {@code %s}
+ * placeholder in the template with an argument. These are matched by
+ * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+ * Unmatched arguments will be appended to the formatted message in square
+ * braces. Unmatched placeholders will be left as-is.
+ * @param errorMessageArgs the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}.
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ public static <T> T checkNotNull(T reference,
+ @Nullable String errorMessageTemplate,
+ @Nullable Object... errorMessageArgs) {
+ if (reference == null) {
+ // If either of these parameters is null, the right thing happens anyway
+ throw new NullPointerException(
+ format(errorMessageTemplate, errorMessageArgs));
+ }
+ return reference;
+ }
+
+ /*
+ * All recent hotspots (as of 2009) *really* like to have the natural code
+ *
+ * if (guardExpression) {
+ * throw new BadException(messageExpression);
+ * }
+ *
+ * refactored so that messageExpression is moved to a separate
+ * String-returning method.
+ *
+ * if (guardExpression) {
+ * throw new BadException(badMsg(...));
+ * }
+ *
+ * The alternative natural refactorings into void or Exception-returning
+ * methods are much slower. This is a big deal - we're talking factors of
+ * 2-8 in microbenchmarks, not just 10-20%. (This is a hotspot optimizer
+ * bug, which should be fixed, but that's a separate, big project).
+ *
+ * The coding pattern above is heavily used in java.util, e.g. in ArrayList.
+ * There is a RangeCheckMicroBenchmark in the JDK that was used to test this.
+ *
+ * But the methods in this class want to throw different exceptions,
+ * depending on the args, so it appears that this pattern is not directly
+ * applicable. But we can use the ridiculous, devious trick of throwing an
+ * exception in the middle of the construction of another exception.
+ * Hotspot is fine with that.
+ */
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+ * list or string of size {@code size}. An element index may range from zero,
+ * inclusive, to {@code size}, exclusive.
+ *
+ * @param index a user-supplied index identifying an element of an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+ * less than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkElementIndex(int index, int size) {
+ return checkElementIndex(index, size, "index");
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+ * list or string of size {@code size}. An element index may range from zero,
+ * inclusive, to {@code size}, exclusive.
+ *
+ * @param index a user-supplied index identifying an element of an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @param desc the text to use to describe this index in an error message
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+ * less than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkElementIndex(
+ int index, int size, @Nullable String desc) {
+ // Carefully optimized for execution by hotspot (explanatory comment above)
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
+ }
+ return index;
+ }
+
+ private static String badElementIndex(int index, int size, String desc) {
+ if (index < 0) {
+ return format("%s (%s) must not be negative", desc, index);
+ } else if (size < 0) {
+ throw new IllegalArgumentException("negative size: " + size);
+ } else { // index >= size
+ return format("%s (%s) must be less than size (%s)", desc, index, size);
+ }
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+ * list or string of size {@code size}. A position index may range from zero
+ * to {@code size}, inclusive.
+ *
+ * @param index a user-supplied index identifying a position in an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is
+ * greater than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkPositionIndex(int index, int size) {
+ return checkPositionIndex(index, size, "index");
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+ * list or string of size {@code size}. A position index may range from zero
+ * to {@code size}, inclusive.
+ *
+ * @param index a user-supplied index identifying a position in an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @param desc the text to use to describe this index in an error message
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is
+ * greater than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkPositionIndex(
+ int index, int size, @Nullable String desc) {
+ // Carefully optimized for execution by hotspot (explanatory comment above)
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
+ }
+ return index;
+ }
+
+ private static String badPositionIndex(int index, int size, String desc) {
+ if (index < 0) {
+ return format("%s (%s) must not be negative", desc, index);
+ } else if (size < 0) {
+ throw new IllegalArgumentException("negative size: " + size);
+ } else { // index > size
+ return format("%s (%s) must not be greater than size (%s)",
+ desc, index, size);
+ }
+ }
+
+ /**
+ * Ensures that {@code start} and {@code end} specify a valid <i>positions</i>
+ * in an array, list or string of size {@code size}, and are in order. A
+ * position index may range from zero to {@code size}, inclusive.
+ *
+ * @param start a user-supplied index identifying a starting position in an
+ * array, list or string
+ * @param end a user-supplied index identifying a ending position in an array,
+ * list or string
+ * @param size the size of that array, list or string
+ * @throws IndexOutOfBoundsException if either index is negative or is
+ * greater than {@code size}, or if {@code end} is less than {@code start}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static void checkPositionIndexes(int start, int end, int size) {
+ // Carefully optimized for execution by hotspot (explanatory comment above)
+ if (start < 0 || end < start || end > size) {
+ throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
+ }
+ }
+
+ private static String badPositionIndexes(int start, int end, int size) {
+ if (start < 0 || start > size) {
+ return badPositionIndex(start, size, "start index");
+ }
+ if (end < 0 || end > size) {
+ return badPositionIndex(end, size, "end index");
+ }
+ // end < start
+ return format("end index (%s) must not be less than start index (%s)",
+ end, start);
+ }
+
+ /**
+ * Substitutes each {@code %s} in {@code template} with an argument. These
+ * are matched by position - the first {@code %s} gets {@code args[0]}, etc.
+ * If there are more arguments than placeholders, the unmatched arguments will
+ * be appended to the end of the formatted message in square braces.
+ *
+ * @param template a non-null string containing 0 or more {@code %s}
+ * placeholders.
+ * @param args the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}. Arguments can be null.
+ */
+ static String format(String template,
+ @Nullable Object... args) {
+ template = String.valueOf(template); // null -> "null"
+
+ // start substituting the arguments into the '%s' placeholders
+ StringBuilder builder = new StringBuilder(
+ template.length() + 16 * args.length);
+ int templateStart = 0;
+ int i = 0;
+ while (i < args.length) {
+ int placeholderStart = template.indexOf("%s", templateStart);
+ if (placeholderStart == -1) {
+ break;
+ }
+ builder.append(template.substring(templateStart, placeholderStart));
+ builder.append(args[i++]);
+ templateStart = placeholderStart + 2;
+ }
+ builder.append(template.substring(templateStart));
+
+ // if we run out of placeholders, append the extra args in square braces
+ if (i < args.length) {
+ builder.append(" [");
+ builder.append(args[i++]);
+ while (i < args.length) {
+ builder.append(", ");
+ builder.append(args[i++]);
+ }
+ builder.append(']');
+ }
+
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.internal;
+
+/**
+ * Copied from commons lang
+ */
+public class StringUtils {
+
+ public static final String EMPTY = "";
+
+ public static String trim(String str) {
+ return str == null ? null : str.trim();
+ }
+
+ public static String removeStart(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (str.startsWith(remove)) {
+ return str.substring(remove.length());
+ }
+ return str;
+ }
+
+ public static String removeEnd(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (str.endsWith(remove)) {
+ return str.substring(0, str.length() - remove.length());
+ }
+ return str;
+ }
+
+ public static boolean isEmpty(String str) {
+ return str == null || str.length() == 0;
+ }
+
+ public static boolean startsWithIgnoreCase(String str, String prefix) {
+ return startsWith(str, prefix, true);
+ }
+
+ private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
+ if (str == null || prefix == null) {
+ return (str == null && prefix == null);
+ }
+ if (prefix.length() > str.length()) {
+ return false;
+ }
+ return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
+ }
+
+ public static String substring(String str, int start) {
+ if (str == null) {
+ return null;
+ }
+
+ // handle negatives, which means last n characters
+ if (start < 0) {
+ start = str.length() + start; // remember start is negative
+ }
+
+ if (start < 0) {
+ start = 0;
+ }
+ if (start > str.length()) {
+ return EMPTY;
+ }
+
+ return str.substring(start);
+ }
+
+ public static boolean isBlank(String str) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return true;
+ }
+ for (int i = 0; i < strLen; i++) {
+ if ((Character.isWhitespace(str.charAt(i)) == false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isNotBlank(String str) {
+ return !StringUtils.isBlank(str);
+ }
+
+ public static String removeEndIgnoreCase(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (endsWithIgnoreCase(str, remove)) {
+ return str.substring(0, str.length() - remove.length());
+ }
+ return str;
+ }
+
+ public static boolean endsWithIgnoreCase(String str, String suffix) {
+ return endsWith(str, suffix, true);
+ }
+
+ private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
+ if (str == null || suffix == null) {
+ return (str == null && suffix == null);
+ }
+ if (suffix.length() > str.length()) {
+ return false;
+ }
+ int strOffset = str.length() - suffix.length();
+ return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
+ }
+
+ public static String lowerCase(String str) {
+ if (str == null) {
+ return null;
+ }
+ return str.toLowerCase();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * Implementation of Ant-style matching patterns.
+ * Contrary to other implementations (like AntPathMatcher from Spring Framework) it is based on {@link Pattern Java Regular Expressions}.
+ * To increase performance it holds an internal cache of all processed patterns.
+ * <p>
+ * Following rules are applied:
+ * <ul>
+ * <li>? matches single character</li>
+ * <li>* matches zero or more characters</li>
+ * <li>** matches zero or more 'directories'</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Some examples of patterns:
+ * <ul>
+ * <li><code>org/T?st.java</code> - matches <code>org/Test.java</code> and also <code>org/Tost.java</code></li>
+ * <li><code>org/*.java</code> - matches all <code>.java</code> files in the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/Bar.java</code></li>
+ * <li><code>org/**</code> - matches all files underneath the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/foo/bar.jsp</code></li>
+ * <li><code>org/**/Test.java</code> - matches all <code>Test.java</code> files underneath the <code>org</code> directory,
+ * e.g. <code>org/Test.java</code> or <code>org/foo/Test.java</code> or <code>org/foo/bar/Test.java</code></li>
+ * <li><code>org/**/*.java</code> - matches all <code>.java</code> files underneath the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/foo/Bar.java</code> or <code>org/foo/bar/Baz.java</code></li>
+ * </ul>
+ * </p>
+ * <p>
+ * Another implementation, which is also based on Java Regular Expressions, can be found in
+ * <a href="https://github.com/JetBrains/intellij-community/blob/idea/107.743/platform/util/src/com/intellij/openapi/util/io/FileUtil.java#L847">FileUtil</a>
+ * from IntelliJ OpenAPI.
+ * </p>
+ *
+ */
+public class WildcardPattern {
+
+ private static final Map<String, WildcardPattern> CACHE = new HashMap<String, WildcardPattern>();
+ private static final String SPECIAL_CHARS = "()[]^$.{}+|";
+
+ private Pattern pattern;
+ private String stringRepresentation;
+
+ protected WildcardPattern(String pattern, String directorySeparator) {
+ this.stringRepresentation = pattern;
+ this.pattern = Pattern.compile(toRegexp(pattern, directorySeparator));
+ }
+
+ private static String toRegexp(String antPattern, String directorySeparator) {
+ final String escapedDirectorySeparator = '\\' + directorySeparator;
+
+ final StringBuilder sb = new StringBuilder(antPattern.length());
+
+ sb.append('^');
+
+ int i = antPattern.startsWith("/") || antPattern.startsWith("\\") ? 1 : 0;
+ while (i < antPattern.length()) {
+ final char ch = antPattern.charAt(i);
+
+ if (SPECIAL_CHARS.indexOf(ch) != -1) {
+ // Escape regexp-specific characters
+ sb.append('\\').append(ch);
+ } else if (ch == '*') {
+ if (i + 1 < antPattern.length() && antPattern.charAt(i + 1) == '*') {
+ // Double asterisk
+ // Zero or more directories
+ if (i + 2 < antPattern.length() && isSlash(antPattern.charAt(i + 2))) {
+ sb.append("(?:.*").append(escapedDirectorySeparator).append("|)");
+ i += 2;
+ } else {
+ sb.append(".*");
+ i += 1;
+ }
+ } else {
+ // Single asterisk
+ // Zero or more characters excluding directory separator
+ sb.append("[^").append(escapedDirectorySeparator).append("]*?");
+ }
+ } else if (ch == '?') {
+ // Any single character excluding directory separator
+ sb.append("[^").append(escapedDirectorySeparator).append("]");
+ } else if (isSlash(ch)) {
+ // Directory separator
+ sb.append(escapedDirectorySeparator);
+ } else {
+ // Single character
+ sb.append(ch);
+ }
+
+ i++;
+ }
+
+ sb.append('$');
+
+ return sb.toString();
+ }
+
+ private static boolean isSlash(char ch) {
+ return ch == '/' || ch == '\\';
+ }
+
+ /**
+ * Returns string representation of this pattern.
+ *
+ * @since 2.5
+ */
+ @Override
+ public String toString() {
+ return stringRepresentation;
+ }
+
+ /**
+ * Returns true if specified value matches this pattern.
+ */
+ public boolean match(String value) {
+ value = StringUtils.removeStart(value, "/");
+ value = StringUtils.removeEnd(value, "/");
+ return pattern.matcher(value).matches();
+ }
+
+ /**
+ * Returns true if specified value matches one of specified patterns.
+ *
+ * @since 2.4
+ */
+ public static boolean match(WildcardPattern[] patterns, String value) {
+ for (WildcardPattern pattern : patterns) {
+ if (pattern.match(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates pattern with "/" as a directory separator.
+ *
+ * @see #create(String, String)
+ */
+ public static WildcardPattern create(String pattern) {
+ return create(pattern, "/");
+ }
+
+ /**
+ * Creates array of patterns with "/" as a directory separator.
+ *
+ * @see #create(String, String)
+ */
+ public static WildcardPattern[] create(String[] patterns) {
+ if (patterns == null) {
+ return new WildcardPattern[0];
+ }
+ WildcardPattern[] exclusionPAtterns = new WildcardPattern[patterns.length];
+ for (int i = 0; i < patterns.length; i++) {
+ exclusionPAtterns[i] = create(patterns[i]);
+ }
+ return exclusionPAtterns;
+ }
+
+ /**
+ * Creates pattern with specified separator for directories.
+ * <p>
+ * This is used to match Java-classes, i.e. <code>org.foo.Bar</code> against <code>org/**</code>.
+ * <b>However usage of character other than "/" as a directory separator is misleading and should be avoided,
+ * so method {@link #create(String)} is preferred over this one.</b>
+ * </p>
+ * <p>
+ * Also note that no matter whether forward or backward slashes were used in the <code>antPattern</code>
+ * the returned pattern will use <code>directorySeparator</code>.
+ * Thus to match Windows-style path "dir\file.ext" against pattern "dir/file.ext" normalization should be performed.
+ * </p>
+ */
+ public static WildcardPattern create(String pattern, String directorySeparator) {
+ String key = pattern + directorySeparator;
+ WildcardPattern wildcardPattern = CACHE.get(key);
+ if (wildcardPattern == null) {
+ wildcardPattern = new WildcardPattern(pattern, directorySeparator);
+ CACHE.put(key, wildcardPattern);
+ }
+ return wildcardPattern;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.internal;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.languages;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public final class Language {
+
+ private final String key, name;
+ private final String[] fileSuffixes;
+
+ public Language(String key, String name, String... fileSuffixes) {
+ this.key = key;
+ this.name = name;
+ this.fileSuffixes = fileSuffixes;
+ }
+
+ /**
+ * For example "java".
+ */
+ public String key() {
+ return key;
+ }
+
+ /**
+ * For example "Java"
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * For example ["jav", "java"].
+ */
+ public Collection<String> fileSuffixes() {
+ return Arrays.asList(fileSuffixes);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.languages;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.measures;
+
+import java.io.Serializable;
+
+public interface Metric<G extends Serializable> {
+
+ Class<G> type();
+
+ String key();
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.measures;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.rules;
+
+public class QProfile {
+ private final String name, language;
+ private final Integer version;
+
+ public QProfile(String name, String language, Integer version) {
+ this.name = name;
+ this.language = language;
+ this.version = version;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public String language() {
+ return language;
+ }
+
+ public Integer version() {
+ return version;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.rules;
+
+import java.io.Serializable;
+
+/**
+ * Key of a rule. Unique among all the rule repositories.
+ *
+ * @since 3.6
+ */
+public class RuleKey implements Serializable {
+ private final String repository, rule;
+
+ protected RuleKey(String repositoryKey, String ruleKey) {
+ this.repository = repositoryKey;
+ this.rule = ruleKey;
+ }
+
+ /**
+ * Create a key. Parameters are NOT null.
+ */
+ public static RuleKey of(String repository, String rule) {
+ return new RuleKey(repository, rule);
+ }
+
+ /**
+ * Never null
+ */
+ public String repository() {
+ return repository;
+ }
+
+ /**
+ * Never null
+ */
+ public String rule() {
+ return rule;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ RuleKey ruleKey = (RuleKey) o;
+ if (!repository.equals(ruleKey.repository)) {
+ return false;
+ }
+ if (!rule.equals(ruleKey.rule)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = repository.hashCode();
+ result = 31 * result + rule.hashCode();
+ return result;
+ }
+
+ /**
+ * Format is "repository:rule", for example "squid:AvoidCycle"
+ */
+ @Override
+ public String toString() {
+ return String.format("%s:%s", repository, rule);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.rules;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.fest.assertions.Assertions;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DefaultFilePredicatesTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ DefaultInputFile javaFile;
+ FilePredicates predicates = new DefaultFilePredicates();
+
+ @Before
+ public void before() throws IOException {
+ javaFile = new DefaultInputFile("src/main/java/struts/Action.java")
+ .setFile(temp.newFile("Action.java"))
+ .setLanguage("java")
+ .setStatus(InputFile.Status.ADDED);
+ }
+
+ @Test
+ public void all() throws Exception {
+ Assertions.assertThat(predicates.all().apply(javaFile)).isTrue();
+ }
+
+ @Test
+ public void none() throws Exception {
+ assertThat(predicates.none().apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void matches_inclusion_pattern() throws Exception {
+ assertThat(predicates.matchesPathPattern("src/main/**/Action.java").apply(javaFile)).isTrue();
+ assertThat(predicates.matchesPathPattern("Action.java").apply(javaFile)).isFalse();
+ assertThat(predicates.matchesPathPattern("src/**/*.php").apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void matches_inclusion_patterns() throws Exception {
+ assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isTrue();
+ assertThat(predicates.matchesPathPatterns(new String[] {}).apply(javaFile)).isTrue();
+ assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void does_not_match_exclusion_pattern() throws Exception {
+ assertThat(predicates.doesNotMatchPathPattern("src/main/**/Action.java").apply(javaFile)).isFalse();
+ assertThat(predicates.doesNotMatchPathPattern("Action.java").apply(javaFile)).isTrue();
+ assertThat(predicates.doesNotMatchPathPattern("src/**/*.php").apply(javaFile)).isTrue();
+ }
+
+ @Test
+ public void does_not_match_exclusion_patterns() throws Exception {
+ assertThat(predicates.doesNotMatchPathPatterns(new String[] {}).apply(javaFile)).isTrue();
+ assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isTrue();
+ assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void has_relative_path() throws Exception {
+ assertThat(predicates.hasRelativePath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
+ assertThat(predicates.hasRelativePath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
+
+ // path is normalized
+ assertThat(predicates.hasRelativePath("src/main/java/../java/struts/Action.java").apply(javaFile)).isTrue();
+
+ assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Action.java").apply(javaFile)).isTrue();
+ assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Other.java").apply(javaFile)).isFalse();
+ assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\..\\struts\\Action.java").apply(javaFile)).isTrue();
+ }
+
+ @Test
+ public void has_absolute_path() throws Exception {
+ String path = javaFile.file().getAbsolutePath();
+ assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
+ assertThat(predicates.hasAbsolutePath(path.replaceAll("/", "\\\\")).apply(javaFile)).isTrue();
+
+ assertThat(predicates.hasAbsolutePath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
+ assertThat(predicates.hasAbsolutePath("src/main/java/struts/Action.java").apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void has_path() throws Exception {
+ // is relative path
+ assertThat(predicates.hasPath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
+ assertThat(predicates.hasPath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
+
+ // is absolute path
+ String path = javaFile.file().getAbsolutePath();
+ assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
+ assertThat(predicates.hasPath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void is_file() throws Exception {
+ // relative file
+ assertThat(predicates.is(new File(javaFile.relativePath())).apply(javaFile)).isTrue();
+
+ // absolute file
+ assertThat(predicates.is(javaFile.file()).apply(javaFile)).isTrue();
+ assertThat(predicates.is(javaFile.file().getAbsoluteFile()).apply(javaFile)).isTrue();
+ assertThat(predicates.is(javaFile.file().getCanonicalFile()).apply(javaFile)).isTrue();
+ assertThat(predicates.is(new File(javaFile.file().toURI())).apply(javaFile)).isTrue();
+ assertThat(predicates.is(temp.newFile()).apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void has_language() throws Exception {
+ assertThat(predicates.hasLanguage("java").apply(javaFile)).isTrue();
+ assertThat(predicates.hasLanguage("php").apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void has_languages() throws Exception {
+ assertThat(predicates.hasLanguages(Arrays.asList("java", "php")).apply(javaFile)).isTrue();
+ assertThat(predicates.hasLanguages(Arrays.asList("cobol", "php")).apply(javaFile)).isFalse();
+ assertThat(predicates.hasLanguages(Collections.<String>emptyList()).apply(javaFile)).isTrue();
+ }
+
+ @Test
+ public void has_status() throws Exception {
+ assertThat(predicates.hasStatus(InputFile.Status.ADDED).apply(javaFile)).isTrue();
+ assertThat(predicates.hasStatus(InputFile.Status.CHANGED).apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void has_type() throws Exception {
+ assertThat(predicates.hasType(InputFile.Type.MAIN).apply(javaFile)).isTrue();
+ assertThat(predicates.hasType(InputFile.Type.TEST).apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void not() throws Exception {
+ assertThat(predicates.not(predicates.hasType(InputFile.Type.MAIN)).apply(javaFile)).isFalse();
+ assertThat(predicates.not(predicates.hasType(InputFile.Type.TEST)).apply(javaFile)).isTrue();
+ }
+
+ @Test
+ public void and() throws Exception {
+ // empty
+ assertThat(predicates.and().apply(javaFile)).isTrue();
+ assertThat(predicates.and(new FilePredicate[0]).apply(javaFile)).isTrue();
+ assertThat(predicates.and(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
+
+ // two arguments
+ assertThat(predicates.and(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
+ assertThat(predicates.and(predicates.all(), predicates.none()).apply(javaFile)).isFalse();
+ assertThat(predicates.and(predicates.none(), predicates.all()).apply(javaFile)).isFalse();
+
+ // collection
+ assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
+ assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isFalse();
+
+ // array
+ assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
+ assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isFalse();
+ }
+
+ @Test
+ public void or() throws Exception {
+ // empty
+ assertThat(predicates.or().apply(javaFile)).isTrue();
+ assertThat(predicates.or(new FilePredicate[0]).apply(javaFile)).isTrue();
+ assertThat(predicates.or(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
+
+ // two arguments
+ assertThat(predicates.or(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
+ assertThat(predicates.or(predicates.all(), predicates.none()).apply(javaFile)).isTrue();
+ assertThat(predicates.or(predicates.none(), predicates.all()).apply(javaFile)).isTrue();
+ assertThat(predicates.or(predicates.none(), predicates.none()).apply(javaFile)).isFalse();
+
+ // collection
+ assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
+ assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isTrue();
+ assertThat(predicates.or(Arrays.asList(predicates.none(), predicates.none())).apply(javaFile)).isFalse();
+
+ // array
+ assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
+ assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isTrue();
+ assertThat(predicates.or(new FilePredicate[] {predicates.none(), predicates.none()}).apply(javaFile)).isFalse();
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.nio.charset.Charset;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DefaultFileSystemTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void test_directories() throws Exception {
+ DefaultFileSystem fs = new DefaultFileSystem();
+
+ File basedir = temp.newFolder();
+ fs.setBaseDir(basedir);
+ assertThat(fs.baseDir()).isAbsolute().isDirectory().exists();
+ assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
+
+ File workdir = temp.newFolder();
+ fs.setWorkDir(workdir);
+ assertThat(fs.workDir()).isAbsolute().isDirectory().exists();
+ assertThat(fs.workDir().getCanonicalPath()).isEqualTo(workdir.getCanonicalPath());
+ }
+
+ @Test
+ public void test_encoding() throws Exception {
+ DefaultFileSystem fs = new DefaultFileSystem();
+
+ assertThat(fs.isDefaultJvmEncoding()).isTrue();
+ assertThat(fs.encoding()).isEqualTo(Charset.defaultCharset());
+
+ fs.setEncoding(Charset.forName("ISO-8859-1"));
+ assertThat(fs.encoding()).isEqualTo(Charset.forName("ISO-8859-1"));
+ assertThat(fs.isDefaultJvmEncoding()).isFalse();
+ }
+
+ @Test
+ public void add_languages() throws Exception {
+ DefaultFileSystem fs = new DefaultFileSystem();
+
+ assertThat(fs.languages()).isEmpty();
+
+ fs.addLanguages("java", "php", "cobol");
+ assertThat(fs.languages()).containsOnly("cobol", "java", "php");
+ }
+
+ @Test
+ public void files() throws Exception {
+ DefaultFileSystem fs = new DefaultFileSystem();
+
+ assertThat(fs.inputFiles(fs.predicates().all())).isEmpty();
+
+ fs.add(new DefaultInputFile("src/Foo.php").setLanguage("php").setFile(temp.newFile()));
+ fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
+ fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
+
+ // no language
+ fs.add(new DefaultInputFile("src/readme.txt").setFile(temp.newFile()));
+
+ assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNotNull();
+ assertThat(fs.inputFile(fs.predicates().hasRelativePath("does/not/exist"))).isNull();
+
+ assertThat(fs.files(fs.predicates().all())).hasSize(4);
+ assertThat(fs.files(fs.predicates().hasLanguage("java"))).hasSize(2);
+ assertThat(fs.files(fs.predicates().hasLanguage("cobol"))).isEmpty();
+
+ assertThat(fs.hasFiles(fs.predicates().all())).isTrue();
+ assertThat(fs.hasFiles(fs.predicates().hasLanguage("java"))).isTrue();
+ assertThat(fs.hasFiles(fs.predicates().hasLanguage("cobol"))).isFalse();
+
+ assertThat(fs.inputFiles(fs.predicates().all())).hasSize(4);
+ assertThat(fs.inputFiles(fs.predicates().hasLanguage("php"))).hasSize(1);
+ assertThat(fs.inputFiles(fs.predicates().hasLanguage("java"))).hasSize(2);
+ assertThat(fs.inputFiles(fs.predicates().hasLanguage("cobol"))).isEmpty();
+
+ assertThat(fs.languages()).containsOnly("java", "php");
+ }
+
+ @Test
+ public void input_file_returns_null_if_file_not_found() throws Exception {
+ DefaultFileSystem fs = new DefaultFileSystem();
+ assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNull();
+ assertThat(fs.inputFile(fs.predicates().hasLanguage("cobol"))).isNull();
+ }
+
+ @Test
+ public void input_file_fails_if_too_many_results() throws Exception {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("expected one element");
+
+ DefaultFileSystem fs = new DefaultFileSystem();
+ fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
+ fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
+
+ fs.inputFile(fs.predicates().all());
+ }
+
+ @Test
+ public void input_file_supports_non_indexed_predicates() throws Exception {
+ DefaultFileSystem fs = new DefaultFileSystem();
+ fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
+
+ // it would fail if more than one java file
+ assertThat(fs.inputFile(fs.predicates().hasLanguage("java"))).isNotNull();
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.io.File;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DefaultInputFileTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void test() throws Exception {
+ DefaultInputFile inputFile = new DefaultInputFile("src/Foo.php")
+ .setFile(temp.newFile("Foo.php"))
+ .setKey("ABCDE")
+ .setHash("1234")
+ .setLines(42)
+ .setLanguage("php")
+ .setStatus(InputFile.Status.ADDED)
+ .setType(InputFile.Type.TEST);
+
+ assertThat(inputFile.relativePath()).isEqualTo("src/Foo.php");
+ assertThat(new File(inputFile.relativePath())).isRelative();
+ assertThat(inputFile.absolutePath()).endsWith("Foo.php");
+ assertThat(new File(inputFile.absolutePath())).isAbsolute();
+ assertThat(inputFile.language()).isEqualTo("php");
+ assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED);
+ assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST);
+ assertThat(inputFile.lines()).isEqualTo(42);
+ assertThat(inputFile.hash()).isEqualTo("1234");
+ }
+
+ @Test
+ public void test_equals_and_hashcode() throws Exception {
+ DefaultInputFile f1 = new DefaultInputFile("src/Foo.php");
+ DefaultInputFile f1a = new DefaultInputFile("src/Foo.php");
+ DefaultInputFile f2 = new DefaultInputFile("src/Bar.php");
+
+ assertThat(f1).isEqualTo(f1);
+ assertThat(f1).isEqualTo(f1a);
+ assertThat(f1).isNotEqualTo(f2);
+ assertThat(f1.equals("foo")).isFalse();
+ assertThat(f1.equals(null)).isFalse();
+
+ assertThat(f1.hashCode()).isEqualTo(f1.hashCode());
+ assertThat(f1.hashCode()).isEqualTo(f1a.hashCode());
+ }
+
+ @Test
+ public void test_toString() throws Exception {
+ DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php");
+ assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]");
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.io.File;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class PathPatternTest {
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void match_relative_path() throws Exception {
+ PathPattern pattern = PathPattern.create("**/*Foo.java");
+ assertThat(pattern.toString()).isEqualTo("**/*Foo.java");
+
+ File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
+ InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
+ assertThat(pattern.match(inputFile)).isTrue();
+
+ // case sensitive by default
+ file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+ inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+ assertThat(pattern.match(inputFile)).isFalse();
+
+ file = new File(temp.newFolder(), "src/main/java/org/Other.java");
+ inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
+ assertThat(pattern.match(inputFile)).isFalse();
+ }
+
+ @Test
+ public void match_relative_path_and_insensitive_file_extension() throws Exception {
+ PathPattern pattern = PathPattern.create("**/*Foo.java");
+
+ File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+ InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+ assertThat(pattern.match(inputFile, false)).isTrue();
+
+ file = new File(temp.newFolder(), "src/main/java/org/Other.java");
+ inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
+ assertThat(pattern.match(inputFile, false)).isFalse();
+ }
+
+ @Test
+ public void match_absolute_path() throws Exception {
+ PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
+ assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
+
+ File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
+ InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
+ assertThat(pattern.match(inputFile)).isTrue();
+
+ // case sensitive by default
+ file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+ inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+ assertThat(pattern.match(inputFile)).isFalse();
+
+ file = new File(temp.newFolder(), "src/main/java/org/Other.java");
+ inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
+ assertThat(pattern.match(inputFile)).isFalse();
+ }
+
+ @Test
+ public void match_absolute_path_and_insensitive_file_extension() throws Exception {
+ PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
+ assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
+
+ File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+ InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+ assertThat(pattern.match(inputFile, false)).isTrue();
+
+ file = new File(temp.newFolder(), "src/main/java/org/Other.JAVA");
+ inputFile = new DefaultInputFile("src/main/java/org/Other.JAVA").setFile(file);
+ assertThat(pattern.match(inputFile, false)).isFalse();
+ }
+
+ @Test
+ public void create_array_of_patterns() throws Exception {
+ PathPattern[] patterns = PathPattern.create(new String[]{
+ "**/src/main/**Foo.java",
+ "file:**/src/main/**Bar.java"
+ });
+ assertThat(patterns).hasSize(2);
+ assertThat(patterns[0].toString()).isEqualTo("**/src/main/**Foo.java");
+ assertThat(patterns[1].toString()).isEqualTo("file:**/src/main/**Bar.java");
+ }
+}
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-java-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-batch-plugin-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-plugin-api</artifactId>
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.*;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectLink;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;
import org.sonar.core.measure.MeasurementFilters;
+import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
}
@Override
- public Measure getMeasure(Metric metric) {
+ public <G extends Serializable> Measure<G> getMeasure(Metric<G> metric) {
return index.getMeasure(project, metric);
}
}
@Override
- public Measure getMeasure(Resource resource, Metric metric) {
+ public <G extends Serializable> Measure<G> getMeasure(Resource resource, Metric<G> metric) {
return index.getMeasure(resource, metric);
}
private boolean preview;
private boolean incremental;
private int previewReadTimeoutSec;
+ private boolean sensorMode;
public AnalysisMode(BootstrapProperties bootstrapProps) {
init(bootstrapProps);
return incremental;
}
+ public boolean isSensorMode() {
+ return sensorMode;
+ }
+
private void init(BootstrapProperties bootstrapProps) {
if (bootstrapProps.properties().containsKey(CoreProperties.DRY_RUN)) {
LOG.warn(MessageFormat.format("Property {0} is deprecated. Please use {1} instead.", CoreProperties.DRY_RUN, CoreProperties.ANALYSIS_MODE));
preview = "true".equals(bootstrapProps.property(CoreProperties.DRY_RUN));
incremental = false;
+ sensorMode = false;
} else {
String mode = bootstrapProps.property(CoreProperties.ANALYSIS_MODE);
preview = CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode);
incremental = CoreProperties.ANALYSIS_MODE_INCREMENTAL.equals(mode);
+ sensorMode = CoreProperties.ANALYSIS_MODE_SENSOR.equals(mode);
}
if (incremental) {
LOG.info("Incremental mode");
} else if (preview) {
LOG.info("Preview mode");
+ } else if (sensorMode) {
+ LOG.info("Sensor mode");
}
// To stay compatible with plugins that use the old property to check mode
if (incremental || preview) {
package org.sonar.batch.bootstrap;
import com.google.common.collect.Lists;
-import org.sonar.batch.debt.DebtDecorator;
-import org.sonar.batch.debt.IssueChangelogDebtCalculator;
-import org.sonar.batch.debt.NewDebtDecorator;
import org.sonar.batch.maven.DefaultMavenPluginExecutor;
import org.sonar.batch.maven.MavenProjectBootstrapper;
import org.sonar.batch.maven.MavenProjectBuilder;
public static Collection all() {
List components = Lists.newArrayList(
// Maven
- MavenProjectBootstrapper.class, DefaultMavenPluginExecutor.class, MavenProjectConverter.class, MavenProjectBuilder.class,
-
- // Debt
- IssueChangelogDebtCalculator.class, DebtDecorator.class, NewDebtDecorator.class
- );
+ MavenProjectBootstrapper.class, DefaultMavenPluginExecutor.class, MavenProjectConverter.class, MavenProjectBuilder.class
+ );
components.addAll(CorePropertyDefinitions.all());
return components;
}
import com.google.common.collect.Lists;
import org.apache.commons.lang.ClassUtils;
-import org.sonar.api.BatchExtension;
import org.sonar.api.batch.CheckProject;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.scan.SensorWrapper;
import java.util.Collection;
import java.util.List;
*/
public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensionDictionnary {
- public BatchExtensionDictionnary(ComponentContainer componentContainer) {
+ private FileSystem fs;
+ private AnalyzerContext context;
+
+ public BatchExtensionDictionnary(ComponentContainer componentContainer, FileSystem fs, AnalyzerContext context) {
super(componentContainer);
+ this.fs = fs;
+ this.context = context;
}
public <T> Collection<T> select(Class<T> type, Project project, boolean sort, ExtensionMatcher matcher) {
private <T> List<T> getFilteredExtensions(Class<T> type, Project project, ExtensionMatcher matcher) {
List<T> result = Lists.newArrayList();
- for (BatchExtension extension : getExtensions()) {
+ for (Object extension : getExtensions()) {
+ if (type == Sensor.class && extension instanceof Analyzer) {
+ extension = new SensorWrapper((Analyzer) extension, context, fs);
+ }
if (shouldKeep(type, extension, project, matcher)) {
result.add((T) extension);
}
}
private boolean shouldKeep(Class type, Object extension, Project project, ExtensionMatcher matcher) {
- boolean keep = ClassUtils.isAssignable(extension.getClass(), type) && (matcher == null || matcher.accept(extension));
+ boolean keep = (ClassUtils.isAssignable(extension.getClass(), type)
+ || (type == Sensor.class && ClassUtils.isAssignable(extension.getClass(), Analyzer.class)))
+ && (matcher == null || matcher.accept(extension));
if (keep && project != null && ClassUtils.isAssignable(extension.getClass(), CheckProject.class)) {
keep = ((CheckProject) extension).shouldExecuteOnProject(project);
}
import org.sonar.batch.components.PastSnapshotFinderByPreviousAnalysis;
import org.sonar.batch.components.PastSnapshotFinderByPreviousVersion;
import org.sonar.batch.components.PastSnapshotFinderByVersion;
+import org.sonar.batch.debt.DebtModelProvider;
+import org.sonar.batch.rule.RulesProvider;
+import org.sonar.batch.rules.DefaultQProfileReferential;
+import org.sonar.batch.rules.QProfilesReferential;
import org.sonar.batch.settings.DefaultSettingsReferential;
import org.sonar.batch.settings.SettingsReferential;
import org.sonar.core.cluster.NullQueue;
addBootstrapComponents();
if (!sensorMode) {
addDatabaseComponents();
+ addCoreComponents();
}
- addCoreComponents();
}
private void addBootstrapComponents() {
if (getComponentByType(MetricFinder.class) == null) {
add(CacheMetricFinder.class);
}
+ if (getComponentByType(QProfilesReferential.class) == null) {
+ add(DefaultQProfileReferential.class);
+ }
}
private void addDatabaseComponents() {
PastSnapshotFinderByPreviousVersion.class,
PastMeasuresLoader.class,
PastSnapshotFinder.class,
- Durations.class);
+ Durations.class,
+ new DebtModelProvider(),
+ new RulesProvider());
}
@Override
}
}
- public void executeTask(Map<String, String> taskProperties) {
- new TaskContainer(this, taskProperties).execute();
+ public void executeTask(Map<String, String> taskProperties, Object... components) {
+ new TaskContainer(this, taskProperties, components).execute();
}
}
}
public ExtensionInstaller install(ComponentContainer container, ExtensionMatcher matcher) {
- boolean preview = analysisMode.isPreview();
// core components
for (Object o : BatchComponents.all()) {
- doInstall(container, matcher, null, preview, o);
+ doInstall(container, matcher, null, o);
}
// plugin extensions
PluginMetadata metadata = entry.getKey();
Plugin plugin = entry.getValue();
for (Object extension : plugin.getExtensions()) {
- doInstall(container, matcher, metadata, preview, extension);
+ doInstall(container, matcher, metadata, extension);
}
}
List<ExtensionProvider> providers = container.getComponentsByType(ExtensionProvider.class);
Object object = provider.provide();
if (object instanceof Iterable) {
for (Object extension : (Iterable) object) {
- doInstall(container, matcher, null, preview, extension);
+ doInstall(container, matcher, null, extension);
}
} else {
- doInstall(container, matcher, null, preview, object);
+ doInstall(container, matcher, null, object);
}
}
return this;
}
- private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginMetadata metadata, boolean dryRun, Object extension) {
+ private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginMetadata metadata, Object extension) {
if (ExtensionUtils.supportsEnvironment(extension, env)
- && (!dryRun || ExtensionUtils.supportsPreview(extension))
+ && (!analysisMode.isPreview() || ExtensionUtils.supportsPreview(extension))
&& matcher.accept(extension)) {
container.addExtension(metadata, extension);
} else {
public class TaskContainer extends ComponentContainer {
private final Map<String, String> taskProperties;
+ private final Object[] components;
- public TaskContainer(ComponentContainer parent, Map<String, String> taskProperties) {
+ public TaskContainer(ComponentContainer parent, Map<String, String> taskProperties, Object... components) {
super(parent);
this.taskProperties = taskProperties;
+ this.components = components;
}
@Override
installCoreTasks();
installTaskExtensions();
installComponentsUsingTaskExtensions();
+ for (Object component : components) {
+ add(component);
+ }
}
void installCoreTasks() {
/**
* @since 4.4
*/
- public Batch executeTask(Map<String, String> taskProperties) {
+ public Batch executeTask(Map<String, String> taskProperties, Object... components) {
if (!started) {
throw new IllegalStateException("Batch is not started. Unable to execute task.");
}
- bootstrapContainer.executeTask(taskProperties);
+ bootstrapContainer.executeTask(taskProperties, components);
return this;
}
}
@Override
- public Measure getMeasure(Resource resource, Metric metric) {
+ public Measure getMeasure(Resource resource, org.sonar.batch.api.measures.Metric<?> metric) {
return getMeasures(resource, MeasuresFilters.metric(metric));
}
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.resources.Directory;
Map<String, InputFile> deprecatedTestKeyMapper = new HashMap<String, InputFile>();
Map<String, String> deprecatedDirectoryKeyMapper = new HashMap<String, String>();
for (InputFile inputFile : inputFiles) {
- String deprecatedKey = ((DefaultInputFile) inputFile).deprecatedKey();
+ String deprecatedKey = ((DeprecatedDefaultInputFile) inputFile).deprecatedKey();
if (deprecatedKey != null) {
if (InputFile.Type.TEST == inputFile.type() && !deprecatedTestKeyMapper.containsKey(deprecatedKey)) {
deprecatedTestKeyMapper.put(deprecatedKey, inputFile);
boolean isTest = Qualifiers.UNIT_TEST_FILE.equals(resourceModel.getQualifier());
InputFile matchedFile = findInputFile(deprecatedFileKeyMapper, deprecatedTestKeyMapper, oldEffectiveKey, isTest);
if (matchedFile != null) {
- String newEffectiveKey = ((DefaultInputFile) matchedFile).key();
+ String newEffectiveKey = ((DeprecatedDefaultInputFile) matchedFile).key();
// Now compute migration of the parent dir
String oldKey = StringUtils.substringAfterLast(oldEffectiveKey, ":");
Resource sonarFile;
this(deprecatedFilters, deprecatedViolations, new org.sonar.api.issue.IssueFilter[0]);
}
+ /**
+ * Used by scan2
+ */
+ public IssueFilters(org.sonar.api.issue.IssueFilter[] exclusionFilters, IssueFilter[] filters) {
+ this(null, null, exclusionFilters, filters);
+ }
+
+ public IssueFilters(org.sonar.api.issue.IssueFilter[] exclusionFilters) {
+ this(null, null, exclusionFilters, new IssueFilter[0]);
+ }
+
+ public IssueFilters(IssueFilter[] filters) {
+ this(null, null, new org.sonar.api.issue.IssueFilter[0], filters);
+ }
+
+ public IssueFilters() {
+ this(null, null, new org.sonar.api.issue.IssueFilter[0], new IssueFilter[0]);
+ }
+
public boolean accept(DefaultIssue issue, @Nullable Violation violation) {
- if(new DefaultIssueFilterChain(filters).accept(issue)) {
+ if (new DefaultIssueFilterChain(filters).accept(issue)) {
// Apply deprecated rules only if filter chain accepts the current issue
for (org.sonar.api.issue.IssueFilter filter : exclusionFilters) {
if (!filter.accept(issue)) {
return false;
}
}
- if (!deprecatedFilters.isEmpty()) {
+ if (deprecatedFilters != null && !deprecatedFilters.isEmpty()) {
Violation v = violation != null ? violation : deprecatedViolations.toViolation(issue);
return !deprecatedFilters.isIgnored(v);
}
private final Project project;
private final IssueFilters filters;
- public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, Project project, IssueFilters filters) {
+ public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, @Nullable Project project, IssueFilters filters) {
this.activeRules = activeRules;
this.rules = rules;
this.cache = cache;
this.filters = filters;
}
+ /**
+ * Used by scan2
+ */
+ public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, IssueFilters filters) {
+ this(activeRules, rules, cache, null, filters);
+ }
+
public boolean initAndAddIssue(DefaultIssue issue) {
return initAndAddIssue(issue, null);
}
private DefaultIssue newIssue(Violation violation) {
return (DefaultIssue) new DefaultIssueBuilder()
.componentKey(violation.getResource().getEffectiveKey())
+ // Project can be null but Violation not used by scan2
.projectKey(project.getRoot().getEffectiveKey())
.ruleKey(RuleKey.of(violation.getRule().getRepositoryKey(), violation.getRule().getKey()))
.effortToFix(violation.getCost())
if (Strings.isNullOrEmpty(issue.message())) {
issue.setMessage(rule.name());
}
- issue.setCreationDate(project.getAnalysisDate());
- issue.setUpdateDate(project.getAnalysisDate());
+ if (project != null) {
+ issue.setCreationDate(project.getAnalysisDate());
+ issue.setUpdateDate(project.getAnalysisDate());
+ }
if (issue.severity() == null) {
issue.setSeverity(activeRule.severity());
}
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
for (InputFile inputFile : fileSystem.inputFiles(fileSystem.predicates().all())) {
try {
- String componentEffectiveKey = ((DefaultInputFile) inputFile).key();
+ String componentEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
if (componentEffectiveKey != null) {
String path = inputFile.relativePath();
inclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey);
@DependsUpon
public List<Metric> dependsUponMetrics() {
- return ImmutableList.of(CoreMetrics.LINES);
+ return ImmutableList.<Metric>of(CoreMetrics.LINES);
}
@DependedUpon
public List<Metric> generatesMetrics() {
return ImmutableList.of(
CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION
- );
+ );
}
public void decorate(Resource resource, DecoratorContext context) {
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.languages;
+
+import org.sonar.api.resources.Languages;
+import org.sonar.batch.api.languages.Language;
+
+import javax.annotation.CheckForNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Languages referential using {@link Languages}
+ * @since 4.4
+ */
+public class DeprecatedLanguagesReferential implements LanguagesReferential {
+
+ private Languages languages;
+
+ public DeprecatedLanguagesReferential(Languages languages) {
+ this.languages = languages;
+ }
+
+ /**
+ * Get language.
+ */
+ @CheckForNull
+ public Language get(String languageKey) {
+ org.sonar.api.resources.Language language = languages.get(languageKey);
+ return language != null ? new Language(language.getKey(), language.getName(), language.getFileSuffixes()) : null;
+ }
+
+ /**
+ * Get list of all supported languages.
+ */
+ public Collection<Language> all() {
+ org.sonar.api.resources.Language[] all = languages.all();
+ Collection<Language> result = new ArrayList<Language>(all.length);
+ for (org.sonar.api.resources.Language language : all) {
+ result.add(new Language(language.getKey(), language.getName(), language.getFileSuffixes()));
+ }
+ return result;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.languages;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.languages.Language;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Collection;
+
+/**
+ * Languages referential
+ * @since 4.4
+ */
+public interface LanguagesReferential extends BatchComponent {
+
+ /**
+ * Get language.
+ */
+ @CheckForNull
+ Language get(String languageKey);
+
+ /**
+ * Get list of all supported languages.
+ */
+ Collection<Language> all();
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.languages;
\ No newline at end of file
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.batch.phases;
-
-import com.google.common.collect.Lists;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.resources.Project;
-import org.sonar.batch.events.EventBus;
-import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
-import org.sonar.batch.rule.QProfileVerifier;
-import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
-import org.sonar.batch.scan.filesystem.FileSystemLogger;
-import org.sonar.batch.scan.maven.MavenPluginsConfigurator;
-
-import java.util.Collection;
-
-public final class Phase2Executor {
-
- public static final Logger LOGGER = LoggerFactory.getLogger(Phase2Executor.class);
-
- private final EventBus eventBus;
- private final Phases phases;
- private final MavenPluginsConfigurator mavenPluginsConfigurator;
- private final InitializersExecutor initializersExecutor;
- private final SensorsExecutor sensorsExecutor;
- private final SensorContext sensorContext;
- private final ProjectInitializer pi;
- private final FileSystemLogger fsLogger;
- private final DefaultModuleFileSystem fs;
- private final QProfileVerifier profileVerifier;
- private final IssueExclusionsLoader issueExclusionsLoader;
-
- public Phase2Executor(Phases phases,
- MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
- SensorsExecutor sensorsExecutor,
- SensorContext sensorContext,
- EventBus eventBus, ProjectInitializer pi,
- FileSystemLogger fsLogger, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
- IssueExclusionsLoader issueExclusionsLoader) {
- this.phases = phases;
- this.mavenPluginsConfigurator = mavenPluginsConfigurator;
- this.initializersExecutor = initializersExecutor;
- this.sensorsExecutor = sensorsExecutor;
- this.sensorContext = sensorContext;
- this.eventBus = eventBus;
- this.pi = pi;
- this.fsLogger = fsLogger;
- this.fs = fs;
- this.profileVerifier = profileVerifier;
- this.issueExclusionsLoader = issueExclusionsLoader;
- }
-
- public static Collection<Class> getPhaseClasses() {
- return Lists.<Class>newArrayList(SensorsExecutor.class, InitializersExecutor.class, ProjectInitializer.class);
- }
-
- /**
- * Executed on each module
- */
- public void execute(Project module) {
- pi.execute(module);
-
- eventBus.fireEvent(new ProjectAnalysisEvent(module, true));
-
- executeMavenPhase(module);
-
- executeInitializersPhase();
-
- // Index and lock the filesystem
- fs.index();
-
- // Log detected languages and their profiles after FS is indexed and languages detected
- profileVerifier.execute();
-
- // Initialize issue exclusions
- issueExclusionsLoader.execute();
-
- sensorsExecutor.execute(sensorContext);
-
- eventBus.fireEvent(new ProjectAnalysisEvent(module, false));
- }
-
- private void executeInitializersPhase() {
- if (phases.isEnabled(Phases.Phase.INIT)) {
- initializersExecutor.execute();
- fsLogger.log();
- }
- }
-
- private void executeMavenPhase(Project module) {
- if (phases.isEnabled(Phases.Phase.MAVEN)) {
- eventBus.fireEvent(new MavenPhaseEvent(true));
- mavenPluginsConfigurator.execute(module);
- eventBus.fireEvent(new MavenPhaseEvent(false));
- }
- }
-}
*/
package org.sonar.batch.phases;
-import org.sonar.batch.bootstrap.ExtensionMatcher;
-
import org.apache.commons.lang.ClassUtils;
import org.sonar.api.BatchExtension;
import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.batch.Sensor;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.bootstrap.ExtensionMatcher;
/**
* Allow to filter sensors that will be executed.
@Override
public final boolean accept(Object extension) {
- return ClassUtils.isAssignable(extension.getClass(), Sensor.class) && acceptSensor((Sensor) extension);
+ return ClassUtils.isAssignable(extension.getClass(), Sensor.class)
+ && acceptSensor((Sensor) extension) || ClassUtils.isAssignable(extension.getClass(), Analyzer.class);
}
public abstract boolean acceptSensor(Sensor sensor);
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RuleParam;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
import org.sonar.core.qualityprofile.db.ActiveRuleDao;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
private ActiveRules load(ModuleQProfiles qProfiles, ActiveRuleDao dao, RuleFinder ruleFinder) {
ActiveRulesBuilder builder = new ActiveRulesBuilder();
- for (ModuleQProfiles.QProfile qProfile : qProfiles.findAll()) {
+ for (QProfile qProfile : qProfiles.findAll()) {
+ QProfileWithId qProfileWithId = (QProfileWithId) qProfile;
ListMultimap<Integer, ActiveRuleParamDto> paramDtosByActiveRuleId = ArrayListMultimap.create();
- for (ActiveRuleParamDto dto : dao.selectParamsByProfileId(qProfile.id())) {
+ for (ActiveRuleParamDto dto : dao.selectParamsByProfileId(qProfileWithId.id())) {
paramDtosByActiveRuleId.put(dto.getActiveRuleId(), dto);
}
- for (ActiveRuleDto activeDto : dao.selectByProfileId(qProfile.id())) {
+ for (ActiveRuleDto activeDto : dao.selectByProfileId(qProfileWithId.id())) {
Rule rule = ruleFinder.findById(activeDto.getRulId());
if (rule != null) {
NewActiveRule newActiveRule = builder.activate(rule.ruleKey());
import org.apache.commons.lang.StringUtils;
import org.sonar.api.BatchComponent;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
import org.sonar.api.utils.MessageException;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.batch.api.languages.Language;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.languages.LanguagesReferential;
+import org.sonar.batch.rules.QProfilesReferential;
import javax.annotation.CheckForNull;
public static final String SONAR_PROFILE_PROP = "sonar.profile";
- public static class QProfile {
- private final String name, language;
- private final Integer version;
- private final int id;
-
- public QProfile(QualityProfileDto dto) {
- this.id = dto.getId();
- this.name = dto.getName();
- this.language = dto.getLanguage();
- this.version = dto.getVersion();
- }
-
- QProfile(int id, String name, String language, Integer version) {
- this.id = id;
- this.name = name;
- this.language = language;
- this.version = version;
- }
-
- public int id() {
- return id;
- }
-
- public String name() {
- return name;
- }
-
- public String language() {
- return language;
- }
-
- public Integer version() {
- return version;
- }
- }
-
private final Map<String, QProfile> byLanguage;
- public ModuleQProfiles(Settings settings, Languages languages, QualityProfileDao dao) {
+ public ModuleQProfiles(Settings settings, LanguagesReferential languages, QProfilesReferential qProfileRef) {
ImmutableMap.Builder<String, QProfile> builder = ImmutableMap.builder();
String defaultName = settings.getString(SONAR_PROFILE_PROP);
for (Language language : languages.all()) {
QProfile profile = null;
if (StringUtils.isNotBlank(defaultName)) {
- profile = loadDefaultQProfile(dao, defaultName, language.getKey());
+ profile = loadDefaultQProfile(qProfileRef, defaultName, language.key());
}
if (profile == null) {
- profile = loadQProfile(dao, settings, language.getKey());
+ profile = loadQProfile(qProfileRef, settings, language.key());
}
if (profile != null) {
builder.put(profile.language(), profile);
}
@CheckForNull
- private QProfile loadQProfile(QualityProfileDao dao, Settings settings, String language) {
+ private QProfile loadQProfile(QProfilesReferential qProfileRef, Settings settings, String language) {
String profileName = settings.getString("sonar.profile." + language);
if (profileName != null) {
- QualityProfileDto dto = dao.selectByNameAndLanguage(profileName, language);
+ QProfile dto = qProfileRef.get(language, profileName);
if (dto == null) {
throw MessageException.of(String.format("Quality profile not found : '%s' on language '%s'", profileName, language));
}
- return new QProfile(dto);
+ return dto;
}
return null;
}
@CheckForNull
- private QProfile loadDefaultQProfile(QualityProfileDao dao, String profileName, String language) {
- QualityProfileDto dto = dao.selectByNameAndLanguage(profileName, language);
- if (dto != null) {
- return new QProfile(dto);
- }
- return null;
+ private QProfile loadDefaultQProfile(QProfilesReferential qProfileRef, String profileName, String language) {
+ return qProfileRef.get(language, profileName);
}
public Collection<QProfile> findAll() {
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.ResourceUtils;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
import org.sonar.core.qualityprofile.db.QualityProfileDto;
} else {
pastProfileVersion = pastProfileVersionMeasure.getIntValue();
}
- pastProfiles = UsedQProfiles.fromProfiles(new ModuleQProfiles.QProfile(pastProfileId, pastProfileName, pastProfileLanguage, pastProfileVersion));
+ pastProfiles = UsedQProfiles.fromProfiles(new QProfileWithId(pastProfileId, pastProfileName, pastProfileLanguage, pastProfileVersion));
}
// Now create appropriate events
- Map<Integer, QProfile> pastProfilesById = Maps.newHashMap(pastProfiles.profilesById());
- for (QProfile profile : currentProfiles.profilesById().values()) {
+ Map<Integer, QProfileWithId> pastProfilesById = Maps.newHashMap(pastProfiles.profilesById());
+ for (QProfileWithId profile : currentProfiles.profilesById().values()) {
if (pastProfilesById.containsKey(profile.id())) {
- QProfile pastProfile = pastProfilesById.get(profile.id());
+ QProfileWithId pastProfile = pastProfilesById.get(profile.id());
if (pastProfile.version() < profile.version()) {
// New version of the same QP
usedProfile(context, profile);
usedProfile(context, profile);
}
}
- for (QProfile profile : pastProfilesById.values()) {
+ for (QProfileWithId profile : pastProfilesById.values()) {
// Following profiles are no more used
stopUsedProfile(context, profile);
}
}
- private void stopUsedProfile(DecoratorContext context, QProfile profile) {
+ private void stopUsedProfile(DecoratorContext context, QProfileWithId profile) {
Language language = languages.get(profile.language());
String languageName = language != null ? language.getName() : profile.language();
context.createEvent("Stop using " + format(profile) + " (" + languageName + ")", format(profile) + " no more used for " + languageName, Event.CATEGORY_PROFILE, null);
}
- private void usedProfile(DecoratorContext context, QProfile profile) {
+ private void usedProfile(DecoratorContext context, QProfileWithId profile) {
Language language = languages.get(profile.language());
String languageName = language != null ? language.getName() : profile.language();
context.createEvent("Use " + format(profile) + " (" + languageName + ")", format(profile) + " used for " + languageName, Event.CATEGORY_PROFILE, null);
}
- private String format(QProfile profile) {
+ private String format(QProfileWithId profile) {
return profile.name() + " version " + profile.version();
}
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.resources.Project;
+import org.sonar.batch.rules.QProfileWithId;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
import java.util.List;
}
public void analyse(Project project, SensorContext context) {
- List<ModuleQProfiles.QProfile> profiles = Lists.newArrayList();
+ List<QProfileWithId> profiles = Lists.newArrayList();
for (String language : fs.languages()) {
- ModuleQProfiles.QProfile qProfile = moduleQProfiles.findByLanguage(language);
+ QProfileWithId qProfile = (QProfileWithId) moduleQProfiles.findByLanguage(language);
if (qProfile != null) {
dao.updateUsedColumn(qProfile.id(), true);
profiles.add(qProfile);
// For backward compatibility
if (profiles.size() == 1) {
- ModuleQProfiles.QProfile qProfile = profiles.get(0);
+ QProfileWithId qProfile = profiles.get(0);
Measure measure = new Measure(CoreMetrics.PROFILE, qProfile.name()).setValue((double) qProfile.id());
Measure measureVersion = new Measure(CoreMetrics.PROFILE_VERSION, qProfile.version().doubleValue());
context.saveMeasure(measure);
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.api.rules.QProfile;
public class QProfileVerifier implements BatchComponent {
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RulePriority;
+import org.sonar.batch.api.rules.QProfile;
import java.util.Collection;
import java.util.Map;
}
private RulesProfile loadSingleLanguageProfile(ModuleQProfiles qProfiles, ActiveRules activeRules,
- RuleFinder ruleFinder, String language) {
- ModuleQProfiles.QProfile qProfile = qProfiles.findByLanguage(language);
+ RuleFinder ruleFinder, String language) {
+ QProfile qProfile = qProfiles.findByLanguage(language);
if (qProfile != null) {
return new RulesProfileWrapper(select(qProfile, activeRules, ruleFinder));
}
private RulesProfile loadProfiles(ModuleQProfiles qProfiles, ActiveRules activeRules, RuleFinder ruleFinder) {
Collection<RulesProfile> dtos = Lists.newArrayList();
- for (ModuleQProfiles.QProfile qProfile : qProfiles.findAll()) {
+ for (QProfile qProfile : qProfiles.findAll()) {
dtos.add(select(qProfile, activeRules, ruleFinder));
}
return new RulesProfileWrapper(dtos);
}
- private RulesProfile select(ModuleQProfiles.QProfile qProfile, ActiveRules activeRules, RuleFinder ruleFinder) {
+ private RulesProfile select(QProfile qProfile, ActiveRules activeRules, RuleFinder ruleFinder) {
RulesProfile deprecatedProfile = new RulesProfile();
deprecatedProfile.setVersion(qProfile.version());
deprecatedProfile.setName(qProfile.name());
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
import javax.annotation.concurrent.Immutable;
@Immutable
public class UsedQProfiles {
- private Map<Integer, ModuleQProfiles.QProfile> profilesById = Maps.newLinkedHashMap();
+ private Map<Integer, QProfileWithId> profilesById = Maps.newLinkedHashMap();
private UsedQProfiles() {
}
- public static final UsedQProfiles fromProfiles(Iterable<QProfile> profiles) {
+ public static final UsedQProfiles fromProfiles(Iterable<QProfileWithId> profiles) {
UsedQProfiles result = new UsedQProfiles();
- for (QProfile qProfile : profiles) {
+ for (QProfileWithId qProfile : profiles) {
result.add(qProfile);
}
return result;
return new UsedQProfiles();
}
- public static final UsedQProfiles fromProfiles(QProfile... profiles) {
+ public static final UsedQProfiles fromProfiles(QProfileWithId... profiles) {
return fromProfiles(Arrays.asList(profiles));
}
JsonArray root = new JsonParser().parse(json).getAsJsonArray();
for (JsonElement elt : root) {
JsonObject profile = elt.getAsJsonObject();
- result.add(new QProfile(profile.get("id").getAsInt(), profile.get("name").getAsString(), profile.get("language").getAsString(), profile.get("version").getAsInt()));
+ result.add(new QProfileWithId(profile.get("id").getAsInt(), profile.get("name").getAsString(), profile.get("language").getAsString(), profile.get("version").getAsInt()));
}
return result;
}
StringWriter json = new StringWriter();
JsonWriter writer = JsonWriter.of(json);
writer.beginArray();
- for (ModuleQProfiles.QProfile qProfile : profilesById.values()) {
+ for (QProfileWithId qProfile : profilesById.values()) {
writer.beginObject()
.prop("id", qProfile.id())
.prop("name", qProfile.name())
return empty().mergeInPlace(this).mergeInPlace(other);
}
- private void add(ModuleQProfiles.QProfile profile) {
- QProfile alreadyAdded = profilesById.get(profile.id());
+ private void add(QProfileWithId profile) {
+ QProfileWithId alreadyAdded = profilesById.get(profile.id());
if (alreadyAdded == null
// Keep only latest version
|| profile.version() > alreadyAdded.version()) {
}
}
- private UsedQProfiles addAll(Iterable<QProfile> profiles) {
- for (QProfile profile : profiles) {
+ private UsedQProfiles addAll(Iterable<QProfileWithId> profiles) {
+ for (QProfileWithId profile : profiles) {
this.add(profile);
}
return this;
return this;
}
- public Map<Integer, ModuleQProfiles.QProfile> profilesById() {
+ public Map<Integer, QProfileWithId> profilesById() {
return ImmutableMap.copyOf(profilesById);
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.rules;
+
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+
+/**
+ * @since 4.4
+ */
+public class DefaultQProfileReferential implements QProfilesReferential {
+
+ private QualityProfileDao qualityProfileDao;
+
+ public DefaultQProfileReferential(QualityProfileDao qualityProfileDao) {
+ this.qualityProfileDao = qualityProfileDao;
+ }
+
+ @Override
+ public QProfile get(String language, String name) {
+ QualityProfileDto dto = qualityProfileDao.selectByNameAndLanguage(name, language);
+ if (dto == null) {
+ return null;
+ }
+ return new QProfileWithId(dto.getId(), dto.getName(), dto.getLanguage(), dto.getVersion());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.rules;
+
+import org.sonar.batch.api.rules.QProfile;
+
+public class QProfileWithId extends QProfile {
+ private final int id;
+
+ public QProfileWithId(int id, String name, String language, Integer version) {
+ super(name, language, version);
+ this.id = id;
+ }
+
+ public int id() {
+ return id;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.rules;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.rules.QProfile;
+
+import javax.annotation.CheckForNull;
+
+/**
+ * Quality profiles referential
+ * @since 4.4
+ */
+public interface QProfilesReferential extends BatchComponent {
+
+ /**
+ * Get quality profile
+ */
+ @CheckForNull
+ QProfile get(String language, String name);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.rules;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan;
+
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.issue.Issuable;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.analyzer.issue.AnalyzerIssue;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.api.measures.Metric;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+public class AnalyzerContextAdaptor implements AnalyzerContext {
+
+ private SensorContext sensorContext;
+ private MetricFinder metricFinder;
+ private Project project;
+ private ResourcePerspectives perspectives;
+
+ public AnalyzerContextAdaptor(SensorContext sensorContext, MetricFinder metricFinder, Project project, ResourcePerspectives perspectives) {
+ this.sensorContext = sensorContext;
+ this.metricFinder = metricFinder;
+ this.project = project;
+ this.perspectives = perspectives;
+ }
+
+ @Override
+ public AnalyzerMeasure<?> getMeasure(String metricKey) {
+ Metric<?> m = metricFinder.findByKey(metricKey);
+ if (m == null) {
+ throw new IllegalStateException("Unknow metric with key: " + metricKey);
+ }
+ return getMeasure(m);
+ }
+
+ @Override
+ public <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric) {
+ org.sonar.api.measures.Metric<G> m = metricFinder.findByKey(metric.key());
+ Measure<G> measure = sensorContext.getMeasure(m);
+ if (measure == null) {
+ return null;
+ }
+ return AnalyzerMeasure.<G>builder()
+ .onProject()
+ .forMetric(metric)
+ .withValue(measure.value())
+ .build();
+ }
+
+ @Override
+ public AnalyzerMeasure<?> getMeasure(InputFile file, String metricKey) {
+ Metric<?> m = metricFinder.findByKey(metricKey);
+ if (m == null) {
+ throw new IllegalStateException("Unknow metric with key: " + metricKey);
+ }
+ return getMeasure(file, m);
+ }
+
+ @Override
+ public <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric) {
+ File fileRes = File.fromIOFile(file.file(), project);
+ org.sonar.api.measures.Metric<G> m = metricFinder.findByKey(metric.key());
+ Measure<G> measure = sensorContext.getMeasure(fileRes, m);
+ if (measure == null) {
+ return null;
+ }
+ return AnalyzerMeasure.<G>builder()
+ .onFile(file)
+ .forMetric(metric)
+ .withValue(measure.value())
+ .build();
+ }
+
+ @Override
+ public void addMeasure(AnalyzerMeasure<?> measure) {
+ org.sonar.api.measures.Metric<?> m = metricFinder.findByKey(measure.metricKey());
+
+ Measure measureToSave = new Measure(m);
+ switch (m.getType()) {
+ case BOOL:
+ measureToSave.setValue(Boolean.TRUE.equals(measure.value()) ? 1.0 : 0.0);
+ break;
+ case INT:
+ case MILLISEC:
+ measureToSave.setValue(Double.valueOf(((Integer) measure.value())));
+ break;
+ case FLOAT:
+ case PERCENT:
+ case RATING:
+ measureToSave.setValue(((Double) measure.value()));
+ break;
+ case STRING:
+ case LEVEL:
+ case DATA:
+ case DISTRIB:
+ measureToSave.setData(((String) measure.value()));
+ break;
+ case WORK_DUR:
+ measureToSave.setValue(Double.valueOf(((Long) measure.value())));
+ break;
+ default:
+ if (m.isNumericType()) {
+ measureToSave.setValue(((Double) measure.value()));
+ } else if (m.isDataType()) {
+ measureToSave.setData(((String) measure.value()));
+ } else {
+ throw new UnsupportedOperationException("Unsupported type :" + m.getType());
+ }
+ }
+ if (measure.inputFile() != null) {
+ File fileRes = File.fromIOFile(measure.inputFile().file(), project);
+ sensorContext.saveMeasure(fileRes, measureToSave);
+ } else {
+ sensorContext.saveMeasure(measureToSave);
+ }
+ }
+
+ @Override
+ public void addIssue(AnalyzerIssue issue) {
+ Resource r;
+ if (issue.inputFile() != null) {
+ r = File.fromIOFile(issue.inputFile().file(), project);
+ } else {
+ r = project;
+ }
+ Issuable issuable = perspectives.as(Issuable.class, r);
+ issuable.addIssue(issuable.newIssueBuilder()
+ .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
+ .effortToFix(issue.effortToFix())
+ .line(issue.line())
+ .message(issue.message())
+ .build());
+ }
+
+ @Override
+ public void addIssues(Collection<AnalyzerIssue> issues) {
+ for (AnalyzerIssue analyzerIssue : issues) {
+ addIssue(analyzerIssue);
+ }
+ }
+
+}
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.api.languages.Language;
+import org.sonar.batch.languages.LanguagesReferential;
/**
* Verifies that the property sonar.language is valid
private static final Logger LOG = LoggerFactory.getLogger(LanguageVerifier.class);
private final Settings settings;
- private final Languages languages;
+ private final LanguagesReferential languages;
private final DefaultFileSystem fs;
- public LanguageVerifier(Settings settings, Languages languages, DefaultFileSystem fs) {
+ public LanguageVerifier(Settings settings, LanguagesReferential languages, DefaultFileSystem fs) {
this.settings = settings;
this.languages = languages;
this.fs = fs;
}
-
@Override
public void start() {
if (settings.hasKey(CoreProperties.PROJECT_LANGUAGE_PROPERTY)) {
import org.sonar.batch.bootstrap.ExtensionMatcher;
import org.sonar.batch.bootstrap.ExtensionUtils;
import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.debt.DebtDecorator;
+import org.sonar.batch.debt.IssueChangelogDebtCalculator;
+import org.sonar.batch.debt.NewDebtDecorator;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.ResourcePersister;
TimeMachineConfiguration.class,
DefaultSensorContext.class,
+ AnalyzerContextAdaptor.class,
BatchExtensionDictionnary.class,
DefaultTimeMachine.class,
ViolationFilters.class,
// language
LanguageDistributionDecorator.class,
+ // Debt
+ IssueChangelogDebtCalculator.class,
+ DebtDecorator.class,
+ NewDebtDecorator.class,
+
ScanPerspectives.class);
}
// Example : C# plugin adds sub-projects at runtime, even if they are not defined in root pom.
return !ExtensionUtils.isMavenExtensionOnly(extension) || module.getPom() != null;
}
- return false;
+ return ExtensionUtils.isType(extension, org.sonar.batch.api.BatchComponent.class)
+ && ExtensionUtils.isInstantiationStrategy(extension, org.sonar.batch.api.InstantiationStrategy.PER_PROJECT);
}
});
}
import org.sonar.batch.bootstrap.ExtensionUtils;
import org.sonar.batch.bootstrap.MetricProvider;
import org.sonar.batch.components.PeriodsDefinition;
-import org.sonar.batch.debt.DebtModelProvider;
import org.sonar.batch.debt.IssueChangelogDebtCalculator;
import org.sonar.batch.index.Caches;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.issue.IssueCache;
import org.sonar.batch.issue.IssuePersister;
import org.sonar.batch.issue.ScanIssueStorage;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
import org.sonar.batch.phases.GraphPersister;
import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
-import org.sonar.batch.rule.RulesProvider;
import org.sonar.batch.scan.filesystem.InputFileCache;
import org.sonar.batch.scan.maven.FakeMavenPluginExecutor;
import org.sonar.batch.scan.maven.MavenPluginExecutor;
}
private void projectBootstrap() {
- // Old versions of bootstrappers used to pass project reactor as an extension
- // so check if it is already present in parent container
- ProjectReactor reactor = getComponentByType(ProjectReactor.class);
+ ProjectReactor reactor;
+ // OK, not present, so look for a custom ProjectBootstrapper
+ ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
+ Settings settings = getComponentByType(Settings.class);
+ if (bootstrapper == null
+ // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
+ || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
+ // Use default SonarRunner project bootstrapper
+ ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
+ reactor = builder.execute();
+ } else {
+ reactor = bootstrapper.bootstrap();
+ }
if (reactor == null) {
- // OK, not present, so look for a custom ProjectBootstrapper
- ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
- Settings settings = getComponentByType(Settings.class);
- if (bootstrapper == null
- // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
- || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
- // Use default SonarRunner project bootstrapper
- ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
- reactor = builder.execute();
- } else {
- reactor = bootstrapper.bootstrap();
- }
- if (reactor == null) {
- throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
- }
- add(reactor);
+ throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
}
+ add(reactor);
}
private void addBatchComponents() {
// lang
Languages.class,
+ DeprecatedLanguagesReferential.class,
HighlightableBuilder.class,
SymbolizableBuilder.class,
// technical debt
DefaultTechnicalDebtModel.class,
- new DebtModelProvider(),
-
- // rules
- new RulesProvider(),
// Differential periods
PeriodsDefinition.class,
import org.sonar.api.task.Task;
import org.sonar.api.task.TaskDefinition;
import org.sonar.batch.DefaultProjectTree;
+import org.sonar.batch.bootstrap.BootstrapProperties;
import org.sonar.batch.bootstrap.TaskContainer;
import org.sonar.batch.phases.Phases;
+import org.sonar.batch.scan2.ProjectScanContainer;
public class ScanTask implements Task {
public static final TaskDefinition DEFINITION = TaskDefinition.builder()
}
public void execute() {
- scan(new ProjectScanContainer(taskContainer));
+ boolean sensorMode = CoreProperties.ANALYSIS_MODE_SENSOR.equals(taskContainer.getComponentByType(BootstrapProperties.class).property(CoreProperties.ANALYSIS_MODE));
+ if (sensorMode) {
+ new ProjectScanContainer(taskContainer).execute();
+ } else {
+ scan(new org.sonar.batch.scan.ProjectScanContainer(taskContainer));
+ }
}
// Add components specific to project scan (views will use different ones)
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan;
+
+import org.sonar.api.batch.DependedUpon;
+import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.resources.Project;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.measures.Metric;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SensorWrapper implements Sensor {
+
+ private Analyzer analyzer;
+ private AnalyzerContext adaptor;
+ private FileSystem fs;
+
+ public SensorWrapper(Analyzer analyzer, AnalyzerContext adaptor, FileSystem fs) {
+ this.analyzer = analyzer;
+ this.adaptor = adaptor;
+ this.fs = fs;
+ }
+
+ @DependedUpon
+ public List<Metric<?>> provides() {
+ return Arrays.asList(analyzer.describe().provides());
+ }
+
+ @DependsUpon
+ public List<Metric<?>> depends() {
+ return Arrays.asList(analyzer.describe().dependsOn());
+ }
+
+ @Override
+ public boolean shouldExecuteOnProject(Project project) {
+ if (!analyzer.describe().languages().isEmpty()) {
+ if (project.getLanguageKey() != null && !analyzer.describe().languages().contains(project.getLanguageKey())) {
+ return false;
+ }
+ boolean hasFile = false;
+ for (String languageKey : analyzer.describe().languages()) {
+ hasFile |= fs.hasFiles(fs.predicates().hasLanguage(languageKey));
+ }
+ if (!hasFile) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void analyse(Project module, SensorContext context) {
+ analyzer.analyse(adaptor);
+ }
+}
import org.apache.commons.io.FilenameUtils;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
/**
* Additional {@link org.sonar.api.batch.fs.FilePredicate}s that are
@Override
public boolean apply(InputFile f) {
- return key.equals(((DefaultInputFile) f).key());
+ return key.equals(((DeprecatedDefaultInputFile) f).key());
}
}
@Override
public boolean apply(InputFile f) {
- return key.equals(((DefaultInputFile) f).deprecatedKey());
+ return key.equals(((DeprecatedDefaultInputFile) f).deprecatedKey());
}
}
@Override
public boolean apply(InputFile f) {
- return path.equals(((DefaultInputFile) f).pathRelativeToSourceDir());
+ return path.equals(((DeprecatedDefaultInputFile) f).pathRelativeToSourceDir());
}
}
@Override
public boolean apply(InputFile f) {
- return path.equals(((DefaultInputFile) f).sourceDirAbsolutePath());
+ return path.equals(((DeprecatedDefaultInputFile) f).sourceDirAbsolutePath());
}
}
}
import org.sonar.api.batch.SonarIndex;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Languages;
for (InputFile inputFile : fs.inputFiles(fs.predicates().all())) {
String languageKey = inputFile.language();
boolean unitTest = InputFile.Type.TEST == inputFile.type();
- String pathFromSourceDir = ((DefaultInputFile) inputFile).pathRelativeToSourceDir();
+ String pathFromSourceDir = ((DeprecatedDefaultInputFile) inputFile).pathRelativeToSourceDir();
if (pathFromSourceDir == null) {
pathFromSourceDir = inputFile.relativePath();
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileQuery;
import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.MessageException;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
private ComponentIndexer componentIndexer;
private boolean initialized;
- public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, Project module, Settings settings, FileIndexer indexer, ModuleFileSystemInitializer initializer,
+ /**
+ * Used by scan2
+ */
+ public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, ProjectDefinition def, Settings settings, FileIndexer indexer, ModuleFileSystemInitializer initializer) {
+ this(moduleInputFileCache, def.getKey(), settings, indexer, initializer, null);
+ }
+
+ public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, ProjectDefinition def, Project project, Settings settings, FileIndexer indexer,
+ ModuleFileSystemInitializer initializer,
ComponentIndexer componentIndexer) {
+ this(moduleInputFileCache, project.getKey(), settings, indexer, initializer, componentIndexer);
+ }
+
+ private DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, String moduleKey, Settings settings, FileIndexer indexer, ModuleFileSystemInitializer initializer,
+ @Nullable ComponentIndexer componentIndexer) {
super(moduleInputFileCache);
this.componentIndexer = componentIndexer;
- this.moduleKey = module.getKey();
+ this.moduleKey = moduleKey;
this.settings = settings;
this.indexer = indexer;
if (initializer.baseDir() != null) {
public void resetDirs(File basedir, File buildDir, List<File> sourceDirs, List<File> testDirs, List<File> binaryDirs) {
if (initialized) {
- throw new SonarException("Module filesystem is already initialized. Modifications of filesystem are only allowed during Initializer phase.");
+ throw MessageException.of("Module filesystem is already initialized. Modifications of filesystem are only allowed during Initializer phase.");
}
setBaseDir(basedir);
this.buildDir = buildDir;
public void index() {
if (initialized) {
- throw new SonarException("Module filesystem can only be indexed once");
+ throw MessageException.of("Module filesystem can only be indexed once");
}
initialized = true;
indexer.index(this);
- componentIndexer.execute(this);
+ if (componentIndexer != null) {
+ componentIndexer.execute(this);
+ }
}
private List<File> existingDirs(List<File> dirs) {
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFileFilter;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.scan.filesystem.FileSystemFilter;
import org.sonar.api.scan.filesystem.FileType;
import org.sonar.api.scan.filesystem.ModuleFileSystem;
@Override
public File relativeDir() {
- return new File(((DefaultInputFile)inputFile).sourceDirAbsolutePath());
+ return new File(((DeprecatedDefaultInputFile)inputFile).sourceDirAbsolutePath());
}
@Override
public String relativePath() {
- return ((DefaultInputFile)inputFile).pathRelativeToSourceDir();
+ return ((DeprecatedDefaultInputFile)inputFile).pathRelativeToSourceDir();
}
@Override
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFileFilter;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.resources.Project;
-import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.MessageException;
import java.io.File;
import java.util.Collection;
*/
public class FileIndexer implements BatchComponent {
+ private static final Logger LOG = LoggerFactory.getLogger(FileIndexer.class);
+
private static final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter(".")));
private static final IOFileFilter FILE_FILTER = HiddenFileFilter.VISIBLE;
private final List<InputFileFilter> filters;
private final InputFileCache fileCache;
- private final Project module;
+ private final boolean isAggregator;
private final ExclusionFilters exclusionFilters;
private final InputFileBuilderFactory inputFileBuilderFactory;
public FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
- InputFileCache cache, Project module) {
+ InputFileCache cache, Project module, ProjectDefinition def) {
+ this(filters, exclusionFilters, inputFileBuilderFactory, cache, !module.getModules().isEmpty());
+ }
+
+ /**
+ * Used by scan2
+ */
+ public FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
+ InputFileCache cache, ProjectDefinition def) {
+ this(filters, exclusionFilters, inputFileBuilderFactory, cache, !def.getSubProjects().isEmpty());
+ }
+
+ private FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
+ InputFileCache cache, boolean isAggregator) {
this.filters = filters;
this.exclusionFilters = exclusionFilters;
this.inputFileBuilderFactory = inputFileBuilderFactory;
this.fileCache = cache;
- this.module = module;
+ this.isAggregator = isAggregator;
}
void index(DefaultModuleFileSystem fileSystem) {
- Logger logger = LoggerFactory.getLogger(FileIndexer.class);
- if (!module.getModules().isEmpty()) {
+ if (isAggregator) {
// No indexing for an aggregator module
return;
}
- logger.info("Index files");
+ LOG.info("Index files");
exclusionFilters.prepare();
Progress progress = new Progress(fileCache.byModule(fileSystem.moduleKey()));
fileCache.remove(fileSystem.moduleKey(), removed);
}
- logger.info(String.format("%d files indexed", progress.count()));
+ LOG.info(String.format("%d files indexed", progress.count()));
}
private void indexFiles(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress progress, List<File> sourceFiles, InputFile.Type type) {
for (File sourceFile : sourceFiles) {
- DefaultInputFile inputFile = inputFileBuilder.create(sourceFile);
+ DeprecatedDefaultInputFile inputFile = inputFileBuilder.create(sourceFile);
if (inputFile != null && exclusionFilters.accept(inputFile, type)) {
indexFile(inputFileBuilder, fileSystem, progress, inputFile, type);
}
private void indexDirectory(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress status, File dirToIndex, InputFile.Type type) {
Collection<File> files = FileUtils.listFiles(dirToIndex, FILE_FILTER, DIR_FILTER);
for (File file : files) {
- DefaultInputFile inputFile = inputFileBuilder.create(file);
+ DeprecatedDefaultInputFile inputFile = inputFileBuilder.create(file);
if (inputFile != null && exclusionFilters.accept(inputFile, type)) {
indexFile(inputFileBuilder, fileSystem, status, inputFile, type);
}
}
private void indexFile(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fs,
- Progress status, DefaultInputFile inputFile, InputFile.Type type) {
+ Progress status, DeprecatedDefaultInputFile inputFile, InputFile.Type type) {
InputFile completedFile = inputFileBuilder.complete(inputFile, type);
if (completedFile != null && accept(completedFile)) {
fs.add(completedFile);
void markAsIndexed(InputFile inputFile) {
if (indexed.contains(inputFile)) {
- throw new SonarException("File " + inputFile + " can't be indexed twice. Please check that inclusion/exclusion patterns produce "
+ throw MessageException.of("File " + inputFile + " can't be indexed twice. Please check that inclusion/exclusion patterns produce "
+ "disjoint sets for main and test files");
}
removed.remove(inputFile);
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.AnalysisMode;
import org.sonar.batch.util.DeprecatedKeyUtils;
}
@CheckForNull
- DefaultInputFile create(File file) {
+ DeprecatedDefaultInputFile create(File file) {
String relativePath = pathResolver.relativePath(fs.baseDir(), file);
if (relativePath == null) {
LOG.warn("File '{}' is ignored. It is not located in module basedir '{}'.", file.getAbsolutePath(), fs.baseDir());
return null;
}
- DefaultInputFile inputFile = new DefaultInputFile(relativePath);
+ DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile(relativePath);
inputFile.setBasedir(fs.baseDir());
inputFile.setFile(file);
return inputFile;
* Optimization to not set all InputFile data if the file is excluded from analysis.
*/
@CheckForNull
- DefaultInputFile complete(DefaultInputFile inputFile, InputFile.Type type) {
+ DeprecatedDefaultInputFile complete(DeprecatedDefaultInputFile inputFile, InputFile.Type type) {
inputFile.setType(type);
inputFile.setKey(new StringBuilder().append(moduleKey).append(":").append(inputFile.relativePath()).toString());
inputFile.setBasedir(fs.baseDir());
return inputFile;
}
- private void fillDeprecatedData(DefaultInputFile inputFile) {
+ private void fillDeprecatedData(DeprecatedDefaultInputFile inputFile) {
List<File> sourceDirs = InputFile.Type.MAIN == inputFile.type() ? fs.sourceDirs() : fs.testDirs();
for (File sourceDir : sourceDirs) {
String sourceRelativePath = pathResolver.relativePath(sourceDir, inputFile.file());
package org.sonar.batch.scan.filesystem;
import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.AnalysisMode;
private final StatusDetectionFactory statusDetectionFactory;
private final AnalysisMode analysisMode;
- public InputFileBuilderFactory(Project moduleDef, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
- StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
- this.moduleKey = moduleDef.getEffectiveKey();
+ public InputFileBuilderFactory(Project module, ProjectDefinition def, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
+ StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
+ this(module.getEffectiveKey(), pathResolver, langDetectionFactory, statusDetectionFactory, analysisMode);
+ }
+
+ /**
+ * Used by scan2
+ */
+ public InputFileBuilderFactory(ProjectDefinition def, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
+ StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
+ this(def.getKey(), pathResolver, langDetectionFactory, statusDetectionFactory, analysisMode);
+ }
+
+ private InputFileBuilderFactory(String effectiveKey, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
+ StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
+ this.moduleKey = effectiveKey;
this.pathResolver = pathResolver;
this.langDetectionFactory = langDetectionFactory;
this.statusDetectionFactory = statusDetectionFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.FileIndex;
-import org.sonar.api.batch.fs.internal.RelativePathIndex;
import org.sonar.batch.index.Cache;
import org.sonar.batch.index.Caches;
return this;
}
-
- public void index(String moduleKey, String indexId, Object indexValue, InputFile inputFile) {
- // already indexed by relative path is already used
- if (!indexId.equals(RelativePathIndex.ID)) {
- // See limitation of org.sonar.batch.index.Cache -> fail
- // to traverse a sub-tree, for example in order to
- // have the following structure in InputFileCache :
- // [index id|module key|index value]
- throw new UnsupportedOperationException("Only relative path index is supported yet");
- }
- }
-
@CheckForNull
- public InputFile get(String moduleKey, String indexId, Object indexValue) {
- if (!indexId.equals(RelativePathIndex.ID)) {
- throw new UnsupportedOperationException("Only relative path index is supported yet");
- }
- return cache.get(moduleKey, indexValue);
+ public InputFile get(String moduleKey, String relativePath) {
+ return cache.get(moduleKey, relativePath);
}
}
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.PathPattern;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.api.languages.Language;
+import org.sonar.batch.languages.LanguagesReferential;
import javax.annotation.CheckForNull;
import java.text.MessageFormat;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
private final List<String> languagesToConsider = Lists.newArrayList();
private final String forcedLanguage;
- LanguageDetection(Settings settings, Languages languages) {
+ LanguageDetection(Settings settings, LanguagesReferential languages) {
for (Language language : languages.all()) {
- String[] filePatterns = settings.getStringArray(getFileLangPatternPropKey(language.getKey()));
+ String[] filePatterns = settings.getStringArray(getFileLangPatternPropKey(language.key()));
PathPattern[] pathPatterns = PathPattern.create(filePatterns);
if (pathPatterns.length > 0) {
- patternsByLanguage.put(language.getKey(), pathPatterns);
+ patternsByLanguage.put(language.key(), pathPatterns);
} else {
// If no custom language pattern is defined then fallback to suffixes declared by language
- String[] patterns = Arrays.copyOf(language.getFileSuffixes(), language.getFileSuffixes().length);
+ String[] patterns = language.fileSuffixes().toArray(new String[language.fileSuffixes().size()]);
for (int i = 0; i < patterns.length; i++) {
String suffix = patterns[i];
String extension = sanitizeExtension(suffix);
patterns[i] = "**/*." + extension;
}
PathPattern[] defaultLanguagePatterns = PathPattern.create(patterns);
- patternsByLanguage.put(language.getKey(), defaultLanguagePatterns);
- LOG.debug("Declared extensions of language " + language + " were converted to " + getDetails(language.getKey()));
+ patternsByLanguage.put(language.key(), defaultLanguagePatterns);
+ LOG.debug("Declared extensions of language " + language + " were converted to " + getDetails(language.key()));
}
}
import org.sonar.api.BatchComponent;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Languages;
+import org.sonar.batch.languages.LanguagesReferential;
public class LanguageDetectionFactory implements BatchComponent {
private final Settings settings;
- private final Languages languages;
+ private final LanguagesReferential languages;
- public LanguageDetectionFactory(Settings settings, Languages languages) {
+ public LanguageDetectionFactory(Settings settings, LanguagesReferential languages) {
this.settings = settings;
this.languages = languages;
}
package org.sonar.batch.scan.filesystem;
import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.UniqueIndexPredicate;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.RelativePathPredicate;
import org.sonar.api.resources.Project;
public class ModuleInputFileCache extends DefaultFileSystem.Cache implements BatchComponent {
private final String moduleKey;
private final InputFileCache projectCache;
- public ModuleInputFileCache(Project module, InputFileCache projectCache) {
+ public ModuleInputFileCache(Project module, ProjectDefinition projectDef, InputFileCache projectCache) {
this.moduleKey = module.getKey();
this.projectCache = projectCache;
}
+ /**
+ * Used by scan2
+ */
+ public ModuleInputFileCache(ProjectDefinition projectDef, InputFileCache projectCache) {
+ this.moduleKey = projectDef.getKey();
+ this.projectCache = projectCache;
+ }
+
@Override
protected Iterable<InputFile> inputFiles() {
return projectCache.byModule(moduleKey);
}
@Override
- protected InputFile inputFile(UniqueIndexPredicate predicate) {
- return projectCache.get(moduleKey, predicate.indexId(), predicate.value());
+ protected InputFile inputFile(RelativePathPredicate predicate) {
+ return projectCache.get(moduleKey, predicate.path());
}
@Override
protected void doAdd(InputFile inputFile) {
projectCache.put(moduleKey, inputFile);
}
-
- @Override
- protected void doIndex(String indexId, Object value, InputFile inputFile) {
- projectCache.index(moduleKey, indexId, value, inputFile);
- }
}
import org.sonar.api.BatchComponent;
+import java.util.Collections;
+
public class StatusDetectionFactory implements BatchComponent {
private final PreviousFileHashLoader previousFileHashLoader;
this.previousFileHashLoader = l;
}
+ /**
+ * Used by scan2
+ */
+ public StatusDetectionFactory() {
+ this.previousFileHashLoader = null;
+ }
+
StatusDetection create() {
- return new StatusDetection(previousFileHashLoader.hashByRelativePath());
+ return new StatusDetection(previousFileHashLoader != null ? previousFileHashLoader.hashByRelativePath() : Collections.<String, String>emptyMap());
}
}
public class MeasureCache implements BatchComponent {
private final Cache<Measure> cache;
- private final Cache<String> dataCache;
public MeasureCache(Caches caches) {
cache = caches.createCache("measures");
- dataCache = caches.createCache("measuresData");
}
public Iterable<Entry<Measure>> entries() {
}
public Iterable<Measure> byMetric(Resource r, String metricKey) {
- return cache.values(r.getEffectiveKey(), metricKey);
+ return byMetric(r.getEffectiveKey(), metricKey);
+ }
+
+ public Iterable<Measure> byMetric(String resourceKey, String metricKey) {
+ return cache.values(resourceKey, metricKey);
}
public MeasureCache put(Resource resource, Measure measure) {
}
return sb.toString();
}
+
}
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.platform.Server;
writeJsonModuleComponents(json, rootModule);
// TODO we need to dump directories
for (InputFile inputFile : fileCache.all()) {
- String key = ((DefaultInputFile) inputFile).key();
+ String key = ((DeprecatedDefaultInputFile) inputFile).key();
json
.beginObject()
.prop("key", key)
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.platform.ComponentContainer;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.analyzer.AnalyzerDescriptor;
+
+import java.util.Collection;
+
+public class AnalyzersExecutor implements BatchComponent {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AnalyzersExecutor.class);
+
+ private ComponentContainer container;
+
+ public AnalyzersExecutor(ComponentContainer container) {
+ this.container = container;
+ }
+
+ public void execute(AnalyzerContext context) {
+ Collection<Analyzer> analyzers = container.getComponentsByType(Analyzer.class);
+
+ for (Analyzer analyzer : analyzers) {
+
+ AnalyzerDescriptor descriptor = analyzer.describe();
+
+ LOG.info("Execute analyzer: " + descriptor.name());
+
+ executeSensor(context, analyzer);
+ }
+
+ }
+
+ private void executeSensor(AnalyzerContext context, Analyzer analyzer) {
+ analyzer.analyse(context);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan2;
+
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.analyzer.issue.AnalyzerIssue;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.api.measures.Metric;
+import org.sonar.batch.issue.ModuleIssues;
+import org.sonar.core.component.ComponentKeys;
+import org.sonar.core.issue.DefaultIssueBuilder;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+public class DefaultAnalyzerContext implements AnalyzerContext {
+
+ private final MeasureCache measureCache;
+ private ProjectDefinition def;
+ private ModuleIssues moduleIssues;
+
+ public DefaultAnalyzerContext(ProjectDefinition def, MeasureCache measureCache, ModuleIssues moduleIssues) {
+ this.def = def;
+ this.measureCache = measureCache;
+ this.moduleIssues = moduleIssues;
+ }
+
+ @Override
+ public AnalyzerMeasure getMeasure(String metricKey) {
+ return measureCache.byMetric(def.getKey(), metricKey);
+ }
+
+ @Override
+ public <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric) {
+ return (AnalyzerMeasure<G>) measureCache.byMetric(def.getKey(), metric.key());
+ }
+
+ @Override
+ public AnalyzerMeasure getMeasure(InputFile file, String metricKey) {
+ return measureCache.byMetric(ComponentKeys.createEffectiveKey(def.getKey(), file), metricKey);
+ }
+
+ @Override
+ public <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric) {
+ return (AnalyzerMeasure<G>) measureCache.byMetric(ComponentKeys.createEffectiveKey(def.getKey(), file), metric.key());
+ }
+
+ @Override
+ public void addMeasure(org.sonar.batch.api.analyzer.measure.AnalyzerMeasure<?> measure) {
+ if (measure.inputFile() != null) {
+ measureCache.put(ComponentKeys.createEffectiveKey(def.getKey(), measure.inputFile()), measure);
+ } else {
+ measureCache.put(def.getKey(), measure);
+ }
+ }
+
+ @Override
+ public void addIssue(AnalyzerIssue issue) {
+ DefaultIssueBuilder builder = new DefaultIssueBuilder()
+ .projectKey(def.getKey());
+ if (issue.inputFile() != null) {
+ builder.componentKey(ComponentKeys.createEffectiveKey(def.getKey(), issue.inputFile()));
+ } else {
+ builder.componentKey(def.getKey());
+ }
+
+ moduleIssues.initAndAddIssue((DefaultIssue) builder
+ .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
+ .message(issue.message())
+ .line(issue.line())
+ .effortToFix(issue.effortToFix())
+ .build());
+ }
+
+ @Override
+ public void addIssues(Collection<AnalyzerIssue> issues) {
+ for (AnalyzerIssue analyzerIssue : issues) {
+ addIssue(analyzerIssue);
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan2;
+
+import com.google.common.base.Preconditions;
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.index.Cache;
+import org.sonar.batch.index.Cache.Entry;
+import org.sonar.batch.index.Caches;
+
+/**
+ * Cache of all measures. This cache is shared amongst all project modules.
+ */
+public class MeasureCache implements BatchComponent {
+
+ private final Cache<AnalyzerMeasure<?>> cache;
+
+ public MeasureCache(Caches caches) {
+ cache = caches.createCache("measures");
+ }
+
+ public Iterable<Entry<AnalyzerMeasure<?>>> entries() {
+ return cache.entries();
+ }
+
+ public AnalyzerMeasure<?> byMetric(String resourceKey, String metricKey) {
+ return cache.get(resourceKey, metricKey);
+ }
+
+ public MeasureCache put(String resourceKey, AnalyzerMeasure<?> measure) {
+ Preconditions.checkNotNull(resourceKey);
+ Preconditions.checkNotNull(measure.metricKey());
+ cache.put(resourceKey, measure.metricKey(), measure);
+ return this;
+ }
+
+ public boolean contains(String resourceKey, AnalyzerMeasure<?> measure) {
+ Preconditions.checkNotNull(resourceKey);
+ Preconditions.checkNotNull(measure);
+ return cache.containsKey(resourceKey, measure.metricKey());
+ }
+
+ public Iterable<AnalyzerMeasure<?>> all() {
+ return cache.values();
+ }
+
+}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.rule.CheckFactory;
import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.batch.DefaultProjectClasspath;
-import org.sonar.batch.DefaultSensorContext;
-import org.sonar.batch.DefaultTimeMachine;
-import org.sonar.batch.ProjectTree;
-import org.sonar.batch.ResourceFilters;
-import org.sonar.batch.ViolationFilters;
+import org.sonar.batch.api.BatchComponent;
+import org.sonar.batch.api.InstantiationStrategy;
import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
import org.sonar.batch.bootstrap.ExtensionInstaller;
import org.sonar.batch.bootstrap.ExtensionMatcher;
import org.sonar.batch.bootstrap.ExtensionUtils;
-import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.batch.events.EventBus;
-import org.sonar.batch.index.DefaultIndex;
-import org.sonar.batch.index.ResourcePersister;
import org.sonar.batch.issue.IssuableFactory;
import org.sonar.batch.issue.IssueFilters;
import org.sonar.batch.issue.ModuleIssues;
import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner;
-import org.sonar.batch.language.LanguageDistributionDecorator;
-import org.sonar.batch.phases.Phase2Executor;
-import org.sonar.batch.phases.PhaseExecutor;
-import org.sonar.batch.phases.PhasesTimeProfiler;
-import org.sonar.batch.qualitygate.GenerateQualityGateEvents;
-import org.sonar.batch.qualitygate.QualityGateProvider;
-import org.sonar.batch.qualitygate.QualityGateVerifier;
-import org.sonar.batch.rule.ActiveRulesProvider;
import org.sonar.batch.rule.ModuleQProfiles;
-import org.sonar.batch.rule.QProfileDecorator;
-import org.sonar.batch.rule.QProfileEventsDecorator;
-import org.sonar.batch.rule.QProfileSensor;
import org.sonar.batch.rule.QProfileVerifier;
-import org.sonar.batch.rule.RulesProfileProvider;
import org.sonar.batch.scan.LanguageVerifier;
import org.sonar.batch.scan.ModuleSettings;
-import org.sonar.batch.scan.filesystem.ComponentIndexer;
import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.batch.scan.filesystem.DeprecatedFileFilters;
import org.sonar.batch.scan.filesystem.ExclusionFilters;
import org.sonar.batch.scan.filesystem.LanguageDetectionFactory;
import org.sonar.batch.scan.filesystem.ModuleFileSystemInitializer;
import org.sonar.batch.scan.filesystem.ModuleInputFileCache;
-import org.sonar.batch.scan.filesystem.PreviousFileHashLoader;
-import org.sonar.batch.scan.filesystem.ProjectFileSystemAdapter;
import org.sonar.batch.scan.filesystem.StatusDetectionFactory;
-import org.sonar.batch.scan.report.JsonReport;
-import org.sonar.core.component.ScanPerspectives;
-import org.sonar.core.measure.MeasurementFilters;
public class ModuleScanContainer extends ComponentContainer {
private static final Logger LOG = LoggerFactory.getLogger(ModuleScanContainer.class);
- private final Project module;
+ private final ProjectDefinition moduleDefinition;
- public ModuleScanContainer(ProjectScanContainer parent, Project module) {
+ public ModuleScanContainer(ProjectScanContainer parent, ProjectDefinition moduleDefinition) {
super(parent);
- this.module = module;
+ this.moduleDefinition = moduleDefinition;
}
@Override
protected void doBeforeStart() {
- LOG.info("------------- Scan {}", module.getName());
+ LOG.info("------------- Scan {}", moduleDefinition.getName());
addCoreComponents();
addExtensions();
}
private void addCoreComponents() {
- ProjectDefinition moduleDefinition = getComponentByType(ProjectTree.class).getProjectDefinition(module);
add(
moduleDefinition,
- module.getConfiguration(),
- module,
- ModuleSettings.class);
+ ModuleSettings.class,
- // hack to initialize commons-configuration before ExtensionProviders
- getComponentByType(ModuleSettings.class);
-
- add(
EventBus.class,
Phase2Executor.class,
- PhasesTimeProfiler.class,
Phase2Executor.getPhaseClasses(),
moduleDefinition.getContainerExtensions(),
+ AnalyzersExecutor.class,
// file system
ModuleInputFileCache.class,
InputFileBuilderFactory.class,
StatusDetectionFactory.class,
LanguageDetectionFactory.class,
- PreviousFileHashLoader.class,
FileIndexer.class,
- ComponentIndexer.class,
LanguageVerifier.class,
FileSystemLogger.class,
- DefaultProjectClasspath.class,
DefaultModuleFileSystem.class,
ModuleFileSystemInitializer.class,
- ProjectFileSystemAdapter.class,
QProfileVerifier.class,
- // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
- getComponentByType(ResourcePersister.class).getSnapshot(module),
-
- TimeMachineConfiguration.class,
- DefaultSensorContext.class,
+ DefaultAnalyzerContext.class,
BatchExtensionDictionnary.class,
- DefaultTimeMachine.class,
- ViolationFilters.class,
IssueFilters.class,
- MeasurementFilters.class,
- ResourceFilters.class,
-
- // quality gates
- new QualityGateProvider(),
- QualityGateVerifier.class,
- GenerateQualityGateEvents.class,
// rules
ModuleQProfiles.class,
- new ActiveRulesProvider(),
- new RulesProfileProvider(),
- QProfileSensor.class,
- QProfileDecorator.class,
- QProfileEventsDecorator.class,
CheckFactory.class,
- // report
- JsonReport.class,
-
// issues
IssuableFactory.class,
ModuleIssues.class,
IssueExclusionsRegexpScanner.class,
IssueExclusionsLoader.class,
EnforceIssuesFilter.class,
- IgnoreIssuesFilter.class,
-
- // language
- LanguageDistributionDecorator.class,
-
- ScanPerspectives.class);
+ IgnoreIssuesFilter.class);
}
private void addExtensions() {
ExtensionInstaller installer = getComponentByType(ExtensionInstaller.class);
installer.install(this, new ExtensionMatcher() {
public boolean accept(Object extension) {
- if (ExtensionUtils.isType(extension, BatchComponent.class) && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT)) {
- // Special use-case: the extension point ProjectBuilder is used in a Maven environment to define some
- // new sub-projects without pom.
- // Example : C# plugin adds sub-projects at runtime, even if they are not defined in root pom.
- return !ExtensionUtils.isMavenExtensionOnly(extension) || module.getPom() != null;
- }
- return false;
+ return ExtensionUtils.isType(extension, BatchComponent.class)
+ && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT);
}
});
}
@Override
protected void doAfterStart() {
- DefaultIndex index = getComponentByType(DefaultIndex.class);
- index.setCurrentProject(module,
- getComponentByType(ModuleIssues.class));
-
- getComponentByType(PhaseExecutor.class).execute(module);
+ getComponentByType(Phase2Executor.class).execute(moduleDefinition);
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan2;
+
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
+import org.sonar.batch.phases.SensorsExecutor;
+import org.sonar.batch.rule.QProfileVerifier;
+import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
+import org.sonar.batch.scan.filesystem.FileSystemLogger;
+
+import java.util.Collection;
+
+public final class Phase2Executor {
+
+ public static final Logger LOGGER = LoggerFactory.getLogger(Phase2Executor.class);
+
+ private final AnalyzersExecutor analyzersExecutor;
+ private final AnalyzerContext analyzerContext;
+ private final FileSystemLogger fsLogger;
+ private final DefaultModuleFileSystem fs;
+ private final QProfileVerifier profileVerifier;
+ private final IssueExclusionsLoader issueExclusionsLoader;
+
+ public Phase2Executor(AnalyzersExecutor analyzersExecutor,
+ AnalyzerContext analyzerContext,
+ FileSystemLogger fsLogger, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
+ IssueExclusionsLoader issueExclusionsLoader) {
+ this.analyzersExecutor = analyzersExecutor;
+ this.analyzerContext = analyzerContext;
+ this.fsLogger = fsLogger;
+ this.fs = fs;
+ this.profileVerifier = profileVerifier;
+ this.issueExclusionsLoader = issueExclusionsLoader;
+ }
+
+ public static Collection<Class> getPhaseClasses() {
+ return Lists.<Class>newArrayList(SensorsExecutor.class);
+ }
+
+ /**
+ * Executed on each module
+ */
+ public void execute(ProjectDefinition moduleDefinition) {
+ fsLogger.log();
+
+ // Index and lock the filesystem
+ fs.index();
+
+ // Log detected languages and their profiles after FS is indexed and languages detected
+ profileVerifier.execute();
+
+ // Initialize issue exclusions
+ issueExclusionsLoader.execute();
+
+ analyzersExecutor.execute(analyzerContext);
+ }
+}
package org.sonar.batch.scan2;
import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.BatchComponent;
import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.batch.bootstrap.ProjectBootstrapper;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.SonarException;
-import org.sonar.batch.DefaultFileLinesContextFactory;
-import org.sonar.batch.ProjectConfigurator;
-import org.sonar.batch.ProjectTree;
+import org.sonar.batch.api.BatchComponent;
+import org.sonar.batch.api.InstantiationStrategy;
import org.sonar.batch.bootstrap.ExtensionInstaller;
import org.sonar.batch.bootstrap.ExtensionMatcher;
import org.sonar.batch.bootstrap.ExtensionUtils;
-import org.sonar.batch.bootstrap.MetricProvider;
-import org.sonar.batch.components.PeriodsDefinition;
-import org.sonar.batch.debt.DebtModelProvider;
import org.sonar.batch.debt.IssueChangelogDebtCalculator;
import org.sonar.batch.index.Caches;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.index.ComponentDataPersister;
-import org.sonar.batch.index.DefaultIndex;
-import org.sonar.batch.index.DefaultPersistenceManager;
-import org.sonar.batch.index.DefaultResourcePersister;
-import org.sonar.batch.index.DependencyPersister;
-import org.sonar.batch.index.EventPersister;
-import org.sonar.batch.index.LinkPersister;
-import org.sonar.batch.index.MeasurePersister;
import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.index.ResourceKeyMigration;
import org.sonar.batch.index.SnapshotCache;
-import org.sonar.batch.index.SourcePersister;
import org.sonar.batch.issue.DefaultProjectIssues;
import org.sonar.batch.issue.DeprecatedViolations;
import org.sonar.batch.issue.IssueCache;
import org.sonar.batch.issue.ScanIssueStorage;
import org.sonar.batch.phases.GraphPersister;
import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
-import org.sonar.batch.rule.RulesProvider;
import org.sonar.batch.scan.ProjectReactorBuilder;
-import org.sonar.batch.scan.ProjectSettingsReady;
import org.sonar.batch.scan.filesystem.InputFileCache;
import org.sonar.batch.scan.maven.FakeMavenPluginExecutor;
import org.sonar.batch.scan.maven.MavenPluginExecutor;
-import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.batch.source.HighlightableBuilder;
import org.sonar.batch.source.SymbolizableBuilder;
import org.sonar.core.component.ScanGraph;
import org.sonar.core.issue.IssueUpdater;
import org.sonar.core.issue.workflow.FunctionExecutor;
import org.sonar.core.issue.workflow.IssueWorkflow;
-import org.sonar.core.notification.DefaultNotificationManager;
-import org.sonar.core.technicaldebt.DefaultTechnicalDebtModel;
import org.sonar.core.test.TestPlanBuilder;
import org.sonar.core.test.TestPlanPerspectiveLoader;
import org.sonar.core.test.TestableBuilder;
import org.sonar.core.test.TestablePerspectiveLoader;
-import org.sonar.core.user.DefaultUserFinder;
public class ProjectScanContainer extends ComponentContainer {
public ProjectScanContainer(ComponentContainer taskContainer) {
}
private void projectBootstrap() {
- // Old versions of bootstrappers used to pass project reactor as an extension
- // so check if it is already present in parent container
- ProjectReactor reactor = getComponentByType(ProjectReactor.class);
+ ProjectReactor reactor;
+ ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
+ Settings settings = getComponentByType(Settings.class);
+ if (bootstrapper == null
+ // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
+ || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
+ // Use default SonarRunner project bootstrapper
+ ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
+ reactor = builder.execute();
+ } else {
+ reactor = bootstrapper.bootstrap();
+ }
if (reactor == null) {
- // OK, not present, so look for a custom ProjectBootstrapper
- ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
- Settings settings = getComponentByType(Settings.class);
- if (bootstrapper == null
- // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
- || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
- // Use default SonarRunner project bootstrapper
- ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
- reactor = builder.execute();
- } else {
- reactor = bootstrapper.bootstrap();
- }
- if (reactor == null) {
- throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
- }
- add(reactor);
+ throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
}
+ add(reactor);
}
private void addBatchComponents() {
add(
- DefaultPersistenceManager.class,
- DependencyPersister.class,
- EventPersister.class,
- LinkPersister.class,
- MeasurePersister.class,
- DefaultResourcePersister.class,
- SourcePersister.class,
- DefaultNotificationManager.class,
- MetricProvider.class,
- ProjectConfigurator.class,
- DefaultIndex.class,
- ResourceKeyMigration.class,
- DefaultFileLinesContextFactory.class,
Caches.class,
SnapshotCache.class,
ResourceCache.class,
ComponentDataCache.class,
ComponentDataPersister.class,
- DefaultUserFinder.class,
+ MeasureCache.class,
// file system
InputFileCache.class,
GraphPersister.class,
// lang
- Languages.class,
HighlightableBuilder.class,
SymbolizableBuilder.class,
- // technical debt
- DefaultTechnicalDebtModel.class,
- new DebtModelProvider(),
-
- // rules
- new RulesProvider(),
-
- // Differential periods
- PeriodsDefinition.class,
-
- // Measures
- MeasureCache.class,
-
- ProjectSettingsReady.class);
+ ScanTaskObservers.class);
}
private void fixMavenExecutor() {
@Override
protected void doAfterStart() {
- ProjectTree tree = getComponentByType(ProjectTree.class);
- scanRecursively(tree.getRootProject());
+ ProjectReactor tree = getComponentByType(ProjectReactor.class);
+ scanRecursively(tree.getRoot());
+ getComponentByType(ScanTaskObservers.class).notifyEndOfScanTask();
}
- private void scanRecursively(Project module) {
- for (Project subModules : module.getModules()) {
+ private void scanRecursively(ProjectDefinition module) {
+ for (ProjectDefinition subModules : module.getSubProjects()) {
scanRecursively(subModules);
}
scan(module);
}
@VisibleForTesting
- void scan(Project module) {
+ void scan(ProjectDefinition module) {
new ModuleScanContainer(this, module).execute();
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan2;
+
+import org.sonar.batch.api.BatchExtension;
+
+public interface ScanTaskObserver extends BatchExtension {
+
+ void scanTaskCompleted(ProjectScanContainer container);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.scan2;
+
+public class ScanTaskObservers {
+
+ private ScanTaskObserver[] observers;
+ private ProjectScanContainer projectScanContainer;
+
+ public ScanTaskObservers(ProjectScanContainer projectScanContainer, ScanTaskObserver... observers) {
+ this.projectScanContainer = projectScanContainer;
+ this.observers = observers;
+ }
+
+ public ScanTaskObservers(ProjectScanContainer projectScanContainer) {
+ this(projectScanContainer, new ScanTaskObserver[0]);
+ }
+
+ public void notifyEndOfScanTask() {
+ for (ScanTaskObserver scanTaskObserver : observers) {
+ scanTaskObserver.scanTaskCompleted(projectScanContainer);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.scan2;
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.settings;
\ No newline at end of file
import org.sonar.api.BatchExtension;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
import java.util.Collection;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
+import static org.mockito.Mockito.mock;
public class BatchExtensionDictionnaryTest {
for (BatchExtension extension : extensions) {
iocContainer.addSingleton(extension);
}
- return new BatchExtensionDictionnary(iocContainer);
+ return new BatchExtensionDictionnary(iocContainer, mock(FileSystem.class), mock(AnalyzerContext.class));
}
@Test
@Test
public void should_provide_plugin_metrics() {
- Metrics factory = new Metrics(){
+ Metrics factory = new Metrics() {
public List<Metric> getMetrics() {
- return Arrays.asList(new Metric.Builder("custom", "Custom", Metric.ValueType.FLOAT).create());
+ return Arrays.<Metric>asList(new Metric.Builder("custom", "Custom", Metric.ValueType.FLOAT).create());
}
};
- MetricProvider provider = new MetricProvider(new Metrics[]{factory});
+ MetricProvider provider = new MetricProvider(new Metrics[] {factory});
List<Metric> metrics = provider.provide();
assertThat(metrics.size()).isEqualTo(1 + CoreMetrics.getMetrics().size());
import org.slf4j.Logger;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.resources.Project;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
File file = new File(baseDir, path);
String effectiveKey = module.getKey() + ":" + path;
String deprecatedEffectiveKey = module.getKey() + ":" + deprecatedKey;
- return new DefaultInputFile(path).setFile(file)
- .setKey(effectiveKey)
+ return new DeprecatedDefaultInputFile(path)
.setDeprecatedKey(deprecatedEffectiveKey)
+ .setFile(file)
+ .setKey(effectiveKey)
.setType(isTest ? InputFile.Type.TEST : InputFile.Type.MAIN);
}
Logger logger = mock(Logger.class);
ResourceKeyMigration migration = new ResourceKeyMigration(getSession(), logger);
migration.checkIfMigrationNeeded(multiModuleProject);
-
+
migration.migrateIfNeeded(javaModule, javaInputFiles);
migration.migrateIfNeeded(phpModule, phpInputFiles);
verify(logger).info("Component {} changed to {}", "b:org/foo", "b:src/main/java/org/foo");
verify(logger).info("Component {} changed to {}", "b:[root]", "b:src/main/java");
- checkTables("shouldMigrateResourceKeys", new String[]{"build_date", "created_at"}, "projects");
+ checkTables("shouldMigrateResourceKeys", new String[] {"build_date", "created_at"}, "projects");
}
private static Project newProject(String key, String language) {
import org.mockito.MockitoAnnotations;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
@Test
public void shouldAnalyzeProject() throws IOException {
File javaFile1 = new File(baseDir, "src/main/java/Foo.java");
- fs.add(new DefaultInputFile("src/main/java/Foo.java")
+ fs.add(new DeprecatedDefaultInputFile("src/main/java/Foo.java")
.setFile(javaFile1)
.setType(InputFile.Type.MAIN)
.setKey("polop:src/main/java/Foo.java"));
File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java");
- fs.add(new DefaultInputFile("src/test/java/FooTest.java")
+ fs.add(new DeprecatedDefaultInputFile("src/test/java/FooTest.java")
.setFile(javaTestFile1)
.setType(InputFile.Type.TEST)
.setKey("polop:src/test/java/FooTest.java"));
@Test
public void shouldAnalyseFilesOnlyWhenRegexConfigured() throws IOException {
File javaFile1 = new File(baseDir, "src/main/java/Foo.java");
- fs.add(new DefaultInputFile("src/main/java/Foo.java")
+ fs.add(new DeprecatedDefaultInputFile("src/main/java/Foo.java")
.setFile(javaFile1)
.setType(InputFile.Type.MAIN)
.setKey("polop:src/main/java/Foo.java"));
File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java");
- fs.add(new DefaultInputFile("src/test/java/FooTest.java")
+ fs.add(new DeprecatedDefaultInputFile("src/test/java/FooTest.java")
.setFile(javaTestFile1)
.setType(InputFile.Type.TEST)
.setKey("polop:src/test/java/FooTest.java"));
@Test
public void shouldReportFailure() throws IOException {
File phpFile1 = new File(baseDir, "src/Foo.php");
- fs.add(new DefaultInputFile("src/Foo.php")
+ fs.add(new DeprecatedDefaultInputFile("src/Foo.php")
.setFile(phpFile1)
.setType(InputFile.Type.MAIN)
.setKey("polop:src/Foo.php"));
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.batch.medium;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.junit.Test;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.RuleQuery;
-import org.sonar.batch.bootstrap.PluginsReferential;
-import org.sonar.batch.bootstrapper.Batch;
-import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import org.sonar.batch.settings.SettingsReferential;
-import org.sonar.core.plugins.RemotePlugin;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class Scan2MediumTest {
-
- @Test
- public void mediumTest() {
- Batch batch = Batch.builder()
- .setEnableLoggingConfiguration(true)
- .addComponent(new EnvironmentInformation("mediumTest", "1.0"))
- .addComponent(new MockSettingsReferential())
- .addComponent(new MockPluginsReferential())
- .addComponent(new MockMetricFinder())
- .addComponent(new MockRuleFinder())
- .setBootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor"))
- .build();
-
- batch.start();
-
- // batch.executeTask(ImmutableMap.<String, String>builder().put("sonar.task", "scan").build());
-
- batch.stop();
- }
-
- private static class MockSettingsReferential implements SettingsReferential {
-
- private Map<String, String> globalSettings = new HashMap<String, String>();
- private Map<String, Map<String, String>> projectSettings = new HashMap<String, Map<String, String>>();
-
- @Override
- public Map<String, String> globalSettings() {
- return globalSettings;
- }
-
- @Override
- public Map<String, String> projectSettings(String projectKey) {
- return projectSettings.containsKey(projectKey) ? projectSettings.get(projectKey) : Collections.<String, String>emptyMap();
- }
-
- }
-
- private static class MockPluginsReferential implements PluginsReferential {
-
- private List<RemotePlugin> pluginList = new ArrayList<RemotePlugin>();
- private Map<RemotePlugin, File> pluginFiles = new HashMap<RemotePlugin, File>();
-
- @Override
- public List<RemotePlugin> pluginList() {
- return pluginList;
- }
-
- @Override
- public File pluginFile(RemotePlugin remote) {
- return pluginFiles.get(remote);
- }
-
- }
-
- private static class MockMetricFinder implements MetricFinder {
-
- private Map<String, Metric> metricsByKey = Maps.newLinkedHashMap();
- private Map<Integer, Metric> metricsById = Maps.newLinkedHashMap();
-
- @Override
- public Metric findById(int metricId) {
- return metricsById.get(metricId);
- }
-
- @Override
- public Metric findByKey(String key) {
- return metricsByKey.get(key);
- }
-
- @Override
- public Collection<Metric> findAll(List<String> metricKeys) {
- List<Metric> result = Lists.newLinkedList();
- for (String metricKey : metricKeys) {
- Metric metric = findByKey(metricKey);
- if (metric != null) {
- result.add(metric);
- }
- }
- return result;
- }
-
- @Override
- public Collection<Metric> findAll() {
- return metricsByKey.values();
- }
-
- }
-
- private static class MockRuleFinder implements RuleFinder {
- private BiMap<Integer, Rule> rulesById = HashBiMap.create();
- private Map<String, Map<String, Rule>> rulesByRepoKeyAndRuleKey = Maps.newHashMap();
-
- @Override
- public Rule findById(int ruleId) {
- return rulesById.get(ruleId);
- }
-
- @Override
- public Rule findByKey(String repositoryKey, String ruleKey) {
- Map<String, Rule> repository = rulesByRepoKeyAndRuleKey.get(repositoryKey);
- return repository != null ? repository.get(ruleKey) : null;
- }
-
- @Override
- public Rule findByKey(RuleKey key) {
- return findByKey(key.repository(), key.rule());
- }
-
- @Override
- public Rule find(RuleQuery query) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Collection<Rule> findAll(RuleQuery query) {
- throw new UnsupportedOperationException();
- }
- }
-
-}
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.qualityprofile.db.ActiveRuleDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
import java.util.Arrays;
@Test
public void build_active_rules() throws Exception {
setupData("shared");
- QualityProfileDao profileDao = new QualityProfileDao(getMyBatis());
- when(qProfiles.findAll()).thenReturn(Arrays.asList(
+ when(qProfiles.findAll()).thenReturn(Arrays.<QProfile>asList(
// 1 rule is enabled on java with severity INFO
- new ModuleQProfiles.QProfile(profileDao.selectById(2)),
+ new QProfileWithId(2, "Java Two", "java", 20),
// 1 rule is enabled on php with severity BLOCKER
- new ModuleQProfiles.QProfile(profileDao.selectById(3))
- ));
+ new QProfileWithId(3, "Php One", "php", 30)
+ ));
ActiveRulesProvider provider = new ActiveRulesProvider();
ActiveRuleDao activeRuleDao = new ActiveRuleDao(getMyBatis());
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
+import org.sonar.batch.rules.DefaultQProfileReferential;
+import org.sonar.batch.rules.QProfilesReferential;
+import org.sonar.batch.rules.QProfileWithId;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
public class ModuleQProfilesTest extends AbstractDaoTestCase {
- Languages languages = new Languages(new SimpleLanguage("java"), new SimpleLanguage("php"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new SimpleLanguage("java"), new SimpleLanguage("php")));
Settings settings = new Settings();
@Test
public void find_profiles() throws Exception {
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+ QProfilesReferential ref = new DefaultQProfileReferential(dao);
settings.setProperty("sonar.profile.java", "Java Two");
settings.setProperty("sonar.profile.abap", "Abap One");
settings.setProperty("sonar.profile.php", "Php One");
- ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, dao);
- List<ModuleQProfiles.QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
+ ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, ref);
+ List<QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
assertThat(qProfiles).hasSize(2);
assertThat(moduleQProfiles.findByLanguage("java")).isNotNull();
assertThat(moduleQProfiles.findByLanguage("php")).isNotNull();
assertThat(moduleQProfiles.findByLanguage("abap")).isNull();
- ModuleQProfiles.QProfile javaProfile = qProfiles.get(0);
+ QProfileWithId javaProfile = (QProfileWithId) qProfiles.get(0);
assertThat(javaProfile.id()).isEqualTo(2);
assertThat(javaProfile.name()).isEqualTo("Java Two");
assertThat(javaProfile.language()).isEqualTo("java");
assertThat(javaProfile.version()).isEqualTo(20);
- ModuleQProfiles.QProfile phpProfile = qProfiles.get(1);
+ QProfileWithId phpProfile = (QProfileWithId) qProfiles.get(1);
assertThat(phpProfile.id()).isEqualTo(3);
assertThat(phpProfile.name()).isEqualTo("Php One");
assertThat(phpProfile.language()).isEqualTo("php");
public void use_sonar_profile_property() throws Exception {
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+ QProfilesReferential ref = new DefaultQProfileReferential(dao);
settings.setProperty("sonar.profile", "Java Two");
settings.setProperty("sonar.profile.php", "Php One");
- ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, dao);
- List<ModuleQProfiles.QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
+ ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, ref);
+ List<QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
assertThat(qProfiles).hasSize(2);
- ModuleQProfiles.QProfile javaProfile = qProfiles.get(0);
+ QProfileWithId javaProfile = (QProfileWithId) qProfiles.get(0);
assertThat(javaProfile.id()).isEqualTo(2);
assertThat(javaProfile.name()).isEqualTo("Java Two");
assertThat(javaProfile.language()).isEqualTo("java");
assertThat(javaProfile.version()).isEqualTo(20);
// Fallback to sonar.profile.php if no match for sonar.profile
- ModuleQProfiles.QProfile phpProfile = qProfiles.get(1);
+ QProfileWithId phpProfile = (QProfileWithId) qProfiles.get(1);
assertThat(phpProfile.id()).isEqualTo(3);
assertThat(phpProfile.name()).isEqualTo("Php One");
assertThat(phpProfile.language()).isEqualTo("php");
public void fail_if_unknown_profile() throws Exception {
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+ QProfilesReferential ref = new DefaultQProfileReferential(dao);
settings.setProperty("sonar.profile.java", "Unknown");
settings.setProperty("sonar.profile.php", "Php One");
try {
- new ModuleQProfiles(settings, languages, dao);
+ new ModuleQProfiles(settings, languages, ref);
fail();
} catch (MessageException e) {
assertThat(e).hasMessage("Quality profile not found : 'Unknown' on language 'java'");
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.resources.Project;
import org.sonar.api.test.IsMeasure;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
public void no_qprofiles() throws Exception {
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
- when(moduleQProfiles.findAll()).thenReturn(Collections.<ModuleQProfiles.QProfile>emptyList());
+ when(moduleQProfiles.findAll()).thenReturn(Collections.<QProfile>emptyList());
QProfileSensor sensor = new QProfileSensor(moduleQProfiles, fs, dao);
assertThat(sensor.shouldExecuteOnProject(project)).isTrue();
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
- when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
- when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+ when(moduleQProfiles.findByLanguage("java")).thenReturn(new QProfileWithId(2, "Java Two", "java", 20));
+ when(moduleQProfiles.findByLanguage("php")).thenReturn(new QProfileWithId(3, "Php One", "php", 30));
when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
fs.addLanguages("java", "php", "abap");
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
- when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
- when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+ when(moduleQProfiles.findByLanguage("java")).thenReturn(new QProfileWithId(2, "Java Two", "java", 20));
+ when(moduleQProfiles.findByLanguage("php")).thenReturn(new QProfileWithId(3, "Php One", "php", 30));
when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
fs.addLanguages("java");
setupData("shared");
QualityProfileDao dao = new QualityProfileDao(getMyBatis());
- when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
- when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+ when(moduleQProfiles.findByLanguage("java")).thenReturn(new QProfileWithId(2, "Java Two", "java", 20));
+ when(moduleQProfiles.findByLanguage("php")).thenReturn(new QProfileWithId(3, "Php One", "php", 30));
when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
fs.addLanguages("java", "php");
import org.sonar.api.config.Settings;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.utils.MessageException;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class QProfileVerifierTest {
@Before
public void before() {
profiles = mock(ModuleQProfiles.class);
- QProfile javaProfile = mock(QProfile.class);
+ QProfileWithId javaProfile = mock(QProfileWithId.class);
when(javaProfile.name()).thenReturn("My Java profile");
javaRulesProfile = mock(RulesProfile.class);
when(profiles.findByLanguage("java")).thenReturn(javaProfile);
- QProfile cobolProfile = mock(QProfile.class);
+ QProfileWithId cobolProfile = mock(QProfileWithId.class);
when(cobolProfile.name()).thenReturn("My Cobol profile");
cobolRulesProfile = mock(RulesProfile.class);
when(profiles.findByLanguage("cobol")).thenReturn(cobolProfile);
import org.sonar.api.config.Settings;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rules.RuleFinder;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
import java.util.Arrays;
@Test
public void merge_profiles() throws Exception {
- ModuleQProfiles.QProfile qProfile = new ModuleQProfiles.QProfile(33, "Sonar way", "java", 12);
- when(qProfiles.findAll()).thenReturn(Arrays.asList(qProfile));
+ QProfileWithId qProfile = new QProfileWithId(33, "Sonar way", "java", 12);
+ when(qProfiles.findAll()).thenReturn(Arrays.<QProfile>asList(qProfile));
RulesProfile profile = provider.provide(qProfiles, activeRules, ruleFinder, settings);
public void keep_compatibility_with_single_language_projects() throws Exception {
settings.setProperty("sonar.language", "java");
- ModuleQProfiles.QProfile qProfile = new ModuleQProfiles.QProfile(33, "Sonar way", "java", 12);
+ QProfileWithId qProfile = new QProfileWithId(33, "Sonar way", "java", 12);
when(qProfiles.findByLanguage("java")).thenReturn(qProfile);
RulesProfile profile = provider.provide(qProfiles, activeRules, ruleFinder, settings);
package org.sonar.batch.rule;
import org.junit.Test;
+import org.sonar.batch.rules.QProfileWithId;
import static org.fest.assertions.Assertions.assertThat;
@Test
public void serialization() throws Exception {
- ModuleQProfiles.QProfile java = new ModuleQProfiles.QProfile(1, "Sonar Way", "java", 1);
- ModuleQProfiles.QProfile php = new ModuleQProfiles.QProfile(2, "Sonar Way", "php", 1);
+ QProfileWithId java = new QProfileWithId(1, "Sonar Way", "java", 1);
+ QProfileWithId php = new QProfileWithId(2, "Sonar Way", "php", 1);
UsedQProfiles used = UsedQProfiles.fromProfiles(java, php);
assertThat(used.toJSON()).isEqualTo(
import org.sonar.api.resources.Java;
import org.sonar.api.resources.Languages;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
import static org.fest.assertions.Assertions.assertThat;
public class LanguageVerifierTest {
Settings settings = new Settings();
- Languages languages = new Languages(Java.INSTANCE);
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(Java.INSTANCE));
DefaultFileSystem fs = new DefaultFileSystem();
@Rule
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import java.io.File;
public void key() throws Exception {
FilePredicate predicate = new AdditionalFilePredicates.KeyPredicate("struts:Action.java");
- DefaultInputFile inputFile = new DefaultInputFile("Action.java").setKey("struts:Action.java");
+ DefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setKey("struts:Action.java");
assertThat(predicate.apply(inputFile)).isTrue();
- inputFile = new DefaultInputFile("Filter.java").setKey("struts:Filter.java");
+ inputFile = new DeprecatedDefaultInputFile("Filter.java").setKey("struts:Filter.java");
assertThat(predicate.apply(inputFile)).isFalse();
}
public void deprecated_key() throws Exception {
FilePredicate predicate = new AdditionalFilePredicates.DeprecatedKeyPredicate("struts:Action.java");
- DefaultInputFile inputFile = new DefaultInputFile("Action.java").setDeprecatedKey("struts:Action.java");
+ DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setDeprecatedKey("struts:Action.java");
assertThat(predicate.apply(inputFile)).isTrue();
- inputFile = new DefaultInputFile("Filter.java").setDeprecatedKey("struts:Filter.java");
+ inputFile = new DeprecatedDefaultInputFile("Filter.java").setDeprecatedKey("struts:Filter.java");
assertThat(predicate.apply(inputFile)).isFalse();
}
File dir = temp.newFolder();
FilePredicate predicate = new AdditionalFilePredicates.SourceDirPredicate(dir.getAbsolutePath());
- DefaultInputFile inputFile = new DefaultInputFile("Action.java").setSourceDirAbsolutePath(dir.getAbsolutePath());
+ DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setSourceDirAbsolutePath(dir.getAbsolutePath());
assertThat(predicate.apply(inputFile)).isTrue();
- inputFile = new DefaultInputFile("Filter.java").setSourceDirAbsolutePath(temp.newFolder().getAbsolutePath());
+ inputFile = new DeprecatedDefaultInputFile("Filter.java").setSourceDirAbsolutePath(temp.newFolder().getAbsolutePath());
assertThat(predicate.apply(inputFile)).isFalse();
}
public void path_relative_to_source_dir() throws Exception {
FilePredicate predicate = new AdditionalFilePredicates.SourceRelativePathPredicate("foo/Bar.php");
- DefaultInputFile inputFile = new DefaultInputFile("src/php/foo/Bar.php").setPathRelativeToSourceDir("foo/Bar.php");
+ DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("src/php/foo/Bar.php").setPathRelativeToSourceDir("foo/Bar.php");
assertThat(predicate.apply(inputFile)).isTrue();
- inputFile = new DefaultInputFile("foo/Bar.php").setPathRelativeToSourceDir("Bar.php");
+ inputFile = new DeprecatedDefaultInputFile("foo/Bar.php").setPathRelativeToSourceDir("Bar.php");
assertThat(predicate.apply(inputFile)).isFalse();
}
}
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.AbstractLanguage;
import org.sonar.api.resources.Java;
File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java");
FileUtils.write(javaFile1, "\uFEFFpublic class Test", Charsets.UTF_8);
- fs.add(new DefaultInputFile("src/main/java/foo/bar/Foo.java").setFile(javaFile1)
+ fs.add(new DeprecatedDefaultInputFile("src/main/java/foo/bar/Foo.java")
.setPathRelativeToSourceDir("foo/bar/Foo.java")
+ .setFile(javaFile1)
.setLanguage("java"));
Languages languages = new Languages(Java.INSTANCE);
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class));
File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java");
FileUtils.copyFile(getFile(testFile), javaFile1);
- fs.add(new DefaultInputFile("src/main/java/foo/bar/Foo.java")
- .setFile(javaFile1)
+ fs.add(new DeprecatedDefaultInputFile("src/main/java/foo/bar/Foo.java")
.setPathRelativeToSourceDir("foo/bar/Foo.java")
+ .setFile(javaFile1)
.setLanguage("java"));
Languages languages = new Languages(Java.INSTANCE);
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class));
private DefaultInputFile newInputFile(String path, String content, String sourceRelativePath, String languageKey, boolean unitTest) throws IOException {
File file = new File(baseDir, path);
FileUtils.write(file, content);
- return new DefaultInputFile(path).setFile(file)
+ return new DeprecatedDefaultInputFile(path)
.setPathRelativeToSourceDir(sourceRelativePath)
+ .setFile(file)
.setLanguage(languageKey)
.setType(unitTest ? InputFile.Type.TEST : InputFile.Type.MAIN);
}
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
@Test
public void test_equals_and_hashCode() throws Exception {
- DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
- DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
- DefaultModuleFileSystem bar = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem bar = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("bar"), settings, fileIndexer, initializer, componentIndexer);
- DefaultModuleFileSystem branch = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem branch = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("bar", "branch", "My project"), settings, fileIndexer, initializer, componentIndexer);
assertThat(foo1.moduleKey()).isEqualTo("foo");
@Test
public void default_source_encoding() {
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
assertThat(fs.sourceCharset()).isEqualTo(Charset.defaultCharset());
@Test
public void source_encoding_is_set() {
settings.setProperty(CoreProperties.ENCODING_PROPERTY, "Cp1124");
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
assertThat(fs.encoding()).isEqualTo(Charset.forName("Cp1124"));
when(initializer.additionalSourceFiles()).thenReturn(Arrays.asList(additionalFile));
when(initializer.additionalTestFiles()).thenReturn(Arrays.asList(additionalTest));
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
when(initializer.workingDir()).thenReturn(basedir);
when(initializer.sourceDirs()).thenReturn(Arrays.asList(new File(basedir, "src/main/java")));
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
File existingDir = temp.newFolder("new_folder");
@Test
public void should_search_input_files() throws Exception {
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
File mainFile = temp.newFile();
- InputFile mainInput = new DefaultInputFile("Main.java").setFile(mainFile).setType(InputFile.Type.MAIN);
- InputFile testInput = new DefaultInputFile("Test.java").setFile(temp.newFile()).setType(InputFile.Type.TEST);
+ InputFile mainInput = new DeprecatedDefaultInputFile("Main.java").setFile(mainFile).setType(InputFile.Type.MAIN);
+ InputFile testInput = new DeprecatedDefaultInputFile("Test.java").setFile(temp.newFile()).setType(InputFile.Type.TEST);
when(moduleInputFileCache.inputFiles()).thenReturn(Lists.newArrayList(mainInput, testInput));
fs.index();
@Test
public void should_index() throws Exception {
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
verifyZeroInteractions(fileIndexer);
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.scan.filesystem.FileSystemFilter;
import org.sonar.api.scan.filesystem.FileType;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class DeprecatedFileFiltersTest {
public void no_filters() throws Exception {
DeprecatedFileFilters filters = new DeprecatedFileFilters();
- InputFile inputFile = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile());
+ InputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile());
assertThat(filters.accept(inputFile)).isTrue();
}
File basedir = temp.newFolder();
File file = temp.newFile();
- InputFile inputFile = new DefaultInputFile("src/main/java/Foo.java")
- .setFile(file)
- .setType(InputFile.Type.MAIN)
+ InputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java")
.setSourceDirAbsolutePath(new File(basedir, "src/main/java").getAbsolutePath())
- .setPathRelativeToSourceDir("Foo.java");
+ .setPathRelativeToSourceDir("Foo.java")
+ .setFile(file)
+ .setType(InputFile.Type.MAIN);
when(filter.accept(eq(file), any(DeprecatedFileFilters.DeprecatedContext.class))).thenReturn(false);
assertThat(filters.accept(inputFile)).isFalse();
assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isFalse();
}
-
@Test
public void match_at_least_one_inclusion() throws IOException {
Settings settings = new Settings();
import org.junit.Test;
import org.mockito.Mockito;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.AnalysisMode;
AnalysisMode analysisMode = mock(AnalysisMode.class);
InputFileBuilderFactory factory = new InputFileBuilderFactory(
- project, pathResolver, langDetectionFactory,
+ project, ProjectDefinition.create(), pathResolver, langDetectionFactory,
statusDetectionFactory, analysisMode);
InputFileBuilder builder = factory.create(fs);
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.PathUtils;
import org.sonar.batch.bootstrap.AnalysisMode;
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
langDetection, statusDetection, fs, analysisMode);
- DefaultInputFile inputFile = builder.create(srcFile);
+ DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
assertThat(inputFile.type()).isEqualTo(InputFile.Type.MAIN);
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
langDetection, statusDetection, fs, analysisMode);
- DefaultInputFile inputFile = builder.create(srcFile);
+ DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
assertThat(inputFile).isNull();
}
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
langDetection, statusDetection, fs, analysisMode);
- DefaultInputFile inputFile = builder.create(srcFile);
+ DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
assertThat(inputFile).isNull();
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
langDetection, statusDetection, fs, analysisMode);
- DefaultInputFile inputFile = builder.create(srcFile);
+ DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
assertThat(inputFile.pathRelativeToSourceDir()).isEqualTo("foo/Bar.java");
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
langDetection, statusDetection, fs, analysisMode);
- DefaultInputFile inputFile = builder.create(srcFile);
+ DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
assertThat(inputFile.pathRelativeToSourceDir()).isEqualTo("foo/Bar.php");
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.RelativePathIndex;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.batch.index.Caches;
import org.sonar.batch.index.CachesTest;
import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
public class InputFileCacheTest {
InputFileCache cache = new InputFileCache(caches);
DefaultInputFile fooFile = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile("Foo.java"));
cache.put("struts", fooFile);
- cache.put("struts-core", new DefaultInputFile("src/main/java/Bar.java").setFile(temp.newFile("Bar.java")));
+ cache.put("struts-core", new DeprecatedDefaultInputFile("src/main/java/Bar.java").setFile(temp.newFile("Bar.java")));
- // index by relative path is automatically fed
- assertThat(cache.get("struts", RelativePathIndex.ID, "src/main/java/Foo.java").relativePath())
+ assertThat(cache.get("struts", "src/main/java/Foo.java").relativePath())
.isEqualTo("src/main/java/Foo.java");
assertThat(cache.byModule("struts")).hasSize(1);
assertThat(cache.all()).hasSize(1);
}
- @Test
- public void only_relative_path_index_is_supported() throws Exception {
- InputFileCache cache = new InputFileCache(caches);
- DefaultInputFile input = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile("Foo.java"));
-
- try {
- cache.index("struts", "unsupported-index", "index-value", input);
- fail();
- } catch (UnsupportedOperationException e) {
- assertThat(e).hasMessage("Only relative path index is supported yet");
- }
-
- try {
- cache.get("struts", "unsupported-index", "index-value");
- fail();
- } catch (UnsupportedOperationException e) {
- assertThat(e).hasMessage("Only relative path index is supported yet");
- }
- }
}
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.Languages;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
import static org.fest.assertions.Assertions.assertThat;
public class LanguageDetectionFactoryTest {
@Test
public void testCreate() throws Exception {
- Languages languages = new Languages(Java.INSTANCE);
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(Java.INSTANCE));
LanguageDetectionFactory factory = new LanguageDetectionFactory(new Settings(), languages);
LanguageDetection languageDetection = factory.create();
assertThat(languageDetection).isNotNull();
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
import java.io.File;
import java.io.IOException;
@Test
public void search_by_file_extension() throws Exception {
- Languages languages = new Languages(new MockLanguage("java", "java", "jav"), new MockLanguage("cobol", "cbl", "cob"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java", "jav"), new MockLanguage("cobol", "cbl", "cob")));
LanguageDetection detection = new LanguageDetection(new Settings(), languages);
assertThat(detection.language(newInputFile("Foo.java"))).isEqualTo("java");
@Test
public void should_not_fail_if_no_language() throws Exception {
- LanguageDetection detection = spy(new LanguageDetection(new Settings(), new Languages()));
+ LanguageDetection detection = spy(new LanguageDetection(new Settings(), new DeprecatedLanguagesReferential(new Languages())));
assertThat(detection.language(newInputFile("Foo.java"))).isNull();
}
@Test
public void plugin_can_declare_a_file_extension_twice_for_case_sensitivity() throws Exception {
- Languages languages = new Languages(new MockLanguage("abap", "abap", "ABAP"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("abap", "abap", "ABAP")));
LanguageDetection detection = new LanguageDetection(new Settings(), languages);
assertThat(detection.language(newInputFile("abc.abap"))).isEqualTo("abap");
public void language_with_no_extension() throws Exception {
// abap does not declare any file extensions.
// When analyzing an ABAP project, then all source files must be parsed.
- Languages languages = new Languages(new MockLanguage("java", "java"), new MockLanguage("abap"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java"), new MockLanguage("abap")));
// No side-effect on non-ABAP projects
LanguageDetection detection = new LanguageDetection(new Settings(), languages);
@Test
public void force_language_using_deprecated_property() throws Exception {
- Languages languages = new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php")));
Settings settings = new Settings();
settings.setProperty(CoreProperties.PROJECT_LANGUAGE_PROPERTY, "java");
thrown.expect(MessageException.class);
thrown.expectMessage("No language is installed with key 'unknown'. Please update property 'sonar.language'");
- Languages languages = new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php")));
Settings settings = new Settings();
settings.setProperty(CoreProperties.PROJECT_LANGUAGE_PROPERTY, "unknown");
new LanguageDetection(settings, languages);
@Test
public void fail_if_conflicting_language_suffix() throws Exception {
- Languages languages = new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml")));
LanguageDetection detection = new LanguageDetection(new Settings(), languages);
try {
detection.language(newInputFile("abc.xhtml"));
@Test
public void solve_conflict_using_filepattern() throws Exception {
- Languages languages = new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml")));
Settings settings = new Settings();
settings.setProperty("sonar.lang.patterns.xml", "xml/**");
@Test
public void fail_if_conflicting_filepattern() throws Exception {
- Languages languages = new Languages(new MockLanguage("abap", "abap"), new MockLanguage("cobol", "cobol"));
+ LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("abap", "abap"), new MockLanguage("cobol", "cobol")));
Settings settings = new Settings();
settings.setProperty("sonar.lang.patterns.abap", "*.abap,*.txt");
settings.setProperty("sonar.lang.patterns.cobol", "*.cobol,*.txt");
import org.skyscreamer.jsonassert.JSONAssert;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
mode = mock(AnalysisMode.class);
when(mode.isPreview()).thenReturn(true);
userFinder = mock(UserFinder.class);
- DefaultInputFile inputFile = new DefaultInputFile("src/main/java/org/apache/struts/Action.java");
+ DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/org/apache/struts/Action.java");
inputFile.setKey("struts:src/main/java/org/apache/struts/Action.java");
inputFile.setStatus(InputFile.Status.CHANGED);
InputFileCache fileCache = mock(InputFileCache.class);
--- /dev/null
+sonar.projectKey=com.foo.project
+sonar.projectName=Foo Project
+sonar.projectVersion=1.0-SNAPSHOT
+sonar.projectDescription=Description of Foo Project
+
+sonar.sources=sources
+sonar.libraries=libs/*.txt
package org.sonar.core.component;
import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
return key;
}
+ public static String createEffectiveKey(String projectKey, InputFile inputFile) {
+ // not a project nor a library
+ return new StringBuilder(ResourceModel.KEY_SIZE)
+ .append(projectKey)
+ .append(':')
+ .append(inputFile.relativePath())
+ .toString();
+ }
+
/**
* <p>Test if given parameter is valid for a project/module. Valid format is:</p>
* <ul>
import org.sonar.api.resources.Project;
import org.sonar.api.utils.AnnotationUtils;
import org.sonar.api.utils.dag.DirectAcyclicGraph;
+import org.sonar.batch.api.analyzer.Analyzer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public Collection<MavenPluginHandler> selectMavenPluginHandlers(Project project) {
List<DependsUponMavenPlugin> selectedExtensions = Lists.newArrayList();
- for (BatchExtension extension : getExtensions()) {
+ for (Object extension : getExtensions()) {
if (ClassUtils.isAssignable(extension.getClass(), DependsUponMavenPlugin.class)) {
selectedExtensions.add((DependsUponMavenPlugin) extension);
}
return handlers;
}
- protected List<BatchExtension> getExtensions() {
- List<BatchExtension> extensions = Lists.newArrayList();
+ protected List<Object> getExtensions() {
+ List<Object> extensions = Lists.newArrayList();
completeBatchExtensions(componentContainer, extensions);
return extensions;
}
- private static void completeBatchExtensions(ComponentContainer container, List<BatchExtension> extensions) {
+ private static void completeBatchExtensions(ComponentContainer container, List<Object> extensions) {
if (container != null) {
extensions.addAll(container.getComponentsByType(BatchExtension.class));
+ extensions.addAll(container.getComponentsByType(org.sonar.batch.api.BatchExtension.class));
completeBatchExtensions(container.getParent(), extensions);
}
}
private <T> List<T> getFilteredExtensions(Class<T> type, Project project) {
List<T> result = Lists.newArrayList();
- for (BatchExtension extension : getExtensions()) {
+ for (Object extension : getExtensions()) {
if (shouldKeep(type, extension, project)) {
result.add((T) extension);
}
/**
* Extension dependencies
*/
- private <T> List getDependencies(T extension) {
- return evaluateAnnotatedClasses(extension, DependsUpon.class);
+ private <T> List<Object> getDependencies(T extension) {
+ List<Object> result = new ArrayList<Object>();
+ result.addAll(evaluateAnnotatedClasses(extension, DependsUpon.class));
+ if (ClassUtils.isAssignable(extension.getClass(), Analyzer.class)) {
+ result.addAll(Arrays.asList(((Analyzer) extension).describe().dependsOn()));
+ }
+ return result;
}
/**
* Objects that depend upon this extension.
*/
- public <T> List getDependents(T extension) {
- return evaluateAnnotatedClasses(extension, DependedUpon.class);
+ public <T> List<Object> getDependents(T extension) {
+ List<Object> result = new ArrayList<Object>();
+ result.addAll(evaluateAnnotatedClasses(extension, DependedUpon.class));
+ if (ClassUtils.isAssignable(extension.getClass(), Analyzer.class)) {
+ result.addAll(Arrays.asList(((Analyzer) extension).describe().provides()));
+ }
+ return result;
}
private void completePhaseDependencies(DirectAcyclicGraph dag, Object extension) {
}
}
- protected List evaluateAnnotatedClasses(Object extension, Class<? extends Annotation> annotation) {
+ protected List<Object> evaluateAnnotatedClasses(Object extension, Class<? extends Annotation> annotation) {
List<Object> results = Lists.newArrayList();
Class aClass = extension.getClass();
while (aClass != null) {
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-check-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-batch-plugin-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-colorizer</artifactId>
/**
* Define instantiation strategy of batch extensions. If an extension is not annotated, then default value
* is {@link org.sonar.api.batch.InstantiationStrategy#PER_PROJECT}.
+ * @since 4.4
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
import javax.annotation.CheckForNull;
+import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* Find a project measure
*/
- Measure getMeasure(Metric metric);
+ <G extends Serializable> Measure<G> getMeasure(Metric<G> metric);
/**
* All measures of the project. Never return null.
/**
* Find a measure for this project
*/
- Measure getMeasure(Resource resource, Metric metric);
+ <G extends Serializable> Measure<G> getMeasure(Resource resource, Metric<G> metric);
/**
* Key is updated when saving the resource.
import org.sonar.api.design.Dependency;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
public abstract Resource addResource(Resource resource);
@CheckForNull
- public abstract Measure getMeasure(Resource resource, Metric metric);
+ public abstract Measure getMeasure(Resource resource, org.sonar.batch.api.measures.Metric<?> metric);
@CheckForNull
public abstract <M> M getMeasures(Resource resource, MeasuresFilter<M> filter);
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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);
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.util.Collection;
-
-/**
- * Factory of {@link org.sonar.api.batch.fs.FilePredicate}
- *
- * @since 4.2
- */
-public interface FilePredicates {
- /**
- * Returns a predicate that always evaluates to true
- */
- FilePredicate all();
-
- /**
- * Returns a predicate that always evaluates to false
- */
- FilePredicate none();
-
- /**
- * Warning - not efficient because absolute path is not indexed yet.
- */
- FilePredicate hasAbsolutePath(String s);
-
- /**
- * TODO document that non-normalized path and Windows-style path are supported
- */
- FilePredicate hasRelativePath(String s);
-
- FilePredicate matchesPathPattern(String inclusionPattern);
-
- FilePredicate matchesPathPatterns(String[] inclusionPatterns);
-
- FilePredicate doesNotMatchPathPattern(String exclusionPattern);
-
- FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns);
-
- FilePredicate hasPath(String s);
-
- FilePredicate is(File ioFile);
-
- FilePredicate hasLanguage(String language);
-
- FilePredicate hasLanguages(Collection<String> languages);
-
- FilePredicate hasStatus(InputFile.Status status);
-
- FilePredicate hasType(InputFile.Type type);
-
- FilePredicate not(FilePredicate p);
-
- FilePredicate or(Collection<FilePredicate> or);
-
- FilePredicate or(FilePredicate... or);
-
- FilePredicate or(FilePredicate first, FilePredicate second);
-
- FilePredicate and(Collection<FilePredicate> and);
-
- FilePredicate and(FilePredicate... and);
-
- FilePredicate and(FilePredicate first, FilePredicate second);
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.SortedSet;
-
-/**
- * The {@link FileSystem} manages all the source files to be analyzed.
- * <p/>
- * This is not an extension point so it must not be implemented by plugins. It must be injected as a
- * constructor parameter :
- * <pre>
- * public class MySensor implements Sensor {
- * private final FileSystem fs;
- *
- * public MySensor(FileSystem fs) {
- * this.fs = fs;
- * }
- * }
- * </pre>
- *
- * <h2>How to use in unit tests</h2>
- * 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.batch.fs.internal.DefaultInputFile},
- * for example :
- * <pre>
- * DefaultFileSystem fs = new DefaultFileSystem();
- * fs.add(new DefaultInputFile("src/foo/bar.php"));
- * </pre>
- *
- * @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.
- * <p/>
- * The work directory can be located outside {@link #baseDir()}.
- */
- File workDir();
-
- /**
- * Factory of {@link FilePredicate}
- */
- FilePredicates predicates();
-
- /**
- * Returns the single element matching the predicate. If more than one elements match
- * the predicate, then {@link IllegalArgumentException} is thrown. Returns {@code null}
- * if no files match.
- *
- * <p/>
- * How to use :
- * <pre>
- * InputFile file = fs.inputFile(fs.predicates().hasRelativePath("src/Foo.php"));
- * </pre>
- *
- * @see #predicates()
- */
- @CheckForNull
- InputFile inputFile(FilePredicate predicate);
-
- /**
- * Input files matching the given attributes. Return all the files if the parameter
- * <code>attributes</code> is empty.
- * <p/>
- * <b>Important</b> - result is an {@link java.lang.Iterable} to benefit from streaming and decreasing
- * memory consumption. It should be iterated only once, else copy it into a list :
- * {@code com.google.common.collect.Lists.newArrayList(inputFiles(predicate))}
- * <p/>
- * How to use :
- * <pre>
- * FilePredicates p = fs.predicates();
- * Iterable<InputFile> files = fs.inputFiles(p.and(p.hasLanguage("java"), p.hasType(InputFile.Type.MAIN)));
- * </pre>
- *
- * @see #predicates()
- */
- Iterable<InputFile> inputFiles(FilePredicate predicate);
-
- /**
- * Returns true if at least one {@link org.sonar.api.batch.fs.InputFile} matches
- * the given predicate. This method can be faster than checking if {@link #inputFiles(org.sonar.api.batch.fs.FilePredicate)}
- * has elements.
- * @see #predicates()
- */
- boolean hasFiles(FilePredicate predicate);
-
- /**
- * Files matching the given predicate.
- * @see #predicates()
- */
- Iterable<File> files(FilePredicate predicate);
-
- /**
- * Languages detected in all files, whatever their type (main or test)
- */
- SortedSet<String> languages();
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 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 <code>{@link FileSystem}</code>. File separator is the forward
- * slash ('/'), even on Microsoft Windows.
- * <p/>
- * Returns <code>src/main/java/com/Foo.java</code> if module base dir is
- * <code>/path/to/module</code> and if file is
- * <code>/path/to/module/src/main/java/com/Foo.java</code>.
- * <p/>
- * 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.
- * <p/>
- * 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 if it is not
- * set in project settings.
- */
- String language();
-
- /**
- * Does it contain main or test code ?
- */
- Type type();
-
- /**
- * Status regarding previous analysis
- */
- Status status();
-
- /**
- * Number of physical lines. This method supports all end-of-line characters. Returns
- * zero if the file is empty.
- */
- int lines();
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 exclude some files from inspection
- * @since 4.2
- */
-public interface InputFileFilter extends BatchExtension {
-
- // TODO requires a context (FileSystem) ?
- boolean accept(InputFile f);
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.apache.commons.io.FilenameUtils;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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());
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.util.Collection;
-
-/**
- * @since 4.2
- */
-class AndPredicate implements FilePredicate {
-
- private final Collection<FilePredicate> predicates;
-
- AndPredicate(Collection<FilePredicate> predicates) {
- this.predicates = predicates;
- }
-
- @Override
- public boolean apply(InputFile f) {
- for (FilePredicate predicate : predicates) {
- if (!predicate.apply(f)) {
- return false;
- }
- }
- return true;
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.collect.Lists;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.InputFile;
-
-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 DefaultFilePredicates implements FilePredicates {
- /**
- * Client code should use {@link org.sonar.api.batch.fs.FileSystem#predicates()} to get an instance
- */
- DefaultFilePredicates() {
- }
-
- /**
- * Returns a predicate that always evaluates to true
- */
- public FilePredicate all() {
- return TruePredicate.TRUE;
- }
-
- /**
- * Returns a predicate that always evaluates to false
- */
- public FilePredicate none() {
- return FalsePredicate.FALSE;
- }
-
- /**
- * Warning - not efficient because absolute path is not indexed yet.
- */
- public FilePredicate hasAbsolutePath(String s) {
- return new AbsolutePathPredicate(s);
- }
-
- /**
- * TODO document that non-normalized path and Windows-style path are supported
- */
- public FilePredicate hasRelativePath(String s) {
- return new RelativePathPredicate(s);
- }
-
- public FilePredicate matchesPathPattern(String inclusionPattern) {
- return new PathPatternPredicate(PathPattern.create(inclusionPattern));
- }
-
- public FilePredicate matchesPathPatterns(String[] inclusionPatterns) {
- if (inclusionPatterns.length == 0) {
- return TruePredicate.TRUE;
- }
- FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length];
- for (int i = 0; i < inclusionPatterns.length; i++) {
- predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i]));
- }
- return or(predicates);
- }
-
- public FilePredicate doesNotMatchPathPattern(String exclusionPattern) {
- return not(matchesPathPattern(exclusionPattern));
- }
-
- public FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) {
- if (exclusionPatterns.length == 0) {
- return TruePredicate.TRUE;
- }
- return not(matchesPathPatterns(exclusionPatterns));
- }
-
- public FilePredicate hasPath(String s) {
- File file = new File(s);
- if (file.isAbsolute()) {
- return hasAbsolutePath(s);
- }
- return hasRelativePath(s);
- }
-
- public FilePredicate is(File ioFile) {
- if (ioFile.isAbsolute()) {
- return hasAbsolutePath(ioFile.getAbsolutePath());
- }
- return hasRelativePath(ioFile.getPath());
- }
-
- public FilePredicate hasLanguage(String language) {
- return new LanguagePredicate(language);
- }
-
- public FilePredicate hasLanguages(Collection<String> languages) {
- List<FilePredicate> list = Lists.newArrayList();
- for (String language : languages) {
- list.add(hasLanguage(language));
- }
- return or(list);
- }
-
- public FilePredicate hasStatus(InputFile.Status status) {
- return new StatusPredicate(status);
- }
-
- public FilePredicate hasType(InputFile.Type type) {
- return new TypePredicate(type);
- }
-
- public FilePredicate not(FilePredicate p) {
- return new NotPredicate(p);
- }
-
- public FilePredicate or(Collection<FilePredicate> or) {
- return new OrPredicate(or);
- }
-
- public FilePredicate or(FilePredicate... or) {
- return new OrPredicate(Arrays.asList(or));
- }
-
- public FilePredicate or(FilePredicate first, FilePredicate second) {
- return new OrPredicate(Arrays.asList(first, second));
- }
-
- public FilePredicate and(Collection<FilePredicate> and) {
- return new AndPredicate(and);
- }
-
- public FilePredicate and(FilePredicate... and) {
- return new AndPredicate(Arrays.asList(and));
- }
-
- public FilePredicate and(FilePredicate first, FilePredicate second) {
- return new AndPredicate(Arrays.asList(first, second));
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import java.io.File;
-import java.nio.charset.Charset;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.SortedSet;
-
-/**
- * @since 4.2
- */
-public class DefaultFileSystem implements FileSystem {
-
- private final Cache cache;
- private final SortedSet<String> languages = Sets.newTreeSet();
- private File baseDir, workDir;
- private Charset encoding;
- private final FilePredicates predicates = new DefaultFilePredicates();
-
- /**
- * 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;
- }
-
- @Override
- public File baseDir() {
- return baseDir;
- }
-
- public DefaultFileSystem setEncoding(@Nullable Charset e) {
- this.encoding = e;
- return this;
- }
-
- @Override
- public Charset encoding() {
- return encoding == null ? Charset.defaultCharset() : encoding;
- }
-
- public boolean isDefaultJvmEncoding() {
- return encoding == null;
- }
-
- public DefaultFileSystem setWorkDir(File d) {
- this.workDir = d.getAbsoluteFile();
- return this;
- }
-
- @Override
- public File workDir() {
- return workDir;
- }
-
- @Override
- public InputFile inputFile(FilePredicate predicate) {
- doPreloadFiles();
- if (predicate instanceof UniqueIndexPredicate) {
- return cache.inputFile((UniqueIndexPredicate) predicate);
- }
- try {
- Iterable<InputFile> files = inputFiles(predicate);
- return Iterables.getOnlyElement(files);
- } catch (NoSuchElementException e) {
- // contrary to guava, return null if iterable is empty
- return null;
- }
- }
-
- @Override
- public Iterable<InputFile> inputFiles(FilePredicate predicate) {
- doPreloadFiles();
- return Iterables.filter(cache.inputFiles(), new GuavaPredicate(predicate));
- }
-
- @Override
- public boolean hasFiles(FilePredicate predicate) {
- doPreloadFiles();
- return Iterables.indexOf(cache.inputFiles(), new GuavaPredicate(predicate)) >= 0;
- }
-
- @Override
- public Iterable<File> files(FilePredicate predicate) {
- doPreloadFiles();
- return Iterables.transform(inputFiles(predicate), new Function<InputFile, File>() {
- @Override
- public File apply(@Nullable InputFile input) {
- return input == null ? null : input.file();
- }
- });
- }
-
- /**
- * Adds InputFile to the list and registers its language, if present.
- */
- public DefaultFileSystem add(InputFile inputFile) {
- cache.add(inputFile);
- if (inputFile.language() != null) {
- languages.add(inputFile.language());
- }
- return this;
- }
-
- /**
- * Adds a language to the list. To be used only for unit tests that need to use {@link #languages()} without
- * using {@link #add(org.sonar.api.batch.fs.InputFile)}.
- */
- public DefaultFileSystem addLanguages(String language, String... others) {
- languages.add(language);
- Collections.addAll(languages, others);
- return this;
- }
-
- @Override
- public SortedSet<String> languages() {
- doPreloadFiles();
- return languages;
- }
-
- @Override
- public FilePredicates predicates() {
- return predicates;
- }
-
- /**
- * This method is called before each search of files.
- */
- protected void doPreloadFiles() {
- // nothing to do by default
- }
-
- public static abstract class Cache {
- protected abstract Iterable<InputFile> 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<InputFile> files = Lists.newArrayList();
- private final Map<String, Map<Object, InputFile>> fileMap = Maps.newHashMap();
-
- @Override
- public Iterable<InputFile> inputFiles() {
- return Lists.newArrayList(files);
- }
-
- @Override
- public InputFile inputFile(UniqueIndexPredicate predicate) {
- Map<Object, InputFile> byAttr = fileMap.get(predicate.indexId());
- if (byAttr != null) {
- return byAttr.get(predicate.value());
- }
- return null;
- }
-
- @Override
- protected void doAdd(InputFile inputFile) {
- files.add(inputFile);
- }
-
- @Override
- protected void doIndex(String indexId, Object value, InputFile inputFile) {
- Map<Object, InputFile> attrValues = fileMap.get(indexId);
- if (attrValues == null) {
- attrValues = Maps.newHashMap();
- fileMap.put(indexId, attrValues);
- }
- attrValues.put(value, inputFile);
- }
- }
-
- private static class GuavaPredicate implements Predicate<InputFile> {
- private final FilePredicate predicate;
-
- private GuavaPredicate(FilePredicate predicate) {
- this.predicate = predicate;
- }
-
- @Override
- public boolean apply(@Nullable InputFile input) {
- return input != null && predicate.apply(input);
- }
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.apache.commons.io.FilenameUtils;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.utils.PathUtils;
-
-import javax.annotation.CheckForNull;
-import java.io.*;
-
-/**
- * @since 4.2
- */
-public class DefaultInputFile implements InputFile, org.sonar.api.resources.InputFile, Serializable {
-
- private final String relativePath;
- private String absolutePath;
- private String language;
- private Type type = Type.MAIN;
- private Status status;
- private String hash;
- private int lines;
- private String key;
- private String deprecatedKey;
- private String sourceDirAbsolutePath;
- private String pathRelativeToSourceDir;
- private String basedir;
-
- public DefaultInputFile(String relativePath) {
- this.relativePath = FilenameUtils.normalize(relativePath, true);
- }
-
- @Override
- public String relativePath() {
- return relativePath;
- }
-
- /**
- * Marked as nullable just for the unit tests that do not call {@link #setFile(java.io.File)}
- * previously.
- */
- @Override
- @CheckForNull
- public String absolutePath() {
- return absolutePath;
- }
-
- @Override
- public File file() {
- if (absolutePath == null) {
- throw new IllegalStateException("Can not return the java.io.File because absolute path is not set (see method setFile(java.io.File))");
- }
- return new File(absolutePath);
- }
-
- /**
- * Marked as nullable just for the unit tests that do not call {@link #setLanguage(String)}
- * previously.
- */
- @CheckForNull
- @Override
- public String language() {
- return language;
- }
-
- @Override
- public Type type() {
- return type;
- }
-
- /**
- * Marked as nullable just for the unit tests that do not previously call
- * {@link #setStatus(org.sonar.api.batch.fs.InputFile.Status)}
- */
- @CheckForNull
- @Override
- public Status status() {
- return status;
- }
-
- /**
- * Digest hash of the file. Marked as nullable just for the unit tests
- * that do not previously call {@link #setHash(String)}
- */
- @CheckForNull
- public String hash() {
- return hash;
- }
-
- @Override
- public int lines() {
- return lines;
- }
-
- /**
- * Component key. It's marked as nullable just for the unit tests that
- * do not previously call {@link #setKey(String)}.
- */
- @CheckForNull
- public String key() {
- return key;
- }
-
- public DefaultInputFile setAbsolutePath(String s) {
- this.absolutePath = FilenameUtils.normalize(s, true);
- return this;
- }
-
- public DefaultInputFile setLanguage(String language) {
- this.language = language;
- return this;
- }
-
- public DefaultInputFile setFile(File file) {
- setAbsolutePath(file.getAbsolutePath());
- return this;
- }
-
- public DefaultInputFile setType(Type type) {
- this.type = type;
- return this;
- }
-
- public DefaultInputFile setStatus(Status status) {
- this.status = status;
- return this;
- }
-
- public DefaultInputFile setHash(String hash) {
- this.hash = hash;
- return this;
- }
-
- public DefaultInputFile setLines(int lines) {
- this.lines = lines;
- return this;
- }
-
- public DefaultInputFile setKey(String s) {
- this.key = s;
- return this;
- }
-
- /**
- * Key used before version 4.2. It can be different than {@link #key} on Java files.
- */
- public String deprecatedKey() {
- return deprecatedKey;
- }
-
- public DefaultInputFile setDeprecatedKey(String s) {
- this.deprecatedKey = s;
- return this;
- }
-
- /**
- * Used only for backward-compatibility. Meaningless since version 4.2.
- */
- public String sourceDirAbsolutePath() {
- return sourceDirAbsolutePath;
- }
-
- public DefaultInputFile setSourceDirAbsolutePath(String s) {
- this.sourceDirAbsolutePath = FilenameUtils.normalize(s, true);
- return this;
- }
-
- /**
- * Used only for backward-compatibility. Meaningless since version 4.2.
- */
-
- public String pathRelativeToSourceDir() {
- return pathRelativeToSourceDir;
- }
-
- public DefaultInputFile setPathRelativeToSourceDir(String s) {
- this.pathRelativeToSourceDir = FilenameUtils.normalize(s, true);
- return this;
- }
-
- /**
- * @deprecated in 4.2. Replaced by {@link org.sonar.api.batch.fs.FileSystem#baseDir()}
- */
- @Deprecated
- @Override
- public File getFileBaseDir() {
- return new File(basedir);
- }
-
- public void setBasedir(File basedir) {
- this.basedir = PathUtils.sanitize(basedir.getAbsolutePath());
- }
-
- /**
- * @deprecated in 4.2. Use {@link #file()}
- */
- @Deprecated
- @Override
- public File getFile() {
- return file();
- }
-
- /**
- * @deprecated in 4.2. Use {@link #relativePath()}
- */
- @Deprecated
- @Override
- public String getRelativePath() {
- return pathRelativeToSourceDir;
- }
-
- @Override
- public InputStream getInputStream() throws FileNotFoundException {
- return new BufferedInputStream(new FileInputStream(file()));
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- DefaultInputFile that = (DefaultInputFile) o;
- return relativePath.equals(that.relativePath);
- }
-
- @Override
- public int hashCode() {
- return relativePath.hashCode();
- }
-
- @Override
- public String toString() {
- return "[relative=" + relativePath + ", abs=" + absolutePath + "]";
- }
-}
-
-
-
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 org.sonar.batch.api.internal.FilenameUtils;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+/**
+ * @since 4.2
+ */
+public class DeprecatedDefaultInputFile extends DefaultInputFile implements org.sonar.api.resources.InputFile {
+
+ private String basedir;
+ private String deprecatedKey;
+ private String sourceDirAbsolutePath;
+ private String pathRelativeToSourceDir;
+
+ public DeprecatedDefaultInputFile(String relativePath) {
+ super(relativePath);
+ }
+
+ /**
+ * @deprecated in 4.2. Replaced by {@link org.sonar.api.batch.fs.FileSystem#baseDir()}
+ */
+ @Deprecated
+ @Override
+ public File getFileBaseDir() {
+ return new File(basedir);
+ }
+
+ public void setBasedir(File basedir) {
+ this.basedir = FilenameUtils.normalize(basedir.getAbsolutePath());
+ }
+
+ /**
+ * @deprecated in 4.2. Use {@link #file()}
+ */
+ @Deprecated
+ @Override
+ public File getFile() {
+ return file();
+ }
+
+ /**
+ * @deprecated in 4.2. Use {@link #relativePath()}
+ */
+ @Deprecated
+ @Override
+ public String getRelativePath() {
+ return pathRelativeToSourceDir;
+ }
+
+ /**
+ * Key used before version 4.2. It can be different than {@link #key} on Java files.
+ */
+ public String deprecatedKey() {
+ return deprecatedKey;
+ }
+
+ public DeprecatedDefaultInputFile setDeprecatedKey(String s) {
+ this.deprecatedKey = s;
+ return this;
+ }
+
+ /**
+ * Used only for backward-compatibility. Meaningless since version 4.2.
+ */
+ public String sourceDirAbsolutePath() {
+ return sourceDirAbsolutePath;
+ }
+
+ public DeprecatedDefaultInputFile setSourceDirAbsolutePath(String s) {
+ this.sourceDirAbsolutePath = FilenameUtils.normalize(s);
+ return this;
+ }
+
+ /**
+ * Used only for backward-compatibility. Meaningless since version 4.2.
+ */
+
+ public String pathRelativeToSourceDir() {
+ return pathRelativeToSourceDir;
+ }
+
+ public DeprecatedDefaultInputFile setPathRelativeToSourceDir(String s) {
+ this.pathRelativeToSourceDir = FilenameUtils.normalize(s);
+ return this;
+ }
+
+ @Override
+ public InputStream getInputStream() throws FileNotFoundException {
+ return new BufferedInputStream(new FileInputStream(file()));
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-class FalsePredicate implements FilePredicate {
-
- static final FilePredicate FALSE = new FalsePredicate();
-
- @Override
- public boolean apply(InputFile inputFile) {
- return false;
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.collect.ImmutableList;
-import org.sonar.api.batch.fs.InputFile;
-
-import javax.annotation.CheckForNull;
-import java.util.List;
-
-// Accepted to support both InputFile and InputDir as long as indexes are on the same attributes
-public interface FileIndex {
-
- // Currently only a single index is supported
- List<FileIndex> ALL = ImmutableList.<FileIndex>of(new RelativePathIndex());
-
- @CheckForNull
- Object valueOf(InputFile f);
-
- String id();
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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());
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * @since 4.2
- */
-class OrPredicate implements FilePredicate {
-
- private final Collection<FilePredicate> predicates;
-
- OrPredicate(Collection<FilePredicate> predicates) {
- if (predicates.isEmpty()) {
- this.predicates = Arrays.asList(TruePredicate.TRUE);
- } else {
- this.predicates = predicates;
- }
- }
-
- @Override
- public boolean apply(InputFile f) {
- for (FilePredicate predicate : predicates) {
- if (predicate.apply(f)) {
- return true;
- }
- }
- return false;
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.utils.WildcardPattern;
-
-public abstract class PathPattern {
-
- final WildcardPattern pattern;
-
- PathPattern(String pattern) {
- this.pattern = WildcardPattern.create(pattern);
- }
-
- public abstract boolean match(InputFile inputFile);
-
- public abstract boolean match(InputFile inputFile, boolean caseSensitiveFileExtension);
-
- public static PathPattern create(String s) {
- String trimmed = StringUtils.trim(s);
- if (StringUtils.startsWithIgnoreCase(trimmed, "file:")) {
- return new AbsolutePathPattern(StringUtils.substring(trimmed, "file:".length()));
- }
- return new RelativePathPattern(trimmed);
- }
-
- public static PathPattern[] create(String[] s) {
- PathPattern[] result = new PathPattern[s.length];
- for (int i = 0; i < s.length; i++) {
- result[i] = create(s[i]);
- }
- return result;
- }
-
- private static class AbsolutePathPattern extends PathPattern {
- private AbsolutePathPattern(String pattern) {
- super(pattern);
- }
-
- @Override
- public boolean match(InputFile inputFile) {
- return match(inputFile, true);
- }
-
- @Override
- public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
- String path = inputFile.absolutePath();
- if (!caseSensitiveFileExtension) {
- String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
- if (StringUtils.isNotBlank(extension)) {
- path = StringUtils.removeEndIgnoreCase(path, extension);
- path = path + extension;
- }
- }
- return pattern.match(path);
- }
-
- @Override
- public String toString() {
- return "file:" + pattern.toString();
- }
- }
-
- /**
- * Path relative to module basedir
- */
- private static class RelativePathPattern extends PathPattern {
- private RelativePathPattern(String pattern) {
- super(pattern);
- }
-
- @Override
- public boolean match(InputFile inputFile) {
- return match(inputFile, true);
- }
-
- @Override
- public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
- String path = inputFile.relativePath();
- if (!caseSensitiveFileExtension) {
- String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
- if (StringUtils.isNotBlank(extension)) {
- path = StringUtils.removeEndIgnoreCase(path, extension);
- path = path + extension;
- }
- }
- return path != null && pattern.match(path);
- }
-
- @Override
- public String toString() {
- return pattern.toString();
- }
- }
-
- static String sanitizeExtension(String suffix) {
- return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-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);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.InputFile;
-
-/**
- * @since 4.2
- */
-public class RelativePathIndex implements FileIndex {
- public static final String ID = "rel";
-
- @Override
- public Object valueOf(InputFile f) {
- return f.relativePath();
- }
-
- @Override
- public String id() {
- return ID;
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.apache.commons.io.FilenameUtils;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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;
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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();
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-class TruePredicate implements FilePredicate {
-
- static final FilePredicate TRUE = new TruePredicate();
-
- @Override
- public boolean apply(InputFile inputFile) {
- return true;
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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();
- }
-
-}
-
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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;
-
-/**
- * @since 4.2
- */
-public interface UniqueIndexPredicate {
-
- String indexId();
-
- Object value();
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.batch.fs.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.batch.fs;
-
-import javax.annotation.ParametersAreNonnullByDefault;
public static String DOMAIN_TECHNICAL_DEBT = "Technical Debt";
public static final String LINES_KEY = "lines";
- public static final Metric LINES = new Metric.Builder(LINES_KEY, "Lines", Metric.ValueType.INT)
+ public static final Metric<Integer> LINES = new Metric.Builder(LINES_KEY, "Lines", Metric.ValueType.INT)
.setDescription("Lines")
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(false)
*
* @since 1.10
*/
-public class Measure implements Serializable {
+public class Measure<G extends Serializable> implements Serializable {
private static final String INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5 = "Index should be in range from 1 to 5";
protected static final int MAX_TEXT_SIZE = 96;
public static final int DEFAULT_PRECISION = 1;
protected String metricKey;
- protected Metric metric;
+ protected Metric<G> metric;
protected Double value;
protected String data;
protected String description;
return value;
}
+ /**
+ * For internal use.
+ */
+ public G value() {
+ switch (getMetric().getType()) {
+ case BOOL:
+ return (G) Boolean.valueOf(1.0 == value);
+ case INT:
+ case MILLISEC:
+ return (G) Integer.valueOf(value.intValue());
+ case FLOAT:
+ case PERCENT:
+ case RATING:
+ return (G) value;
+ case STRING:
+ case LEVEL:
+ case DATA:
+ case DISTRIB:
+ return (G) getData();
+ case WORK_DUR:
+ return (G) Long.valueOf(value.longValue());
+ default:
+ if (getMetric().isNumericType()) {
+ return (G) getValue();
+ } else if (getMetric().isDataType()) {
+ return (G) getData();
+ } else {
+ throw new UnsupportedOperationException("Unsupported type :" + getMetric().getType());
+ }
+ }
+ }
+
/**
* @return the value of the measure as an int
*/
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
+
}
};
}
- public static MeasuresFilter<Measure> metric(final Metric metric) {
- return metric(metric.getKey());
+ public static MeasuresFilter<Measure> metric(final org.sonar.batch.api.measures.Metric<?> metric) {
+ return metric(metric.key());
}
public static MeasuresFilter<Measure> metric(final String metricKey) {
@Table(name = "metrics")
@Entity(name = "Metric")
@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
-public class Metric implements ServerExtension, BatchExtension, Serializable {
+public class Metric<G extends Serializable> implements ServerExtension, BatchExtension, Serializable, org.sonar.batch.api.measures.Metric<G> {
/**
* A metric bigger value means a degradation
public static final int DIRECTION_NONE = 0;
public enum ValueType {
- INT, FLOAT, PERCENT, BOOL, STRING, MILLISEC, DATA, LEVEL, DISTRIB, RATING, WORK_DUR
+ INT(Integer.class),
+ FLOAT(Double.class),
+ PERCENT(Double.class),
+ BOOL(Boolean.class),
+ STRING(String.class),
+ MILLISEC(Integer.class),
+ DATA(String.class),
+ LEVEL(String.class),
+ DISTRIB(String.class),
+ RATING(String.class),
+ WORK_DUR(Long.class);
+
+ private final Class measureJavaType;
+
+ private ValueType(Class measureJavaType) {
+ this.measureJavaType = measureJavaType;
+ }
+
+ private Class measureJavaType() {
+ return measureJavaType;
+ }
+
}
public enum Level {
* @param qualitative whether the metric is qualitative
* @param domain the metric domain
* @param userManaged whether the metric is user managed
- * @deprecated since 2.7 use the {@link Builder} factory.
*/
- @Deprecated
- public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, @Nullable String domain,
+ private Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, @Nullable String domain,
boolean userManaged) {
this.key = key;
this.description = description;
}
}
- /**
- * Creates a fully qualified metric. This defaults some values:
- * <ul>
- * <li>origin : Origin.JAV</li>
- * <li>enabled : true</li>
- * <li>userManaged : true</li>
- * </ul>
- *
- * @param key the metric key
- * @param name the metric name
- * @param type the metric type
- * @param direction the metric direction
- * @param qualitative whether the metric is qualitative
- * @param domain the metric domain
- * @param formula the metric formula
- * @deprecated since 2.7 use the {@link Builder} factory.
- */
- @Deprecated
- public Metric(String key, String name, ValueType type, Integer direction, Boolean qualitative, String domain, Formula formula) {
- this.key = key;
- this.name = name;
- this.type = type;
- this.direction = direction;
- this.domain = domain;
- this.qualitative = qualitative;
- this.origin = Origin.JAV;
- this.enabled = true;
- this.userManaged = false;
- this.formula = formula;
- if (ValueType.PERCENT.equals(this.type)) {
- this.bestValue = (direction == DIRECTION_BETTER ? 100.0 : 0.0);
- this.worstValue = (direction == DIRECTION_BETTER ? 0.0 : 100.0);
- }
- }
-
/**
* For internal use only
*/
*
* @return a new {@link Metric} object
*/
- public Metric create() {
+ public <G extends Serializable> Metric<G> create() {
if (ValueType.PERCENT.equals(this.type)) {
this.bestValue = (direction == DIRECTION_BETTER ? 100.0 : 0.0);
this.worstValue = (direction == DIRECTION_BETTER ? 0.0 : 100.0);
}
- return new Metric(this);
+ return new Metric<G>(this);
}
}
+
+ @Override
+ public String key() {
+ return getKey();
+ }
+
+ @Override
+ public Class<G> type() {
+ return getType().measureJavaType();
+ }
}
/**
* @since 1.10
- * @deprecated replaced by {@link org.sonar.api.scan.filesystem.ModuleFileSystem} in 3.5
+ * @deprecated since 3.5 replaced by {@link org.sonar.api.scan.filesystem.ModuleFileSystem}
*/
@Deprecated
public interface ProjectFileSystem extends BatchComponent {
public void sumChildren() {
DecoratorContext context = mock(DecoratorContext.class);
when(context.getChildrenMeasures(CoreMetrics.LINES)).thenReturn(Arrays.<Measure>asList(
- new Measure(CoreMetrics.LINES, 100.0),
- new Measure(CoreMetrics.LINES, 50.0)));
+ new Measure(CoreMetrics.LINES, 100.0),
+ new Measure(CoreMetrics.LINES, 50.0)));
create(false).decorate(null, context);
@Override
@DependedUpon
public List<Metric> generatesMetrics() {
- return Arrays.asList(CoreMetrics.LINES);
+ return Arrays.<Metric>asList(CoreMetrics.LINES);
}
@Override
import org.junit.Test;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
import java.util.Arrays;
@Test
public void setNullMetrics() {
- TimeMachineQuery query = new TimeMachineQuery(null).setMetrics(Arrays.asList(CoreMetrics.LINES));
+ TimeMachineQuery query = new TimeMachineQuery(null).setMetrics(Arrays.<Metric>asList(CoreMetrics.LINES));
assertThat(query.getMetrics()).contains(CoreMetrics.LINES);
query.unsetMetrics();
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.apache.commons.io.FilenameUtils;
-import org.fest.assertions.Assertions;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DefaultFilePredicatesTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- DefaultInputFile javaFile;
- FilePredicates predicates = new DefaultFilePredicates();
-
- @Before
- public void before() throws IOException {
- javaFile = new DefaultInputFile("src/main/java/struts/Action.java")
- .setFile(temp.newFile("Action.java"))
- .setLanguage("java")
- .setStatus(InputFile.Status.ADDED);
- }
-
- @Test
- public void all() throws Exception {
- Assertions.assertThat(predicates.all().apply(javaFile)).isTrue();
- }
-
- @Test
- public void none() throws Exception {
- assertThat(predicates.none().apply(javaFile)).isFalse();
- }
-
- @Test
- public void matches_inclusion_pattern() throws Exception {
- assertThat(predicates.matchesPathPattern("src/main/**/Action.java").apply(javaFile)).isTrue();
- assertThat(predicates.matchesPathPattern("Action.java").apply(javaFile)).isFalse();
- assertThat(predicates.matchesPathPattern("src/**/*.php").apply(javaFile)).isFalse();
- }
-
- @Test
- public void matches_inclusion_patterns() throws Exception {
- assertThat(predicates.matchesPathPatterns(new String[]{"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isTrue();
- assertThat(predicates.matchesPathPatterns(new String[]{}).apply(javaFile)).isTrue();
- assertThat(predicates.matchesPathPatterns(new String[]{"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isFalse();
- }
-
- @Test
- public void does_not_match_exclusion_pattern() throws Exception {
- assertThat(predicates.doesNotMatchPathPattern("src/main/**/Action.java").apply(javaFile)).isFalse();
- assertThat(predicates.doesNotMatchPathPattern("Action.java").apply(javaFile)).isTrue();
- assertThat(predicates.doesNotMatchPathPattern("src/**/*.php").apply(javaFile)).isTrue();
- }
-
- @Test
- public void does_not_match_exclusion_patterns() throws Exception {
- assertThat(predicates.doesNotMatchPathPatterns(new String[]{}).apply(javaFile)).isTrue();
- assertThat(predicates.doesNotMatchPathPatterns(new String[]{"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isTrue();
- assertThat(predicates.doesNotMatchPathPatterns(new String[]{"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isFalse();
- }
-
- @Test
- public void has_relative_path() throws Exception {
- assertThat(predicates.hasRelativePath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
- assertThat(predicates.hasRelativePath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
-
- // path is normalized
- assertThat(predicates.hasRelativePath("src/main/java/../java/struts/Action.java").apply(javaFile)).isTrue();
-
- assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Action.java").apply(javaFile)).isTrue();
- assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Other.java").apply(javaFile)).isFalse();
- assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\..\\struts\\Action.java").apply(javaFile)).isTrue();
- }
-
- @Test
- public void has_absolute_path() throws Exception {
- String path = javaFile.file().getAbsolutePath();
- assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
- assertThat(predicates.hasAbsolutePath(FilenameUtils.separatorsToWindows(path)).apply(javaFile)).isTrue();
-
- assertThat(predicates.hasAbsolutePath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
- assertThat(predicates.hasAbsolutePath("src/main/java/struts/Action.java").apply(javaFile)).isFalse();
- }
-
- @Test
- public void has_path() throws Exception {
- // is relative path
- assertThat(predicates.hasPath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
- assertThat(predicates.hasPath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
-
- // is absolute path
- String path = javaFile.file().getAbsolutePath();
- assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
- assertThat(predicates.hasPath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
- }
-
- @Test
- public void is_file() throws Exception {
- // relative file
- assertThat(predicates.is(new File(javaFile.relativePath())).apply(javaFile)).isTrue();
-
-
- // absolute file
- assertThat(predicates.is(javaFile.file()).apply(javaFile)).isTrue();
- assertThat(predicates.is(javaFile.file().getAbsoluteFile()).apply(javaFile)).isTrue();
- assertThat(predicates.is(javaFile.file().getCanonicalFile()).apply(javaFile)).isTrue();
- assertThat(predicates.is(new File(javaFile.file().toURI())).apply(javaFile)).isTrue();
- assertThat(predicates.is(temp.newFile()).apply(javaFile)).isFalse();
- }
-
- @Test
- public void has_language() throws Exception {
- assertThat(predicates.hasLanguage("java").apply(javaFile)).isTrue();
- assertThat(predicates.hasLanguage("php").apply(javaFile)).isFalse();
- }
-
- @Test
- public void has_languages() throws Exception {
- assertThat(predicates.hasLanguages(Arrays.asList("java", "php")).apply(javaFile)).isTrue();
- assertThat(predicates.hasLanguages(Arrays.asList("cobol", "php")).apply(javaFile)).isFalse();
- assertThat(predicates.hasLanguages(Collections.<String>emptyList()).apply(javaFile)).isTrue();
- }
-
- @Test
- public void has_status() throws Exception {
- assertThat(predicates.hasStatus(InputFile.Status.ADDED).apply(javaFile)).isTrue();
- assertThat(predicates.hasStatus(InputFile.Status.CHANGED).apply(javaFile)).isFalse();
- }
-
- @Test
- public void has_type() throws Exception {
- assertThat(predicates.hasType(InputFile.Type.MAIN).apply(javaFile)).isTrue();
- assertThat(predicates.hasType(InputFile.Type.TEST).apply(javaFile)).isFalse();
- }
-
- @Test
- public void not() throws Exception {
- assertThat(predicates.not(predicates.hasType(InputFile.Type.MAIN)).apply(javaFile)).isFalse();
- assertThat(predicates.not(predicates.hasType(InputFile.Type.TEST)).apply(javaFile)).isTrue();
- }
-
- @Test
- public void and() throws Exception {
- // empty
- assertThat(predicates.and().apply(javaFile)).isTrue();
- assertThat(predicates.and(new FilePredicate[0]).apply(javaFile)).isTrue();
- assertThat(predicates.and(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
-
- // two arguments
- assertThat(predicates.and(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
- assertThat(predicates.and(predicates.all(), predicates.none()).apply(javaFile)).isFalse();
- assertThat(predicates.and(predicates.none(), predicates.all()).apply(javaFile)).isFalse();
-
- // collection
- assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
- assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isFalse();
-
- // array
- assertThat(predicates.and(new FilePredicate[]{predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
- assertThat(predicates.and(new FilePredicate[]{predicates.all(), predicates.none()}).apply(javaFile)).isFalse();
- }
-
- @Test
- public void or() throws Exception {
- // empty
- assertThat(predicates.or().apply(javaFile)).isTrue();
- assertThat(predicates.or(new FilePredicate[0]).apply(javaFile)).isTrue();
- assertThat(predicates.or(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
-
- // two arguments
- assertThat(predicates.or(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
- assertThat(predicates.or(predicates.all(), predicates.none()).apply(javaFile)).isTrue();
- assertThat(predicates.or(predicates.none(), predicates.all()).apply(javaFile)).isTrue();
- assertThat(predicates.or(predicates.none(), predicates.none()).apply(javaFile)).isFalse();
-
- // collection
- assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
- assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isTrue();
- assertThat(predicates.or(Arrays.asList(predicates.none(), predicates.none())).apply(javaFile)).isFalse();
-
- // array
- assertThat(predicates.or(new FilePredicate[]{predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
- assertThat(predicates.or(new FilePredicate[]{predicates.all(), predicates.none()}).apply(javaFile)).isTrue();
- assertThat(predicates.or(new FilePredicate[]{predicates.none(), predicates.none()}).apply(javaFile)).isFalse();
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.Charsets;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-
-import java.io.File;
-import java.nio.charset.Charset;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DefaultFileSystemTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Test
- public void test_directories() throws Exception {
- DefaultFileSystem fs = new DefaultFileSystem();
-
- File basedir = temp.newFolder();
- fs.setBaseDir(basedir);
- assertThat(fs.baseDir()).isAbsolute().isDirectory().exists();
- assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
-
- File workdir = temp.newFolder();
- fs.setWorkDir(workdir);
- assertThat(fs.workDir()).isAbsolute().isDirectory().exists();
- assertThat(fs.workDir().getCanonicalPath()).isEqualTo(workdir.getCanonicalPath());
- }
-
- @Test
- public void test_encoding() throws Exception {
- DefaultFileSystem fs = new DefaultFileSystem();
-
- assertThat(fs.isDefaultJvmEncoding()).isTrue();
- assertThat(fs.encoding()).isEqualTo(Charset.defaultCharset());
-
- fs.setEncoding(Charsets.ISO_8859_1);
- assertThat(fs.encoding()).isEqualTo(Charsets.ISO_8859_1);
- assertThat(fs.isDefaultJvmEncoding()).isFalse();
- }
-
- @Test
- public void add_languages() throws Exception {
- DefaultFileSystem fs = new DefaultFileSystem();
-
- assertThat(fs.languages()).isEmpty();
-
- fs.addLanguages("java", "php", "cobol");
- assertThat(fs.languages()).containsOnly("cobol", "java", "php");
- }
-
- @Test
- public void files() throws Exception {
- DefaultFileSystem fs = new DefaultFileSystem();
-
- assertThat(fs.inputFiles(fs.predicates().all())).isEmpty();
-
- fs.add(new DefaultInputFile("src/Foo.php").setLanguage("php").setFile(temp.newFile()));
- fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
- fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
-
- // no language
- fs.add(new DefaultInputFile("src/readme.txt").setFile(temp.newFile()));
-
- assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNotNull();
- assertThat(fs.inputFile(fs.predicates().hasRelativePath("does/not/exist"))).isNull();
-
- assertThat(fs.files(fs.predicates().all())).hasSize(4);
- assertThat(fs.files(fs.predicates().hasLanguage("java"))).hasSize(2);
- assertThat(fs.files(fs.predicates().hasLanguage("cobol"))).isEmpty();
-
- assertThat(fs.hasFiles(fs.predicates().all())).isTrue();
- assertThat(fs.hasFiles(fs.predicates().hasLanguage("java"))).isTrue();
- assertThat(fs.hasFiles(fs.predicates().hasLanguage("cobol"))).isFalse();
-
- assertThat(fs.inputFiles(fs.predicates().all())).hasSize(4);
- assertThat(fs.inputFiles(fs.predicates().hasLanguage("php"))).hasSize(1);
- assertThat(fs.inputFiles(fs.predicates().hasLanguage("java"))).hasSize(2);
- assertThat(fs.inputFiles(fs.predicates().hasLanguage("cobol"))).isEmpty();
-
- assertThat(fs.languages()).containsOnly("java", "php");
- }
-
- @Test
- public void input_file_returns_null_if_file_not_found() throws Exception {
- DefaultFileSystem fs = new DefaultFileSystem();
- assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNull();
- assertThat(fs.inputFile(fs.predicates().hasLanguage("cobol"))).isNull();
- }
-
- @Test
- public void input_file_fails_if_too_many_results() throws Exception {
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("expected one element");
-
- DefaultFileSystem fs = new DefaultFileSystem();
- fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
- fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
-
- fs.inputFile(fs.predicates().all());
- }
-
- @Test
- public void input_file_supports_non_indexed_predicates() throws Exception {
- DefaultFileSystem fs = new DefaultFileSystem();
- fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
-
- // it would fail if more than one java file
- assertThat(fs.inputFile(fs.predicates().hasLanguage("java"))).isNotNull();
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.io.File;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DefaultInputFileTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Test
- public void test() throws Exception {
- DefaultInputFile inputFile = new DefaultInputFile("src/Foo.php")
- .setFile(temp.newFile("Foo.php"))
- .setDeprecatedKey("deprecated")
- .setKey("ABCDE")
- .setHash("1234")
- .setLines(42)
- .setLanguage("php")
- .setStatus(InputFile.Status.ADDED)
- .setType(InputFile.Type.TEST)
- .setPathRelativeToSourceDir("Foo.php");
-
- assertThat(inputFile.relativePath()).isEqualTo("src/Foo.php");
- // deprecated method is different -> path relative to source dir
- assertThat(inputFile.getRelativePath()).isEqualTo("Foo.php");
- assertThat(new File(inputFile.relativePath())).isRelative();
- assertThat(inputFile.absolutePath()).endsWith("Foo.php");
- assertThat(new File(inputFile.absolutePath())).isAbsolute();
- assertThat(inputFile.language()).isEqualTo("php");
- assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED);
- assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST);
- assertThat(inputFile.lines()).isEqualTo(42);
- assertThat(inputFile.hash()).isEqualTo("1234");
- }
-
- @Test
- public void test_equals_and_hashcode() throws Exception {
- DefaultInputFile f1 = new DefaultInputFile("src/Foo.php");
- DefaultInputFile f1a = new DefaultInputFile("src/Foo.php");
- DefaultInputFile f2 = new DefaultInputFile("src/Bar.php");
-
- assertThat(f1).isEqualTo(f1);
- assertThat(f1).isEqualTo(f1a);
- assertThat(f1).isNotEqualTo(f2);
- assertThat(f1.equals("foo")).isFalse();
- assertThat(f1.equals(null)).isFalse();
-
- assertThat(f1.hashCode()).isEqualTo(f1.hashCode());
- assertThat(f1.hashCode()).isEqualTo(f1a.hashCode());
- }
-
- @Test
- public void test_toString() throws Exception {
- DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php");
- assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]");
- }
-}
--- /dev/null
+package org.sonar.api.batch.fs.internal;
+
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.io.File;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DeprecatedDefaultInputFileTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void test() throws Exception {
+ DeprecatedDefaultInputFile inputFile = (DeprecatedDefaultInputFile) new DeprecatedDefaultInputFile("src/Foo.php")
+ .setPathRelativeToSourceDir("Foo.php")
+ .setDeprecatedKey("deprecated")
+ .setFile(temp.newFile("Foo.php"))
+ .setKey("ABCDE")
+ .setHash("1234")
+ .setLines(42)
+ .setLanguage("php")
+ .setStatus(InputFile.Status.ADDED)
+ .setType(InputFile.Type.TEST);
+
+ assertThat(inputFile.relativePath()).isEqualTo("src/Foo.php");
+ // deprecated method is different -> path relative to source dir
+ assertThat(inputFile.getRelativePath()).isEqualTo("Foo.php");
+ assertThat(new File(inputFile.relativePath())).isRelative();
+ assertThat(inputFile.absolutePath()).endsWith("Foo.php");
+ assertThat(new File(inputFile.absolutePath())).isAbsolute();
+ assertThat(inputFile.language()).isEqualTo("php");
+ assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED);
+ assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST);
+ assertThat(inputFile.lines()).isEqualTo(42);
+ assertThat(inputFile.hash()).isEqualTo("1234");
+ }
+
+ @Test
+ public void test_equals_and_hashcode() throws Exception {
+ DefaultInputFile f1 = new DefaultInputFile("src/Foo.php");
+ DefaultInputFile f1a = new DefaultInputFile("src/Foo.php");
+ DefaultInputFile f2 = new DefaultInputFile("src/Bar.php");
+
+ assertThat(f1).isEqualTo(f1);
+ assertThat(f1).isEqualTo(f1a);
+ assertThat(f1).isNotEqualTo(f2);
+ assertThat(f1.equals("foo")).isFalse();
+ assertThat(f1.equals(null)).isFalse();
+
+ assertThat(f1.hashCode()).isEqualTo(f1.hashCode());
+ assertThat(f1.hashCode()).isEqualTo(f1a.hashCode());
+ }
+
+ @Test
+ public void test_toString() throws Exception {
+ DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php");
+ assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]");
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.io.File;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class PathPatternTest {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Test
- public void match_relative_path() throws Exception {
- PathPattern pattern = PathPattern.create("**/*Foo.java");
- assertThat(pattern.toString()).isEqualTo("**/*Foo.java");
-
- File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
- InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
- assertThat(pattern.match(inputFile)).isTrue();
-
- // case sensitive by default
- file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
- inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
- assertThat(pattern.match(inputFile)).isFalse();
-
- file = new File(temp.newFolder(), "src/main/java/org/Other.java");
- inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
- assertThat(pattern.match(inputFile)).isFalse();
- }
-
- @Test
- public void match_relative_path_and_insensitive_file_extension() throws Exception {
- PathPattern pattern = PathPattern.create("**/*Foo.java");
-
- File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
- InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
- assertThat(pattern.match(inputFile, false)).isTrue();
-
- file = new File(temp.newFolder(), "src/main/java/org/Other.java");
- inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
- assertThat(pattern.match(inputFile, false)).isFalse();
- }
-
- @Test
- public void match_absolute_path() throws Exception {
- PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
- assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
-
- File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
- InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
- assertThat(pattern.match(inputFile)).isTrue();
-
- // case sensitive by default
- file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
- inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
- assertThat(pattern.match(inputFile)).isFalse();
-
- file = new File(temp.newFolder(), "src/main/java/org/Other.java");
- inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
- assertThat(pattern.match(inputFile)).isFalse();
- }
-
- @Test
- public void match_absolute_path_and_insensitive_file_extension() throws Exception {
- PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
- assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
-
- File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
- InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
- assertThat(pattern.match(inputFile, false)).isTrue();
-
- file = new File(temp.newFolder(), "src/main/java/org/Other.JAVA");
- inputFile = new DefaultInputFile("src/main/java/org/Other.JAVA").setFile(file);
- assertThat(pattern.match(inputFile, false)).isFalse();
- }
-
- @Test
- public void create_array_of_patterns() throws Exception {
- PathPattern[] patterns = PathPattern.create(new String[]{
- "**/src/main/**Foo.java",
- "file:**/src/main/**Bar.java"
- });
- assertThat(patterns).hasSize(2);
- assertThat(patterns[0].toString()).isEqualTo("**/src/main/**Foo.java");
- assertThat(patterns[1].toString()).isEqualTo("file:**/src/main/**Bar.java");
- }
-}
*/
package org.sonar.server.startup;
+import com.google.common.collect.Lists;
import org.junit.Test;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import java.util.Arrays;
import java.util.List;
-import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
setupData("shouldUpdateIfAlreadyExists");
RegisterMetrics synchronizer = new RegisterMetrics(new MeasuresDao(getSession()), mock(QualityGateConditionDao.class), new Metrics[0]);
- synchronizer.register(newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
+ synchronizer.register(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
.setDescription("new description")
.setDirection(-1)
.setQualitative(true)
@Test
public void shouldAddUserManagesMetric() {
Metrics metrics = mock(Metrics.class);
- when(metrics.getMetrics()).thenReturn(newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
+ when(metrics.getMetrics()).thenReturn(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
.setDescription("new description")
.setDirection(-1)
.setQualitative(true)
.create()));
MeasuresDao measuresDao = new MeasuresDao(getSession());
- RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[]{metrics});
+ RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[] {metrics});
List<Metric> result = loader.getMetricsRepositories();
assertThat(result).hasSize(1);
setupData("shouldNotUpdateUserManagesMetricIfAlreadyExists");
Metrics metrics = mock(Metrics.class);
- when(metrics.getMetrics()).thenReturn(newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
+ when(metrics.getMetrics()).thenReturn(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
.setDescription("new description")
.setDirection(-1)
.setQualitative(true)
.create()));
MeasuresDao measuresDao = new MeasuresDao(getSession());
- RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[]{metrics});
+ RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[] {metrics});
List<Metric> result = loader.getMetricsRepositories();
assertThat(result).isEmpty();