From d590c655de2808fb447acbe94a1a436e2838a6c5 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Wed, 29 Jan 2014 15:59:23 +0100 Subject: [PATCH] SONAR-926 Improve File/Directory to better support plugin still using this API --- .../org/sonar/batch/index/DefaultIndex.java | 35 ++++++--- .../java/org/sonar/api/batch/SquidUtils.java | 7 +- .../org/sonar/api/resources/Directory.java | 35 ++++++--- .../java/org/sonar/api/resources/File.java | 75 ++++++++++++------- .../org/sonar/api/resources/JavaFile.java | 17 ++--- 5 files changed, 109 insertions(+), 60 deletions(-) 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 90dea4a940c..459b1af63f9 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 @@ -32,8 +32,21 @@ import org.sonar.api.batch.SquidUtils; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.database.model.Snapshot; import org.sonar.api.design.Dependency; -import org.sonar.api.measures.*; -import org.sonar.api.resources.*; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilter; +import org.sonar.api.measures.MeasuresFilters; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.MetricFinder; +import org.sonar.api.resources.Directory; +import org.sonar.api.resources.File; +import org.sonar.api.resources.JavaFile; +import org.sonar.api.resources.JavaPackage; +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.resources.ResourceUtils; +import org.sonar.api.resources.Scopes; import org.sonar.api.rules.Rule; import org.sonar.api.rules.Violation; import org.sonar.api.scan.filesystem.PathResolver; @@ -46,7 +59,14 @@ import org.sonar.batch.issue.ModuleIssues; import org.sonar.core.component.ComponentKeys; import org.sonar.core.component.ScanGraph; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; public class DefaultIndex extends SonarIndex { @@ -72,7 +92,7 @@ public class DefaultIndex extends SonarIndex { private ResourceKeyMigration migration; public DefaultIndex(PersistenceManager persistence, ProjectTree projectTree, MetricFinder metricFinder, - ScanGraph graph, DeprecatedViolations deprecatedViolations, ResourceKeyMigration migration) { + ScanGraph graph, DeprecatedViolations deprecatedViolations, ResourceKeyMigration migration) { this.persistence = persistence; this.projectTree = projectTree; this.metricFinder = metricFinder; @@ -547,7 +567,6 @@ public class DefaultIndex extends SonarIndex { return bucket; } - private Bucket checkIndexed(Resource resource) { Bucket bucket = getBucket(resource, true); if (bucket == null) { @@ -591,13 +610,9 @@ public class DefaultIndex extends SonarIndex { * @return */ private Bucket getBucket(Resource res) { - if (StringUtils.isNotBlank(res.getKey()) && StringUtils.isNotBlank(res.getDeprecatedKey())) { + if (StringUtils.isNotBlank(res.getKey())) { return buckets.get(res); } - // Squid compatibility fix (case 2) - if (StringUtils.isBlank(res.getDeprecatedKey())) { - res.setDeprecatedKey(res.getKey()); - } if (StringUtils.isNotBlank(res.getDeprecatedKey())) { // Fallback to use deprecated key for (Map.Entry entry : buckets.entrySet()) { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SquidUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SquidUtils.java index b514fb0a89b..3a280e2b792 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SquidUtils.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SquidUtils.java @@ -31,6 +31,10 @@ public final class SquidUtils { // only static methods } + /** + * @deprecated since 4.2 JavaFile is deprecated + */ + @Deprecated public static JavaFile convertJavaFileKeyFromSquidFormat(String key) { String extension = StringUtils.lowerCase(FilenameUtils.getExtension(key)); boolean isJavaFile = "jav".equals(extension) || "java".equals(extension); @@ -50,11 +54,10 @@ public final class SquidUtils { } /** - * @deprecated since 4.2 JavaPackage key is now the same than directory (ie path) + * @deprecated since 4.2 JavaPackage is deprecated */ @Deprecated public static JavaPackage convertJavaPackageKeyFromSquidFormat(String key) { - String convertedKey = key.replace('/', '.'); return new Directory(key); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Directory.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Directory.java index fee9e1d0599..d3ea1c9e17b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Directory.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Directory.java @@ -21,6 +21,7 @@ package org.sonar.api.resources; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.batch.SensorContext; import org.sonar.api.utils.WildcardPattern; /** @@ -37,19 +38,19 @@ public class Directory extends JavaPackage { } /** - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * @deprecated since 4.2 use {@link #create(String, String)} */ @Deprecated - public Directory(String deprecatedKey) { - this(deprecatedKey, null); + public Directory(String relativePathFromSourceDir) { + this(relativePathFromSourceDir, null); } /** - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * @deprecated since 4.2 use {@link #create(String, String)} */ @Deprecated - public Directory(String deprecatedKey, Language language) { - setDeprecatedKey(parseKey(deprecatedKey)); + public Directory(String relativePathFromSourceDir, Language language) { + setDeprecatedKey(parseKey(relativePathFromSourceDir)); } @Override @@ -105,15 +106,31 @@ public class Directory extends JavaPackage { return normalizedKey; } - public static Directory create(String path, String directoryDeprecatedKey) { + /** + * Create a Directory that is partially initialized. But that's enough to call for example + * {@link SensorContext#saveMeasure(Resource, org.sonar.api.measures.Measure)} when resources are already indexed. + * Internal use only. + * @since 4.2 + */ + public static Directory create(String relativePathFromBaseDir) { Directory d = new Directory(); - String normalizedPath = normalize(path); + String normalizedPath = normalize(relativePathFromBaseDir); d.setKey(normalizedPath); - d.setDeprecatedKey(parseKey(directoryDeprecatedKey)); d.setPath(normalizedPath); return d; } + /** + * Create a directory that is fully initialized. Use for indexing resources. + * Internal use only. + * @since 4.2 + */ + public static Directory create(String relativePathFromBaseDir, String relativePathFromSourceDir) { + Directory d = Directory.create(relativePathFromBaseDir); + d.setDeprecatedKey(parseKey(relativePathFromSourceDir)); + return d; + } + @Override public String toString() { return new ToStringBuilder(this) 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 b0701c368d4..475363fe6f2 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 @@ -21,6 +21,7 @@ package org.sonar.api.resources; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.batch.SensorContext; import org.sonar.api.scan.filesystem.PathResolver; import org.sonar.api.utils.WildcardPattern; @@ -49,58 +50,58 @@ public class File extends Resource { * 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 * to source directories. Example : new File("org/sonar/foo.sql"). The absolute path may be * c:/myproject/src/main/sql/org/sonar/foo.sql. Project root is c:/myproject and source dir is src/main/sql. - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)} */ @Deprecated - public File(String deprecatedKey) { - if (deprecatedKey == null) { + public File(String relativePathFromSourceDir) { + if (relativePathFromSourceDir == null) { throw new IllegalArgumentException("File key is null"); } - String realKey = parseKey(deprecatedKey); + String realKey = parseKey(relativePathFromSourceDir); if (realKey.indexOf(Directory.SEPARATOR) >= 0) { - this.directoryDeprecatedKey = Directory.parseKey(StringUtils.substringBeforeLast(deprecatedKey, Directory.SEPARATOR)); + this.directoryDeprecatedKey = Directory.parseKey(StringUtils.substringBeforeLast(relativePathFromSourceDir, Directory.SEPARATOR)); this.filename = StringUtils.substringAfterLast(realKey, Directory.SEPARATOR); realKey = new StringBuilder().append(this.directoryDeprecatedKey).append(Directory.SEPARATOR).append(filename).toString(); } else { - this.filename = deprecatedKey; + this.filename = relativePathFromSourceDir; } setDeprecatedKey(realKey); } /** * Creates a file from its containing directory and name - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)} */ @Deprecated - public File(String deprecatedDirectoryKey, String filename) { + public File(String relativeDirectoryPathFromSourceDir, String filename) { this.filename = StringUtils.trim(filename); - if (StringUtils.isBlank(deprecatedDirectoryKey)) { + if (StringUtils.isBlank(relativeDirectoryPathFromSourceDir)) { setDeprecatedKey(filename); } else { - this.directoryDeprecatedKey = Directory.parseKey(deprecatedDirectoryKey); + this.directoryDeprecatedKey = Directory.parseKey(relativeDirectoryPathFromSourceDir); setDeprecatedKey(new StringBuilder().append(directoryDeprecatedKey).append(Directory.SEPARATOR).append(this.filename).toString()); } } /** * Creates a File from its language and its key - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)} */ @Deprecated - public File(Language language, String deprecatedKey) { - this(deprecatedKey); + public File(Language language, String relativePathFromSourceDir) { + this(relativePathFromSourceDir); this.language = language; } /** * Creates a File from language, directory and filename - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)} */ @Deprecated - public File(Language language, String directory, String filename) { - this(directory, filename); + public File(Language language, String relativeDirectoryPathFromSourceDir, String filename) { + this(relativeDirectoryPathFromSourceDir, filename); this.language = language; } @@ -140,7 +141,7 @@ public class File extends Resource { /** * Creates a File from an io.file and a list of sources directories - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)} */ @Deprecated public static File fromIOFile(java.io.File file, List sourceDirs) { @@ -152,12 +153,17 @@ public class File extends Resource { } /** - * Creates a File from its name and a project - * @deprecated since 4.2 use {@link #create(String, String, Language, boolean)} + * Creates a SonarQube File from its Java IO File and a module. + * The returned SonarQube File is partially initialized. But that's enough to call for example + * {@link SensorContext#saveMeasure(Resource, org.sonar.api.measures.Measure)} when resources are already index. + * @return null if the file is not under module basedir. */ - @Deprecated - public static File fromIOFile(java.io.File file, Project project) { - return fromIOFile(file, project.getFileSystem().getSourceDirs()); + public static File fromIOFile(java.io.File file, Project module) { + String relativePathFromBasedir = new PathResolver().relativePath(module.getFileSystem().getBasedir(), file); + if (relativePathFromBasedir != null) { + return File.create(relativePathFromBasedir); + } + return null; } /** @@ -216,9 +222,7 @@ public class File extends Resource { } /** - * Returns the qualifier associated to this File. Should be QUALIFIER_FILE or - * - * @return QUALIFIER_UNIT_TEST_CLASS + * Returns the qualifier associated to this File. Should be QUALIFIER_FILE or QUALIFIER_UNIT_TEST_CLASS */ @Override public String getQualifier() { @@ -229,7 +233,13 @@ public class File extends Resource { this.qualifier = qualifier; } - public static File create(String relativePathFromBasedir, String relativePathFromSourceDir, Language language, boolean unitTest) { + /** + * Create a File that is partially initialized. But that's enough to call for example + * {@link SensorContext#saveMeasure(Resource, org.sonar.api.measures.Measure)} when resources are already indexed. + * Internal use only. + * @since 4.2 + */ + public static File create(String relativePathFromBasedir) { File file = new File(); String normalizedPath = normalize(relativePathFromBasedir); file.setKey(normalizedPath); @@ -240,6 +250,17 @@ public class File extends Resource { } else { directoryPath = Directory.SEPARATOR; } + file.parent = Directory.create(directoryPath); + return file; + } + + /** + * Create a file that is fully initialized. Use for indexing resources. + * Internal use only. + * @since 4.2 + */ + public static File create(String relativePathFromBasedir, String relativePathFromSourceDir, Language language, boolean unitTest) { + File file = create(relativePathFromBasedir); file.setLanguage(language); if (relativePathFromSourceDir.contains(Directory.SEPARATOR)) { file.filename = StringUtils.substringAfterLast(relativePathFromSourceDir, Directory.SEPARATOR); @@ -253,7 +274,7 @@ public class File extends Resource { if (unitTest) { file.setQualifier(Qualifiers.UNIT_TEST_FILE); } - file.parent = Directory.create(directoryPath, file.directoryDeprecatedKey); + file.parent.setDeprecatedKey(file.directoryDeprecatedKey); return file; } 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 770a58e9340..ecc675b5a6b 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 @@ -31,7 +31,9 @@ import java.util.List; * A class that represents a Java class. This class can either be a Test class or source class * * @since 1.10 + * @deprecated since 4.2 use {@link org.sonar.api.resources.File} */ +@Deprecated public class JavaFile extends Resource { private static final String JAVA_SUFFIX = ".java"; @@ -49,9 +51,7 @@ public class JavaFile extends Resource { /** * Creates a JavaFile that is not a class of test based on package and file names - * @deprecated since 4.2 use {@link #create(String, String, boolean)} */ - @Deprecated public JavaFile(String packageName, String className) { this(packageName, className, false); } @@ -60,9 +60,7 @@ public class JavaFile extends Resource { * Creates a JavaFile that can be of any type based on package and file names * * @param unitTest whether it is a unit test file or a source file - * @deprecated since 4.2 use {@link #create(String, String, boolean)} */ - @Deprecated public JavaFile(String packageKey, String className, boolean unitTest) { if (className == null) { throw new IllegalArgumentException("Java filename can not be null"); @@ -84,9 +82,7 @@ public class JavaFile extends Resource { /** * Creates a source file from its key - * @deprecated since 4.2 use {@link #create(String, String, boolean)} */ - @Deprecated public JavaFile(String deprecatedKey) { this(deprecatedKey, false); } @@ -95,9 +91,7 @@ public class JavaFile extends Resource { * Creates any JavaFile from its key * * @param unitTest whether it is a unit test file or a source file - * @deprecated since 4.2 use {@link #create(String, String, boolean)} */ - @Deprecated public JavaFile(String deprecatedKey, boolean unitTest) { if (deprecatedKey == null) { throw new IllegalArgumentException("Java filename can not be null"); @@ -194,10 +188,6 @@ public class JavaFile extends Resource { return matcher.match(getKey()); } - /** - * @deprecated since 4.2 use {@link #create(String, String, boolean)} - */ - @Deprecated public static JavaFile fromIOFile(File file, Project module, boolean unitTest) { if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), JAVA_SUFFIX)) { return null; @@ -234,6 +224,9 @@ public class JavaFile extends Resource { return javaFile; } + /** + * For internal use only. + */ public static JavaFile create(String relativePathFromBasedir, String relativePathFromSourceDir, boolean unitTest) { JavaFile javaFile = JavaFile.create(relativePathFromBasedir); if (relativePathFromSourceDir.contains(Directory.SEPARATOR)) { -- 2.39.5