aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java65
-rw-r--r--plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java15
-rw-r--r--plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java57
-rw-r--r--plugins/sonar-squid-java-plugin/test-resources/basic_handlers/javaFile.java31
-rw-r--r--plugins/sonar-squid-java-plugin/test-resources/basic_handlers/plsqlFile.pak83
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java8
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java46
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/ResourceNotIndexedException.java33
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java17
-rw-r--r--sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java1
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java9
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java5
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java8
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java6
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java10
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java60
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java2
17 files changed, 240 insertions, 216 deletions
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java
index 87e7699ba88..0e7a1c1e3f4 100644
--- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java
+++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java
@@ -19,30 +19,73 @@
*/
package org.sonar.plugins.squid;
+import org.apache.commons.io.FileUtils;
+import org.sonar.api.CoreProperties;
import org.sonar.api.batch.*;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.JavaFile;
-import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.*;
+import org.sonar.api.utils.SonarException;
import org.sonar.java.api.JavaUtils;
-import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
import java.util.List;
-@DependsUpon(classes=SquidSensor.class)
+@Phase(name = Phase.Name.PRE)
+@DependsUpon(classes = SquidSensor.class)
@DependedUpon(JavaUtils.BARRIER_AFTER_SQUID)
-public class JavaSourceImporter extends AbstractSourceImporter {
+public final class JavaSourceImporter implements Sensor {
- public JavaSourceImporter() {
- super(Java.INSTANCE);
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldExecuteOnProject(Project project) {
+ return isEnabled(project) && Java.KEY.equals(project.getLanguageKey());
}
- @Override
- protected Resource createResource(File file, List<File> sourceDirs, boolean unitTest) {
- return file != null ? JavaFile.fromIOFile(file, sourceDirs, unitTest) : null;
+ /**
+ * {@inheritDoc}
+ */
+ public void analyse(Project project, SensorContext context) {
+ analyse(project.getFileSystem(), context);
+ }
+
+ void analyse(ProjectFileSystem fileSystem, SensorContext context) {
+ parseDirs(context, fileSystem.mainFiles(Java.INSTANCE), false, fileSystem.getSourceCharset());
+ parseDirs(context, fileSystem.testFiles(Java.INSTANCE), true, fileSystem.getSourceCharset());
+ }
+
+ void parseDirs(SensorContext context, List<InputFile> inputFiles, boolean unitTest, Charset sourcesEncoding) {
+ for (InputFile inputFile : inputFiles) {
+ JavaFile javaFile = JavaFile.fromRelativePath(inputFile.getRelativePath(), unitTest);
+ importSource(context, javaFile, inputFile, sourcesEncoding);
+ }
+ }
+
+ void importSource(SensorContext context, JavaFile javaFile, InputFile inputFile, Charset sourcesEncoding) {
+ try {
+ //if (!context.isIndexed(javaFile, true)) {
+ // See http://jira.codehaus.org/browse/SONAR-791
+ // Squid is the reference plugin to index files. If a file is not indexed,
+ // throw new SonarException("Invalid file: " + javaFile + ". Please check that Java source directories match root directories" +
+ // " as defined by packages.");
+ //}
+ String source = FileUtils.readFileToString(inputFile.getFile(), sourcesEncoding.name());
+ context.saveSource(javaFile, source);
+
+ } catch (IOException e) {
+ throw new SonarException("Unable to read and import the source file : '" + inputFile.getFile().getAbsolutePath() + "' with the charset : '"
+ + sourcesEncoding.name() + "'.", e);
+ }
+ }
+
+ boolean isEnabled(Project project) {
+ return project.getConfiguration().getBoolean(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY,
+ CoreProperties.CORE_IMPORT_SOURCES_DEFAULT_VALUE);
}
@Override
public String toString() {
return getClass().getSimpleName();
}
+
}
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java
index c1b242e09de..c79a60d2559 100644
--- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java
+++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java
@@ -25,6 +25,7 @@ import org.sonar.api.batch.*;
import org.sonar.api.checks.AnnotationCheckFactory;
import org.sonar.api.checks.NoSonarFilter;
import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.resources.InputFile;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Project;
@@ -82,22 +83,18 @@ public class SquidSensor implements Sensor {
}
private void browseTestSources(Project project, SensorContext context) {
- for (File testFile : getTestSourceFiles(project)) {
- context.index(JavaFile.fromIOFile(testFile, project.getFileSystem().getTestDirs(), true));
+ for (InputFile testFile : project.getFileSystem().testFiles(Java.INSTANCE)) {
+ context.index(JavaFile.fromRelativePath(testFile.getRelativePath(), true));
}
}
- private List<File> getTestSourceFiles(Project project) {
- return project.getFileSystem().getTestFiles(Java.INSTANCE);
- }
-
private List<File> getMainSourceFiles(Project project) {
return project.getFileSystem().getJavaSourceFiles();
}
private Collection<File> getMainBytecodeFiles(Project project) {
Collection<File> bytecodeFiles = projectClasspath.getElements();
- if ( !hasProjectBytecodeFiles(project)) {
+ if (!hasProjectBytecodeFiles(project)) {
File classesDir = project.getFileSystem().getBuildOutputDir();
if (classesDir != null && classesDir.exists()) {
bytecodeFiles.remove(classesDir);
@@ -107,11 +104,11 @@ public class SquidSensor implements Sensor {
}
private boolean hasProjectBytecodeFiles(Project project) {
- if ( !project.getConfiguration()
+ if (!project.getConfiguration()
.getBoolean(CoreProperties.DESIGN_SKIP_DESIGN_PROPERTY, CoreProperties.DESIGN_SKIP_DESIGN_DEFAULT_VALUE)) {
File classesDir = project.getFileSystem().getBuildOutputDir();
if (classesDir != null && classesDir.exists()) {
- return !FileUtils.listFiles(classesDir, new String[] { "class" }, true).isEmpty();
+ return !FileUtils.listFiles(classesDir, new String[]{"class"}, true).isEmpty();
}
}
return false;
diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java
index c6667a6920e..f90274d9964 100644
--- a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java
+++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java
@@ -19,42 +19,53 @@
*/
package org.sonar.plugins.squid;
-import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.resources.InputFile;
import org.sonar.api.resources.JavaFile;
-import org.sonar.api.resources.JavaPackage;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.ResourceUtils;
+import org.sonar.api.utils.SonarException;
import java.io.File;
import java.io.IOException;
-import java.util.Arrays;
+import java.nio.charset.Charset;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
public class JavaSourceImporterTest {
- @Test
- public void shouldDefineMainFile() throws IOException {
- JavaSourceImporter importer = new JavaSourceImporter();
- Resource clazz = importer.createResource(new File(newDir("source1"), "/MyClass.java"), Arrays.asList(newDir("source1")), false);
- assertThat(clazz, is(JavaFile.class));
- assertThat(clazz.getKey(), is(JavaPackage.DEFAULT_PACKAGE_NAME + ".MyClass"));
- assertThat(clazz.getName(), is("MyClass"));
+ private JavaSourceImporter importer;
+ private SensorContext context;
+ private InputFile inputFile;
+
+ @Before
+ public void init() {
+ File fileToImport = new File("test-resources/rules/UndocumentedApi.java");
+ inputFile = mock(InputFile.class);
+ when(inputFile.getRelativePath()).thenReturn("UndocumentedApi.java");
+ when(inputFile.getFile()).thenReturn(fileToImport);
+ when(inputFile.getFileBaseDir()).thenReturn(fileToImport.getParentFile());
+ importer = new JavaSourceImporter();
+ context = mock(SensorContext.class);
}
@Test
- public void shouldDefineTestFile() throws IOException {
- JavaSourceImporter importer = new JavaSourceImporter();
- Resource resource = importer.createResource(new File(newDir("tests"), "/MyClassTest.java"), Arrays.asList(newDir("tests")), true);
- assertThat(resource, is(JavaFile.class));
- assertThat(ResourceUtils.isUnitTestClass(resource), is(true));
+ public void shouldSetSource() throws IOException {
+ JavaFile javaFile = JavaFile.fromRelativePath("UndocumentedApi.java", true);
+ when(context.isIndexed(javaFile, true)).thenReturn(true);
+ importer.importSource(context, javaFile, inputFile, Charset.defaultCharset());
+
+ verify(context).saveSource(eq(javaFile), anyString());
}
- private File newDir(String relativePath) throws IOException {
- File target = new File("target", relativePath);
- FileUtils.forceMkdir(target);
- return target;
+ @Test(expected = SonarException.class)
+ @Ignore("see SONAR-791")
+ public void shouldFailWhenSquidDidNotIndexFile() throws IOException {
+ JavaFile javaFile = new JavaFile("Bar");
+ when(context.isIndexed(javaFile, true)).thenReturn(false);
+ importer.importSource(context, javaFile, inputFile, Charset.defaultCharset());
}
} \ No newline at end of file
diff --git a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/javaFile.java b/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/javaFile.java
deleted file mode 100644
index 5ea06251f14..00000000000
--- a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/javaFile.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Javadoc for this Car class
- * @author freddy
- *
- */
-public class Car {
-
- private int n; //C++ inline comment
- private String s;
-
- public AClass(int n, String s) {
- this.n = n;
- this.s = s;
- }
-
- /*
- *C style comment
- *
- */
- public int getN() {
- /*
- * Another C style comment
- */
- return n;
- }
-
- public String getS() {
- return s;
- }
-
-} \ No newline at end of file
diff --git a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/plsqlFile.pak b/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/plsqlFile.pak
deleted file mode 100644
index f0e5a8535a5..00000000000
--- a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/plsqlFile.pak
+++ /dev/null
@@ -1,83 +0,0 @@
-
-CREATE OR REPLACE PACKAGE SONAR002 AS
-
--- ----------------------------------------------------------------------------
--- package version
-FUNCTION VERSION RETURN VARCHAR2;
- PRAGMA RESTRICT_REFERENCES (VERSION, WNDS, WNPS, RNPS);
-
-
-TYPE T_trans IS TABLE OF VARCHAR2(250) INDEX BY BINARY_INTEGER;
-A_trans T_trans;
-w_origine VARCHAR2(160);
-w_sqlerrm VARCHAR2(255);
-
-header_c_langue VARCHAR2(2);
-
-TYPE T_TAG IS RECORD ( NOM_TAG VARCHAR2(50)
- ,VALEUR VARCHAR2(32000));
-
-TYPE TT_TAGS IS TABLE OF T_TAG INDEX BY BINARY_INTEGER;
-
-tb_TAGS TT_TAGS;
-
-
-TYPE ControleData IS RECORD
- ( pourcent NUMBER,
- bande VARCHAR2(40),
- nb_ligne NUMBER,
- typ_avis VARCHAR2(25),
- nb_brique NUMBER,
- no_op operation.no_op%TYPE,
- no_op_pere operation.no_op%TYPE,
- no_op_doss operation.no_op%TYPE,
- c_typ_contrat operation.c_typ_contrat%TYPE,
- ref_op operation.ref_op%TYPE,
- c_op_param type_oper_param.c_op_param%TYPE,
- c_serv operation.c_serv%TYPE,
- c_dev operation.c_dev%TYPE,
- d_op operation.d_op%TYPE,
- c_op_param_role VARCHAR2(4),
- c_phase VARCHAR2(4),
- c_phase_real VARCHAR2(4),
- id_avis NUMBER,
- c_form VARCHAR2(10),
- c_teneur_envoi VARCHAR2(10),
- Spool VARCHAR2(320),
- spool_tmp VARCHAR2(320),
- old_elt VARCHAR2(10),
- new_elt VARCHAR2(10),
- old_ligne NUMBER,
- new_ligne NUMBER,
- old_ordre NUMBER,
- new_tag VARCHAR2(3),
- old_tag VARCHAR2(3),
- new_ordre NUMBER,
- mode_fusion VARCHAR2(1),
- TRACE VARCHAR2(80),
- taux_cent_mille NUMBER,
- caractere_taux VARCHAR2(1),
- chemin_avis VARCHAR2(20),
- nbr_dec_doss NUMBER,
- c_dev_doss VARCHAR2(3),
- mt_cpta_bloc_2 NUMBER,
- regr_aff_dest VARCHAR2(1),
- no_seq NUMBER(8),
- no_seq_pere NUMBER(8),
- id_envoi NUMBER(8),
- id_envoi_pere NUMBER(8),
- id_message NUMBER(8),
- generation VARCHAR2(1),
- c_uti VARCHAR2(6),
- c_uti_cre VARCHAR2(6),
- no_swift VARCHAR2(1),
- c_trait_202 VARCHAR2(5),
- envoi_pere_202 VARCHAR2(5),
- f_envoi_ga_java VARCHAR2(1),
- avec_templ_perso VARCHAR2(1),
- f_comm_prises VARCHAR2(1),
- liab_reduc_with_pmt VARCHAR2(1));
-Controle ControleData;
-
-END SONAR002;
-
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
index a924fba8ac1..4a4acf8bf32 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
@@ -60,8 +60,8 @@ public class DefaultSensorContext implements SensorContext {
return index.isExcluded(reference);
}
- public boolean isIndexed(Resource reference) {
- return index.isIndexed(reference);
+ public boolean isIndexed(Resource reference, boolean acceptExcluded) {
+ return index.isIndexed(reference, acceptExcluded);
}
public Resource getParent(Resource reference) {
@@ -155,8 +155,8 @@ public class DefaultSensorContext implements SensorContext {
return index.getOutgoingEdges(resourceOrProject(from));
}
- public boolean saveSource(Resource reference, String source) throws DuplicatedSourceException {
- return index.setSource(reference, source);
+ public void saveSource(Resource reference, String source) throws DuplicatedSourceException {
+ index.setSource(reference, source);
}
public void saveLink(ProjectLink link) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
index 5660bf44ade..01ba7d6b384 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
@@ -157,7 +157,7 @@ public final class DefaultIndex extends SonarIndex {
* the measure is updated if it's already registered.
*/
public Measure addMeasure(Resource resource, Measure measure) {
- Bucket bucket = doIndex(resource);
+ Bucket bucket = checkIndexed(resource);
if (bucket != null && !bucket.isExcluded()) {
Metric metric = metricFinder.findByKey(measure.getMetricKey());
if (metric == null) {
@@ -170,7 +170,6 @@ public final class DefaultIndex extends SonarIndex {
if (measure.getPersistenceMode().useDatabase()) {
persistence.saveMeasure(resource, measure);
}
-
// TODO keep database measures in cache but remove data
}
return measure;
@@ -295,13 +294,12 @@ public final class DefaultIndex extends SonarIndex {
}
public void addViolation(Violation violation, boolean force) {
- Bucket bucket;
Resource resource = violation.getResource();
if (resource == null) {
violation.setResource(currentProject);
}
- bucket = doIndex(violation.getResource());
- if (!bucket.isExcluded()) {
+ Bucket bucket = checkIndexed(resource);
+ if (bucket != null && !bucket.isExcluded()) {
boolean isIgnored = !force && violationFilters != null && violationFilters.isIgnored(violation);
if (!isIgnored) {
ActiveRule activeRule = profile.getActiveRule(violation.getRule());
@@ -366,13 +364,11 @@ public final class DefaultIndex extends SonarIndex {
return null;
}
- public boolean setSource(Resource reference, String source) {
- boolean result = false;
- if (isIndexed(reference)) {
+ public void setSource(Resource reference, String source) {
+ Bucket bucket = checkIndexed(reference);
+ if (bucket != null && !bucket.isExcluded()) {
persistence.setSource(reference, source);
- result = true;
}
- return result;
}
@@ -387,7 +383,7 @@ public final class DefaultIndex extends SonarIndex {
public <R extends Resource> R getResource(R reference) {
Bucket bucket = buckets.get(reference);
if (bucket != null) {
- return (R)bucket.getResource();
+ return (R) bucket.getResource();
}
return null;
}
@@ -443,8 +439,7 @@ public final class DefaultIndex extends SonarIndex {
private Bucket doIndex(Resource resource) {
if (resource.getParent() != null) {
- // SONAR-2127 backward-compatibility - create automatically parent of files
- doIndex(resource.getParent(), currentProject);
+ doIndex(resource.getParent());
}
return doIndex(resource, resource.getParent());
}
@@ -469,7 +464,7 @@ public final class DefaultIndex extends SonarIndex {
}
Bucket parentBucket = getBucket(parent, true);
- if (parentBucket==null && parent!=null) {
+ if (parentBucket == null && parent != null) {
LOG.warn("Resource ignored, parent is not indexed: " + resource);
return null;
}
@@ -480,7 +475,7 @@ public final class DefaultIndex extends SonarIndex {
boolean excluded = checkExclusion(resource, parentBucket);
if (!excluded) {
- persistence.saveResource(currentProject, resource, (parentBucket!=null ? parentBucket.getResource() : null));
+ persistence.saveResource(currentProject, resource, (parentBucket != null ? parentBucket.getResource() : null));
}
return bucket;
}
@@ -494,13 +489,30 @@ public final class DefaultIndex extends SonarIndex {
}
}
+ private Bucket checkIndexed(Resource reference) {
+ Bucket bucket = getBucket(reference, true);
+ if (bucket == null) {
+ if (lock.isLocked()) {
+ if (lock.isFailWhenLocked()) {
+ throw new ResourceNotIndexedException(reference);
+ }
+ LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + reference);
+ } else {
+ // other languages than Java - keep backward compatibility
+ bucket = doIndex(reference);
+ }
+ }
+ return bucket;
+ }
+
+
public boolean isExcluded(Resource reference) {
Bucket bucket = getBucket(reference, true);
return bucket != null && bucket.isExcluded();
}
- public boolean isIndexed(Resource reference) {
- return getBucket(reference, false) != null;
+ public boolean isIndexed(Resource reference, boolean acceptExcluded) {
+ return getBucket(reference, acceptExcluded) != null;
}
private Bucket getBucket(Resource resource, boolean acceptExcluded) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceNotIndexedException.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceNotIndexedException.java
new file mode 100644
index 00000000000..203f4043ff6
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceNotIndexedException.java
@@ -0,0 +1,33 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.index;
+
+import org.sonar.api.resources.Resource;
+import org.sonar.api.utils.SonarException;
+
+/**
+ * @since 2.6
+ */
+public class ResourceNotIndexedException extends SonarException {
+
+ public ResourceNotIndexedException(final Resource reference) {
+ super(reference.toString());
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
index e90cd8a9b61..ef88932c7e1 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
@@ -85,7 +85,7 @@ public class DefaultIndexTest {
Directory reference = new Directory("org/foo");
assertThat(index.getResource(reference).getName(), is("org/foo"));
- assertThat(index.isIndexed(reference), is(true));
+ assertThat(index.isIndexed(reference, true), is(true));
assertThat(index.isExcluded(reference), is(false));
assertThat(index.getChildren(reference).size(), is(1));
assertThat(index.getParent(reference), is(Project.class));
@@ -103,7 +103,7 @@ public class DefaultIndexTest {
File fileRef = new File("org/foo/Bar.java");
assertThat(index.getResource(fileRef).getKey(), is("org/foo/Bar.java"));
assertThat(index.getResource(fileRef).getLanguage(), is((Language) Java.INSTANCE));
- assertThat(index.isIndexed(fileRef), is(true));
+ assertThat(index.isIndexed(fileRef, true), is(true));
assertThat(index.isExcluded(fileRef), is(false));
assertThat(index.getChildren(fileRef).size(), is(0));
assertThat(index.getParent(fileRef), is(Directory.class));
@@ -116,7 +116,7 @@ public class DefaultIndexTest {
Library reference = new Library("junit", "4.8");
assertThat(index.getResource(reference).getQualifier(), is(Qualifiers.LIBRARY));
- assertThat(index.isIndexed(reference), is(true));
+ assertThat(index.isIndexed(reference, true), is(true));
assertThat(index.isExcluded(reference), is(false));
}
@@ -128,8 +128,8 @@ public class DefaultIndexTest {
assertThat(index.index(file, directory), is(false));
File fileRef = new File("org/foo/Bar.java");
- assertThat(index.isIndexed(directory), is(false));
- assertThat(index.isIndexed(fileRef), is(false));
+ assertThat(index.isIndexed(directory, true), is(false));
+ assertThat(index.isIndexed(fileRef, true), is(false));
assertThat(index.isExcluded(fileRef), is(false));
assertThat(index.getChildren(fileRef).size(), is(0));
assertThat(index.getParent(fileRef), nullValue());
@@ -145,7 +145,7 @@ public class DefaultIndexTest {
Directory dir = new Directory("org/foo");
assertThat(index.index(dir), is(true));
- assertThat(index.isIndexed(dir), is(true));
+ assertThat(index.isIndexed(dir, true), is(true));
}
@Test(expected = SonarException.class)
@@ -161,7 +161,8 @@ public class DefaultIndexTest {
public void shouldBeExcluded() {
File file = new File("org/foo/ExcludedBar.java");
assertThat(index.index(file), is(false));
- assertThat(index.isIndexed(file), is(false));
+ assertThat(index.isIndexed(file, true), is(true));
+ assertThat(index.isIndexed(file, false), is(false));
assertThat(index.isExcluded(file), is(true));
}
@@ -170,7 +171,7 @@ public class DefaultIndexTest {
Resource dir = new Directory("org/foo");
index.addMeasure(dir, new Measure("ncloc").setValue(50.0));
- assertThat(index.isIndexed(dir), is(true));
+ assertThat(index.isIndexed(dir, true), is(true));
assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc")).getIntValue(), is(50));
}
}
diff --git a/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java b/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java
index dad567cc1e3..9fa234f5626 100644
--- a/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java
+++ b/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java
@@ -24,6 +24,7 @@ import org.apache.commons.lang.StringUtils;
public final class JavaUtils {
public static final String PACKAGE_SEPARATOR = ".";
+ public static final String DEFAULT_PACKAGE = "[default]";
/**
* All sensors executed after this barrier are sure that all Java resources are indexed.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
index 07b58dc1a13..8ac007a1e6a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
@@ -58,15 +58,16 @@ public interface SensorContext {
boolean index(Resource resource, Resource parentReference);
/**
- * Returns true if the referenced resource is excluded. An excluded resource is not indexed.
+ * Returns true if the referenced resource is indexed and excluded.
* @since 2.6
*/
boolean isExcluded(Resource reference);
/**
+ * Returns true if the referenced resource is indexed.
* @since 2.6
*/
- boolean isIndexed(Resource reference);
+ boolean isIndexed(Resource reference, boolean acceptExcluded);
/**
* Search for an indexed resource.
@@ -88,7 +89,6 @@ public interface SensorContext {
Collection<Resource> getChildren(Resource reference);
-
// ----------- MEASURES ON PROJECT --------------
/**
@@ -188,14 +188,13 @@ public interface SensorContext {
/**
* Save the source code of a file. The file must be have been indexed before.
- * Note: the source stream is not closed.
*
* @return false if the resource is excluded or not indexed
* @throws org.sonar.api.resources.DuplicatedSourceException
* if the source has already been set on this resource
* @since 1.10. Returns a boolean since 2.6.
*/
- boolean saveSource(Resource reference, String source) throws DuplicatedSourceException;
+ void saveSource(Resource reference, String source) throws DuplicatedSourceException;
// ----------- LINKS --------------
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
index 06ae5ae80fd..cf441562c1b 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
@@ -39,6 +39,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe
/**
* Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed.
+ * If the method resource.getParent() does not return null, then this parent will be indexed too.
*
* @return false if the resource is excluded
* @since 2.6
@@ -65,7 +66,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe
/**
* @since 2.6
*/
- public abstract boolean isIndexed(Resource reference);
+ public abstract boolean isIndexed(Resource reference, boolean acceptExcluded);
/**
* Search for an indexed resource.
@@ -95,7 +96,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe
* @throws org.sonar.api.resources.DuplicatedSourceException
* if the source has already been set on this resource
*/
- public abstract boolean setSource(Resource reference, String source) throws DuplicatedSourceException;
+ public abstract void setSource(Resource reference, String source) throws DuplicatedSourceException;
public abstract Project getProject();
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java
index 4b7837779e3..85a47eb8945 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java
@@ -353,11 +353,11 @@ public class DefaultProjectFileSystem implements ProjectFileSystem {
return getFiles(getTestDirs(), false /* FIXME should be true? */, langs);
}
- private class DefaultInputFile implements InputFile {
+ private static final class DefaultInputFile implements InputFile {
private File basedir;
private File file;
- public DefaultInputFile(File basedir, File file) {
+ DefaultInputFile(File basedir, File file) {
this.basedir = basedir;
this.file = file;
}
@@ -369,6 +369,10 @@ public class DefaultProjectFileSystem implements ProjectFileSystem {
public File getFile() {
return file;
}
+
+ public String getRelativePath() {
+ return DefaultProjectFileSystem.getRelativePath(file, basedir);
+ }
}
/**
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java
index 24b7d32b6b8..40872867c7e 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java
@@ -38,7 +38,7 @@ public class File extends Resource<Directory> {
private String filename;
private Language language;
private Directory parent;
- private String qualifier = Resource.QUALIFIER_FILE;
+ private String qualifier = Qualifiers.FILE;
/**
* File in project. Key is the path relative to project source directories. It is not the absolute path and it does not include the path
@@ -187,8 +187,8 @@ public class File extends Resource<Directory> {
/**
* @return SCOPE_ENTITY
*/
- public String getScope() {
- return Resource.SCOPE_ENTITY;
+ public final String getScope() {
+ return SCOPE;
}
/**
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java
index 6e87e3445ad..4c926f897e1 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java
@@ -30,4 +30,14 @@ public interface InputFile {
File getFile();
+ /**
+ * Path relative to basedir. Directory separator is slash '/', whatever the platform.
+ *
+ * Example on windows: if basedir is c:\project\src\ and file is c:\project\src\org\foo\Bar.java, then relative path
+ * is org/foo/Bar.java
+ *
+ * Example on unix: if basedir is /project/src and file is /project/src/org/foo/Bar.java, then relative path
+ * is org/foo/Bar.java as well.
+ */
+ String getRelativePath();
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java
index ef940898ced..009a04e670a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java
@@ -37,7 +37,7 @@ public class JavaFile extends Resource<JavaPackage> {
private String longName;
private String packageKey;
private boolean unitTest;
- private JavaPackage parent = null;
+ private JavaPackage parent;
/**
* Creates a JavaFile that is not a class of test based on package and file names
@@ -52,7 +52,7 @@ public class JavaFile extends Resource<JavaPackage> {
* @param unitTest whether it is a unit test file or a source file
*/
public JavaFile(String packageKey, String className, boolean unitTest) {
- if (className==null) {
+ if (className == null) {
throw new IllegalArgumentException("Java filename can not be null");
}
if (className.indexOf('$') >= 0) {
@@ -86,10 +86,10 @@ public class JavaFile extends Resource<JavaPackage> {
* @param unitTest whether it is a unit test file or a source file
*/
public JavaFile(String key, boolean unitTest) {
- if (key==null) {
+ if (key == null) {
throw new IllegalArgumentException("Java filename can not be null");
}
- if (key != null && key.indexOf('$') >= 0) {
+ if (key.indexOf('$') >= 0) {
throw new IllegalArgumentException("Java inner classes are not supported : " + key);
}
String realKey = StringUtils.trim(key);
@@ -117,6 +117,7 @@ public class JavaFile extends Resource<JavaPackage> {
parent = new JavaPackage(packageKey);
}
return parent;
+
}
/**
@@ -151,14 +152,14 @@ public class JavaFile extends Resource<JavaPackage> {
* @return SCOPE_ENTITY
*/
public String getScope() {
- return Resource.SCOPE_ENTITY;
+ return Scopes.FILE;
}
/**
* @return QUALIFIER_UNIT_TEST_CLASS or QUALIFIER_CLASS depending whether it is a unit test class
*/
public String getQualifier() {
- return unitTest ? Qualifiers.UNIT_TEST_FILE : Resource.QUALIFIER_CLASS;
+ return unitTest ? Qualifiers.UNIT_TEST_FILE : Qualifiers.CLASS;
}
/**
@@ -179,23 +180,14 @@ public class JavaFile extends Resource<JavaPackage> {
if (!fileKey.endsWith(".java")) {
fileKey += ".java";
}
- if (StringUtils.substringAfterLast(antPattern, "/").indexOf(".")<0) {
+ if (StringUtils.substringAfterLast(antPattern, "/").indexOf(".") < 0) {
antPattern += ".*";
}
WildcardPattern matcher = WildcardPattern.create(antPattern, ".");
return matcher.match(fileKey);
}
- /**
- * Creates a JavaFile from a file in the source directories
- *
- * @return the JavaFile created if exists, null otherwise
- */
- public static JavaFile fromIOFile(File file, List<File> sourceDirs, boolean unitTest) {
- if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), ".java")) {
- return null;
- }
- String relativePath = DefaultProjectFileSystem.getRelativePath(file, sourceDirs);
+ public static JavaFile fromRelativePath(String relativePath, boolean unitTest) {
if (relativePath != null) {
String pacname = null;
String classname = relativePath;
@@ -212,6 +204,19 @@ public class JavaFile extends Resource<JavaPackage> {
}
/**
+ * Creates a JavaFile from a file in the source directories
+ *
+ * @return the JavaFile created if exists, null otherwise
+ */
+ public static JavaFile fromIOFile(File file, List<File> sourceDirs, boolean unitTest) {
+ if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), ".java")) {
+ return null;
+ }
+ String relativePath = DefaultProjectFileSystem.getRelativePath(file, sourceDirs);
+ return fromRelativePath(relativePath, unitTest);
+ }
+
+ /**
* Shortcut to fromIOFile with an abolute path
*/
public static JavaFile fromAbsolutePath(String path, List<File> sourceDirs, boolean unitTest) {
@@ -230,4 +235,25 @@ public class JavaFile extends Resource<JavaPackage> {
.append("unitTest", unitTest)
.toString();
}
+
+// @Override
+// public boolean equals(Object o) {
+// if (this == o) return true;
+// if (o == null || getClass() != o.getClass()) return false;
+// if (!super.equals(o)) return false;
+//
+// JavaFile javaFile = (JavaFile) o;
+// if (unitTest != javaFile.unitTest) return false;
+// if (!getKey().equals(javaFile.getKey())) return false;
+//
+// return true;
+// }
+//
+// @Override
+// public int hashCode() {
+// int result = super.hashCode();
+// result = 31 * result + getKey().hashCode();
+// result = 31 * result + (unitTest ? 1 : 0);
+// return result;
+// }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java
index d61088c1b45..0ec5528ca9f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java
@@ -80,7 +80,7 @@ public class JavaPackage extends Resource {
* @return QUALIFIER_PACKAGE
*/
public String getQualifier() {
- return Resource.QUALIFIER_PACKAGE;
+ return Qualifiers.PACKAGE;
}
/**