diff options
Diffstat (limited to 'sonar-plugin-api/src/main/java/org/sonar/api/resources')
16 files changed, 2427 insertions, 0 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/AbstractLanguage.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/AbstractLanguage.java new file mode 100644 index 00000000000..26fe63effe9 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/AbstractLanguage.java @@ -0,0 +1,93 @@ +/* + * 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.api.resources; + +/** + * Inherit this class to define a new language like PLSQL, PHP or C# + * + * @since 1.10 + */ +public abstract class AbstractLanguage implements Language { + private final String key; + private String name; + + /** + * Better to use AbstractLanguage(key, name). In this case, key and name will be the same + */ + public AbstractLanguage(String key) { + this(key, key); + } + + /** + * Should be the constructor used to build an AbstractLanguage. + * + * @param key the key that will be used to retrieve the language. This key is important as it will be used to teint rules repositories... + * @param name the display name of the language in the interface + */ + public AbstractLanguage(String key, String name) { + this.key = key.toLowerCase(); + this.name = name; + } + + /** + * {@inheritDoc} + */ + public String getKey() { + return key; + } + + /** + * {@inheritDoc} + */ + public String getName() { + return name; + } + + /** + * Sets the language name + */ + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Language language = (Language) o; + return !(key != null ? !key.equals(language.getKey()) : language.getKey() != null); + + } + + @Override + public int hashCode() { + return (key != null ? key.hashCode() : 0); + } + + @Override + public String toString() { + return name; + } +} 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 new file mode 100644 index 00000000000..1c04e67b0a5 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java @@ -0,0 +1,350 @@ +/* + * 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.api.resources; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.filefilter.*; +import org.apache.commons.lang.CharEncoding; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.batch.maven.MavenUtils; +import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.WildcardPattern; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * An implementation of ProjectFileSystem + * + * @since 1.10 + */ +public class DefaultProjectFileSystem implements ProjectFileSystem { + + private Project project; + + /** + * Creates a DefaultProjectFileSystem based on a project + * + * @param project + */ + public DefaultProjectFileSystem(Project project) { + this.project = project; + } + + /** + * Source encoding. Never null, it returns the default plateform charset if it is not defined in project. + */ + public Charset getSourceCharset() { + return MavenUtils.getSourceCharset(project.getPom()); + } + + + /** + * Basedir is the project root directory. + */ + public File getBasedir() { + return project.getPom().getBasedir(); + } + + /** + * Build directory is by default "target" in maven projects. + */ + public File getBuildDir() { + return resolvePath(project.getPom().getBuild().getDirectory()); + } + + /** + * Directory where classes are placed. By default "target/classes" in maven projects. + */ + public File getBuildOutputDir() { + return resolvePath(project.getPom().getBuild().getOutputDirectory()); + } + + /** + * The list of directories for sources + */ + public List<File> getSourceDirs() { + return resolvePaths(project.getPom().getCompileSourceRoots()); + } + + /** + * Adds a source directory + * + * @return the current object + */ + public DefaultProjectFileSystem addSourceDir(File dir) { + if (dir == null) { + throw new IllegalArgumentException("Can not add null to project source dirs"); + } + project.getPom().getCompileSourceRoots().add(0, dir.getAbsolutePath()); + return this; + } + + /** + * The list of directories for tests + */ + public List<File> getTestDirs() { + return resolvePaths(project.getPom().getTestCompileSourceRoots()); + } + + /** + * Adds a test directory + * + * @return the current object + */ + public DefaultProjectFileSystem addTestDir(File dir) { + if (dir == null) { + throw new IllegalArgumentException("Can not add null to project test dirs"); + } + project.getPom().getTestCompileSourceRoots().add(0, dir.getAbsolutePath()); + return this; + } + + /** + * @return the directory where reporting is placed. Default is target/sites + */ + public File getReportOutputDir() { + return resolvePath(project.getPom().getReporting().getOutputDirectory()); + } + + /** + * @return the Sonar working directory. Default is "target/sonar" + */ + public File getSonarWorkingDirectory() { + try { + File dir = new File(project.getPom().getBuild().getDirectory(), "sonar"); + FileUtils.forceMkdir(dir); + return dir; + + } catch (IOException e) { + throw new SonarException("Unable to retrieve Sonar working directory.", e); + } + } + + public File resolvePath(String path) { + File file = new File(path); + if (!file.isAbsolute()) { + file = new File(project.getPom().getBasedir(), path); + } + return file; + } + + private List<File> resolvePaths(List<String> paths) { + List<File> result = new ArrayList<File>(); + if (paths != null) { + for (String path : paths) { + result.add(resolvePath(path)); + } + } + + return result; + } + + /** + * Gets the list of source files for given languages + * + * @param langs language filter. If null or empty, will return empty list + */ + public List<File> getSourceFiles(Language... langs) { + return getFiles(getSourceDirs(), true, langs); + } + + /** + * Gets the list of java source files + */ + public List<File> getJavaSourceFiles() { + return getSourceFiles(Java.INSTANCE); + } + + /** + * @return whether there are java source + */ + public boolean hasJavaSourceFiles() { + return !getJavaSourceFiles().isEmpty(); + } + + /** + * Gets the list of test files for given languages + * + * @param langs language filter. If null or empty, will return empty list + */ + public List<File> getTestFiles(Language... langs) { + return getFiles(getTestDirs(), false, langs); + } + + /** + * @return whether there are tests files + */ + public boolean hasTestFiles(Language lang) { + return !getTestFiles(lang).isEmpty(); + } + + private List<File> getFiles(List<File> directories, boolean applyExclusionPatterns, Language... langs) { + List<File> result = new ArrayList<File>(); + if (directories == null) { + return result; + } + + IOFileFilter suffixFilter = getFileSuffixFilter(langs); + WildcardPattern[] exclusionPatterns = getExclusionPatterns(applyExclusionPatterns); + + for (File dir : directories) { + if (dir.exists()) { + IOFileFilter exclusionFilter = new ExclusionFilter(dir, exclusionPatterns); + IOFileFilter visibleFileFilter = HiddenFileFilter.VISIBLE; + AndFileFilter filters = new AndFileFilter(new AndFileFilter(exclusionFilter, suffixFilter), visibleFileFilter); + result.addAll(FileUtils.listFiles(dir, filters, HiddenFileFilter.VISIBLE)); + } + } + return result; + } + + private WildcardPattern[] getExclusionPatterns(boolean applyExclusionPatterns) { + WildcardPattern[] exclusionPatterns; + if (applyExclusionPatterns) { + exclusionPatterns = WildcardPattern.create(project.getExclusionPatterns()); + } else { + exclusionPatterns = new WildcardPattern[0]; + } + return exclusionPatterns; + } + + private IOFileFilter getFileSuffixFilter(Language... langs) { + IOFileFilter suffixFilter = FileFilterUtils.trueFileFilter(); + if (langs != null && langs.length>0) { + List<String> suffixes = new ArrayList<String>(); + for (Language lang : langs) { + if (lang.getFileSuffixes() != null) { + suffixes.addAll(Arrays.asList(lang.getFileSuffixes())); + } + } + if (!suffixes.isEmpty()) { + suffixFilter = new SuffixFileFilter(suffixes); + } + } + + return suffixFilter; + } + + private static class ExclusionFilter implements IOFileFilter { + File sourceDir; + WildcardPattern[] patterns; + + ExclusionFilter(File sourceDir, WildcardPattern[] patterns) { + this.sourceDir = sourceDir; + this.patterns = patterns; + } + + public boolean accept(File file) { + String relativePath = getRelativePath(file, sourceDir); + if (relativePath == null) { + return false; + } + for (WildcardPattern pattern : patterns) { + if (pattern.match(relativePath)) { + return false; + } + } + return true; + } + + public boolean accept(File file, String name) { + return accept(file); + } + } + + /** + * Save data into a new file of Sonar working directory. + * + * @return the created file + */ + public File writeToWorkingDirectory(String content, String fileName) throws IOException { + return writeToFile(content, getSonarWorkingDirectory(), fileName); + } + + protected static File writeToFile(String content, File dir, String fileName) throws IOException { + File file = new File(dir, fileName); + FileUtils.writeStringToFile(file, content, CharEncoding.UTF_8); + return file; + } + + /** + * getRelativePath("c:/foo/src/my/package/Hello.java", "c:/foo/src") is "my/package/Hello.java" + * + * @return null if file is not in dir (including recursive subdirectories) + */ + public static String getRelativePath(File file, File dir) { + return getRelativePath(file, Arrays.asList(dir)); + } + + /** + * getRelativePath("c:/foo/src/my/package/Hello.java", ["c:/bar", "c:/foo/src"]) is "my/package/Hello.java". + * <p/> + * <p>Relative path is composed of slashes. Windows backslaches are replaced by /</p> + * + * @return null if file is not in dir (including recursive subdirectories) + */ + public static String getRelativePath(File file, List<File> dirs) { + List<String> stack = new ArrayList<String>(); + String path = FilenameUtils.normalize(file.getAbsolutePath()); + File cursor = new File(path); + while (cursor != null) { + if (containsFile(dirs, cursor)) { + return StringUtils.join(stack, "/"); + } + stack.add(0, cursor.getName()); + cursor = cursor.getParentFile(); + } + return null; + } + + public File getFileFromBuildDirectory(String filename) { + File file = new File(getBuildDir(), filename); + return (file.exists() ? file : null); + } + + public Resource toResource(File file) { + if (file == null || !file.exists()) { + return null; + } + + String relativePath = getRelativePath(file, getSourceDirs()); + if (relativePath == null) { + return null; + } + + return (file.isFile() ? new org.sonar.api.resources.File(relativePath) : new org.sonar.api.resources.Directory(relativePath)); + } + + private static boolean containsFile(List<File> dirs, File cursor) { + for (File dir : dirs) { + if (FilenameUtils.equalsNormalizedOnSystem(dir.getAbsolutePath(), cursor.getAbsolutePath())) { + return true; + } + } + return false; + } + +} 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 new file mode 100644 index 00000000000..ebf2b745c42 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Directory.java @@ -0,0 +1,97 @@ +/* + * 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.api.resources; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.utils.WildcardPattern; + +/** + * @since 1.10 + */ +public class Directory extends Resource { + + public static final String SEPARATOR = "/"; + public static final String ROOT = "[root]"; + + private Language language; + + public Directory(String key) { + this(key, null); + } + + public Directory(String key, Language language) { + setKey(parseKey(key)); + this.language = language; + } + + public String getName() { + return getKey(); + } + + public String getLongName() { + return null; + } + + public String getDescription() { + return null; + } + + public Language getLanguage() { + return language; + } + + public String getScope() { + return Resource.SCOPE_SPACE; + } + + public String getQualifier() { + return Resource.QUALIFIER_DIRECTORY; + } + + public Resource getParent() { + return null; + } + + public boolean matchFilePattern(String antPattern) { + WildcardPattern matcher = WildcardPattern.create(antPattern, "/"); + return matcher.match(getKey()); + } + + public static String parseKey(String key) { + if (StringUtils.isBlank(key)) { + return ROOT; + } + + key = key.replace('\\', '/'); + key = StringUtils.trim(key); + key = StringUtils.removeStart(key, Directory.SEPARATOR); + key = StringUtils.removeEnd(key, Directory.SEPARATOR); + return key; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("key", getKey()) + .append("language", language) + .toString(); + } +} 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 new file mode 100644 index 00000000000..5d7fb94d212 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java @@ -0,0 +1,207 @@ +/* + * 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.api.resources; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.utils.WildcardPattern; + +import java.util.List; + +/** + * This class is an implementation of a resource of type FILE + * @since 1.10 + */ +public class File extends Resource<Directory> { + + private String directoryKey; + private String filename; + private Language language; + private Directory parent; + + /** + * 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 : <code>new File("org/sonar/foo.sql")</code>. 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. + */ + public File(String key) { + if (key == null) { + throw new IllegalArgumentException("File key is null"); + } + String realKey = parseKey(key); + if (realKey.indexOf(Directory.SEPARATOR) >= 0) { + this.directoryKey = Directory.parseKey(StringUtils.substringBeforeLast(key, Directory.SEPARATOR)); + this.filename = StringUtils.substringAfterLast(realKey, Directory.SEPARATOR); + realKey = new StringBuilder().append(this.directoryKey).append(Directory.SEPARATOR).append(filename).toString(); + + } else { + this.filename = key; + } + setKey(realKey); + } + + /** + * Creates a file from its containing directory and name + */ + public File(String directory, String filename) { + this.filename = StringUtils.trim(filename); + if (StringUtils.isBlank(directory)) { + setKey(filename); + + } else { + this.directoryKey = Directory.parseKey(directory); + setKey(new StringBuilder().append(directoryKey).append(Directory.SEPARATOR).append(this.filename).toString()); + } + } + + /** + * Creates a File from its language and its key + */ + public File(Language language, String key) { + this(key); + this.language = language; + } + + /** + * Creates a File from language, directory and filename + */ + public File(Language language, String directory, String filename) { + this(directory, filename); + this.language = language; + } + + /** + * {@inheritDoc} + * + * @see Resource#getParent() + */ + public Directory getParent() { + if (parent == null) { + parent = new Directory(directoryKey); + } + return parent; + } + + private static String parseKey(String key) { + if (StringUtils.isBlank(key)) { + return null; + } + + key = key.replace('\\', '/'); + key = StringUtils.trim(key); + return key; + } + + /** + * {@inheritDoc} + * + * @see Resource#matchFilePattern(String) + */ + public boolean matchFilePattern(String antPattern) { + WildcardPattern matcher = WildcardPattern.create(antPattern, "/"); + return matcher.match(getKey()); + } + + /** + * Creates a File from an io.file and a list of sources directories + */ + public static File fromIOFile(java.io.File file, List<java.io.File> sourceDirs) { + String relativePath = DefaultProjectFileSystem.getRelativePath(file, sourceDirs); + if (relativePath != null) { + return new File(relativePath); + } + return null; + } + + /** + * Creates a File from its name and a project + */ + public static File fromIOFile(java.io.File file, Project project) { + return fromIOFile(file, project.getFileSystem().getSourceDirs()); + } + + /** + * {@inheritDoc} + * + * @see Resource#getName() + */ + public String getName() { + return filename; + } + + /** + * {@inheritDoc} + * + * @see Resource#getLongName() + */ + public String getLongName() { + return getKey(); + } + + /** + * {@inheritDoc} + * + * @see Resource#getDescription() + */ + public String getDescription() { + return null; + } + + /** + * {@inheritDoc} + * + * @see Resource#getLanguage() + */ + public Language getLanguage() { + return language; + } + + /** + * Sets the language of the file + */ + public void setLanguage(Language language) { + this.language = language; + } + + /** + * @return SCOPE_ENTITY + */ + public String getScope() { + return Resource.SCOPE_ENTITY; + } + + /** + * @return QUALIFIER_FILE + */ + public String getQualifier() { + return Resource.QUALIFIER_FILE; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("key", getKey()) + .append("dir", directoryKey) + .append("filename", filename) + .append("language", language) + .toString(); + } +}
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Java.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Java.java new file mode 100644 index 00000000000..4f5f22c683e --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Java.java @@ -0,0 +1,60 @@ +/* + * 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.api.resources; + +/** + * Java language implementation + * + * @since 1.10 + */ +public class Java extends AbstractLanguage { + + public static final Java INSTANCE = new Java(); + + /** + * Java key + */ + public static final String KEY = "java"; + /** + * Default package name for classes without package def + */ + public static final String DEFAULT_PACKAGE_NAME = "[default]"; + /** + * Java files knows suffixes + */ + public static final String[] SUFFIXES = {"java", "jav"}; + + /** + * Default constructor + */ + public Java() { + super(KEY, "Java"); + } + + /** + * {@inheritDoc} + * + * @see AbstractLanguage#getFileSuffixes() + */ + public String[] getFileSuffixes() { + return SUFFIXES; + } + +} 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 new file mode 100644 index 00000000000..c2ece8bbb35 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java @@ -0,0 +1,233 @@ +/* + * 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.api.resources; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.utils.WildcardPattern; + +import java.io.File; +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 + */ +public class JavaFile extends Resource<JavaPackage> { + + private String filename; + private String longName; + private String packageKey; + private boolean unitTest; + private JavaPackage parent = null; + + /** + * Creates a JavaFile that is not a class of test based on package and file names + */ + public JavaFile(String packageName, String className) { + this(packageName, className, false); + } + + /** + * 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 + */ + public JavaFile(String packageKey, String className, boolean unitTest) { + if (className==null) { + throw new IllegalArgumentException("Java filename can not be null"); + } + if (className.indexOf('$') >= 0) { + throw new IllegalArgumentException("Java inner classes are not supported : " + className); + } + this.filename = StringUtils.trim(className); + String key; + if (StringUtils.isBlank(packageKey)) { + this.packageKey = JavaPackage.DEFAULT_PACKAGE_NAME; + this.longName = this.filename; + key = new StringBuilder().append(this.packageKey).append(".").append(this.filename).toString(); + } else { + this.packageKey = packageKey.trim(); + key = new StringBuilder().append(this.packageKey).append(".").append(this.filename).toString(); + this.longName = key; + } + setKey(key); + this.unitTest = unitTest; + } + + /** + * Creates a source file from its key + */ + public JavaFile(String key) { + this(key, false); + } + + /** + * Creates any JavaFile from its key + * + * @param unitTest whether it is a unit test file or a source file + */ + public JavaFile(String key, boolean unitTest) { + if (key==null) { + throw new IllegalArgumentException("Java filename can not be null"); + } + if (key != null && key.indexOf('$') >= 0) { + throw new IllegalArgumentException("Java inner classes are not supported : " + key); + } + String realKey = StringUtils.trim(key); + this.unitTest = unitTest; + + if (realKey.contains(".")) { + this.filename = StringUtils.substringAfterLast(realKey, "."); + this.packageKey = StringUtils.substringBeforeLast(realKey, "."); + this.longName = realKey; + + } else { + this.filename = realKey; + this.longName = realKey; + this.packageKey = JavaPackage.DEFAULT_PACKAGE_NAME; + realKey = new StringBuilder().append(JavaPackage.DEFAULT_PACKAGE_NAME).append(".").append(realKey).toString(); + } + setKey(realKey); + } + + /** + * {@inheritDoc} + */ + public JavaPackage getParent() { + if (parent == null) { + parent = new JavaPackage(packageKey); + } + return parent; + } + + /** + * @return null + */ + public String getDescription() { + return null; + } + + /** + * @return Java + */ + public Language getLanguage() { + return Java.INSTANCE; + } + + /** + * {@inheritDoc} + */ + public String getName() { + return filename; + } + + /** + * {@inheritDoc} + */ + public String getLongName() { + return longName; + } + + /** + * @return SCOPE_ENTITY + */ + public String getScope() { + return Resource.SCOPE_ENTITY; + } + + /** + * @return QUALIFIER_UNIT_TEST_CLASS or QUALIFIER_CLASS depending whether it is a unit test class + */ + public String getQualifier() { + return unitTest ? Resource.QUALIFIER_UNIT_TEST_CLASS : Resource.QUALIFIER_CLASS; + } + + /** + * @return whether the JavaFile is a unit test class or not + */ + public boolean isUnitTest() { + return unitTest; + } + + /** + * {@inheritDoc} + */ + public boolean matchFilePattern(String antPattern) { + if (unitTest) { + return false; + } + String fileKey = getKey(); + if (!fileKey.endsWith(".java")) { + fileKey += ".java"; + } + 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); + if (relativePath != null) { + String pacname = null; + String classname = relativePath; + + if (relativePath.indexOf('/') >= 0) { + pacname = StringUtils.substringBeforeLast(relativePath, "/"); + pacname = StringUtils.replace(pacname, "/", "."); + classname = StringUtils.substringAfterLast(relativePath, "/"); + } + classname = StringUtils.substringBeforeLast(classname, "."); + return new JavaFile(pacname, classname, unitTest); + } + return null; + } + + /** + * Shortcut to fromIOFile with an abolute path + */ + public static JavaFile fromAbsolutePath(String path, List<File> sourceDirs, boolean unitTest) { + if (path == null) { + return null; + } + return fromIOFile(new File(path), sourceDirs, unitTest); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("key", getKey()) + .append("package", packageKey) + .append("longName", longName) + .append("unitTest", unitTest) + .toString(); + } +} 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 new file mode 100644 index 00000000000..ef3aa1fc236 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java @@ -0,0 +1,122 @@ +/* + * 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.api.resources; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.utils.WildcardPattern; + +/** + * A class that represents a Java package in Sonar + * + * @since 1.10 + */ +public class JavaPackage extends Resource { + + /** + * Default package name for classes without package definition + */ + public static final String DEFAULT_PACKAGE_NAME = "[default]"; + + /** + * Defaul constructor + */ + public JavaPackage() { + this(null); + } + + /** + * Creates a JavaPackage from its key. Will use DEFAULT_PACKAGE_NAME if key is null + */ + public JavaPackage(String key) { + setKey(StringUtils.defaultIfEmpty(StringUtils.trim(key), DEFAULT_PACKAGE_NAME)); + } + + /** + * @return whether the JavaPackage key is the defult key + */ + public boolean isDefault() { + return StringUtils.equals(getKey(), DEFAULT_PACKAGE_NAME); + } + + /** + * {@inheritDoc} + */ + public boolean matchFilePattern(String antPattern) { + return false; + } + + /** + * {@inheritDoc} + */ + public String getDescription() { + return null; + } + + /** + * @return SCOPE_SPACE + */ + public String getScope() { + return Resource.SCOPE_SPACE; + } + + /** + * @return QUALIFIER_PACKAGE + */ + public String getQualifier() { + return Resource.QUALIFIER_PACKAGE; + } + + /** + * {@inheritDoc} + */ + public String getName() { + return getKey(); + } + + /** + * {@inheritDoc} + */ + public Resource<?> getParent() { + return null; + } + + /** + * {@inheritDoc} + */ + public String getLongName() { + return null; + } + + /** + * @return Java + */ + public Language getLanguage() { + return Java.INSTANCE; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("id", getId()) + .append("key", getKey()) + .toString(); + } +}
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java new file mode 100644 index 00000000000..a86ffb650e5 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java @@ -0,0 +1,47 @@ +/* + * 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.api.resources; + +import org.sonar.api.BatchExtension; +import org.sonar.api.ServerExtension; + +/** + * The extension point to define a new language + * + * @since 1.10 + */ +public interface Language extends BatchExtension, ServerExtension { + + /** + * For example "java". Should not be more than 5 chars. + */ + String getKey(); + + /** + * For example "Java" + */ + String getName(); + + /** + * For example ["jav","java"]. If empty, then all files in source directories are considered as sources. + */ + String[] getFileSuffixes(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Languages.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Languages.java new file mode 100644 index 00000000000..372100fe4ae --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Languages.java @@ -0,0 +1,77 @@ +/* + * 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.api.resources; + +import org.apache.commons.lang.ArrayUtils; +import org.sonar.api.BatchComponent; +import org.sonar.api.ServerComponent; + +import java.util.*; + +/** + * A class to store the list of languages + * + * @since 1.10 + */ +public class Languages implements BatchComponent, ServerComponent { + + private final Map<String, Language> map = new HashMap<String, Language>(); + + /** + * Creates a list of languages + */ + public Languages(Language... languages) { + if (languages != null) { + for (Language language : languages) { + map.put(language.getKey(), language); + } + } + } + + /** + * @param keys the languages keys + * @return * @return the list of suffix files associates to languages included in the current object + */ + + public String[] getSuffixes(String... keys) { + List<String> suffixes = new ArrayList<String>(); + + for (Map.Entry<String, Language> entry : map.entrySet()) { + if (ArrayUtils.isEmpty(keys) || ArrayUtils.contains(keys, entry.getKey())) { + suffixes.addAll(Arrays.asList(entry.getValue().getFileSuffixes())); + } + } + return suffixes.toArray(new String[suffixes.size()]); + } + + /** + * Return a language from the current object based on its key + */ + public Language get(String key) { + return map.get(key); + } + + /** + * Adds a language to the current object + */ + public void add(Language language) { + map.put(language.getKey(), language); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Library.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Library.java new file mode 100644 index 00000000000..84daac57437 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Library.java @@ -0,0 +1,121 @@ +/* + * 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.api.resources; + +import org.apache.commons.lang.builder.ToStringBuilder; + +public class Library extends Resource { + + private String name; + private String description; + private String version; + + public Library(String key, String version) { + setKey(key); + this.version = version; + } + + public String getVersion() { + return version; + } + + public Library setName(String name) { + this.name = name; + return this; + } + + public Library setDescription(String description) { + this.description = description; + return this; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getLongName() { + return null; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public Language getLanguage() { + return null; + } + + @Override + public String getScope() { + return Resource.SCOPE_PROJECT; + } + + @Override + public String getQualifier() { + return Resource.QUALIFIER_LIB; + } + + @Override + public Resource getParent() { + return null; + } + + @Override + public boolean matchFilePattern(String antPattern) { + return false; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Library library = (Library) o; + if (!getKey().equals(library.getKey())) { + return false; + } + return version.equals(library.version); + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + getKey().hashCode(); + result = 31 * result + version.hashCode(); + return result; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("key", getKey()) + .append("name", getName()) + .append("version", version) + .toString(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java new file mode 100644 index 00000000000..7e4371a0e1f --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java @@ -0,0 +1,412 @@ +/* + * 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.api.resources; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.maven.project.MavenProject; +import org.sonar.api.CoreProperties; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * A class that manipulates Projects in the Sonar way, i.e. mixing MavenProjects with the way it should be analyzed + * + * @since 1.10 + */ +public class Project extends Resource { + + /** + * @deprecated since version 1.11. Constant moved to CoreProperties + */ + @Deprecated + public static final String PARAM_VERSION = "sonar.projectVersion"; + + /** + * @deprecated since version 1.11. Constant moved to CoreProperties + */ + @Deprecated + public static final String PARAM_DATE = "sonar.projectDate"; + + /** + * @deprecated since version 1.11. Constant moved to CoreProperties + */ + @Deprecated + public static final String PARAM_LANGUAGE = "sonar.language"; + + /** + * @deprecated since version 1.11. Constant moved to CoreProperties + */ + @Deprecated + public static final String PARAM_DYNAMIC_ANALYSIS = "sonar.dynamicAnalysis"; + + /** + * @deprecated since version 1.11. Constant moved to CoreProperties + */ + @Deprecated + public static final String PARAM_EXCLUSIONS = "sonar.exclusions"; + + /** + * @deprecated since version 1.11. Constant moved to CoreProperties + */ + @Deprecated + public static final String PARAM_REUSE_RULES_CONFIG = "sonar.reuseExistingRulesConfiguration"; + + + /** + * Enumerates the type of possible analysis + */ + public enum AnalysisType { + STATIC, DYNAMIC, REUSE_REPORTS; + + /** + * @param includeReuseReportMode whether to count report reuse as dynamic or not + * @return whether this a dynamic analysis + */ + public boolean isDynamic(boolean includeReuseReportMode) { + return equals(Project.AnalysisType.DYNAMIC) || + (equals(Project.AnalysisType.REUSE_REPORTS) && includeReuseReportMode); + } + } + + private MavenProject pom; + private String branch; + private ProjectFileSystem fileSystem; + private Configuration configuration; + private String name; + private String description; + private String packaging; + private Language language; + private String languageKey; + private Date analysisDate; + private AnalysisType analysisType; + private String[] exclusionPatterns; + private String analysisVersion; + private boolean latestAnalysis; + + // modules tree + private Project parent; + private List<Project> modules = new ArrayList<Project>(); + + public Project(String key) { + setKey(key); + } + + public Project(String key, String branch, String name) { + if (StringUtils.isNotBlank(branch)) { + setKey(String.format("%s:%s", key, branch)); + this.name = String.format("%s %s", name, branch); + } else { + setKey(key); + this.name = name; + } + this.branch = branch; + } + + public String getBranch() { + return branch; + } + + public Project setBranch(String branch) { + this.branch = branch; + return this; + } + + public final Project setPom(MavenProject pom) { + this.pom = pom; + return this; + } + + /** + * @return the project's packaging + */ + public String getPackaging() { + return packaging; + } + + public String getName() { + return name; + } + + public String getLongName() { + return null; + } + + public String getDescription() { + return description; + } + + public Project setName(String name) { + this.name = name; + return this; + } + + public Project setDescription(String description) { + this.description = description; + return this; + } + + public Project setPackaging(String packaging) { + this.packaging = packaging; + return this; + } + + /** + * @return whether the current project is root project + */ + public boolean isRoot() { + return getParent() == null; + } + + public Project getRoot() { + return (parent == null ? this : parent.getRoot()); + } + + /** + * @return whether the current project is a module + */ + public boolean isModule() { + return !isRoot(); + } + + /** + * @return the type of analysis of the project + */ + public AnalysisType getAnalysisType() { + return analysisType; + } + + public Project setAnalysisType(AnalysisType at) { + this.analysisType = at; + return this; + } + + /** + * whether it's the latest analysis done on this project (displayed in sonar dashboard) or an analysis on a past revision. + * @since 2.0 + */ + public boolean isLatestAnalysis() { + return latestAnalysis; + } + + /** + * For internal use only. + */ + public Project setLatestAnalysis(boolean b) { + this.latestAnalysis = b; + return this; + } + + /** + * Used for Maven projects + */ + public String getGroupId() { + return pom.getGroupId(); + } + + /** + * Used for Maven projects + */ + public String getArtifactId() { + return pom.getArtifactId(); + } + + /** + * @return the project language + */ + public Language getLanguage() { + return language; + } + + public Project setLanguage(Language language) { + this.language = language; + return this; + } + + /** + * @return the language key + */ + public String getLanguageKey() { + return languageKey; + } + + /** + * For internal use only. + */ + public Project setLanguageKey(String languageKey) { + this.languageKey = languageKey; + return this; + } + + /** + * For internal use only. + */ + public Project setAnalysisDate(Date analysisDate) { + this.analysisDate = analysisDate; + return this; + } + + /** + * For internal use only. + */ + public Project setAnalysisVersion(String analysisVersion) { + this.analysisVersion = analysisVersion; + return this; + } + + /** + * @return the scope of the current object + */ + public String getScope() { + return SCOPE_SET; + } + + /** + * @return the qualifier of the current object + */ + public String getQualifier() { + return isRoot() ? QUALIFIER_PROJECT : QUALIFIER_MODULE; + } + + @Override + public boolean matchFilePattern(String antPattern) { + return false; + } + + public Project getParent() { + return parent; + } + + /** + * For internal use only. + */ + public Project setParent(Project parent) { + this.parent = parent; + if (parent != null) { + parent.modules.add(this); + } + return this; + } + + /** + * For internal use only. + */ + public void removeFromParent() { + if (parent!=null) { + parent.modules.remove(this); + } + } + + /** + * @return the list of modules + */ + public List<Project> getModules() { + return modules; + } + + /** + * @return whether to use external source for rules configuration + */ + public boolean getReuseExistingRulesConfig() { + return (configuration != null && configuration.getBoolean(CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY, false)); + } + + /** + * @return the current version of the project + */ + public String getAnalysisVersion() { + return analysisVersion; + } + + /** + * @return the analysis date, i.e. the date that will be used to store the snapshot + */ + public Date getAnalysisDate() { + return analysisDate; + } + + /** + * Patterns of resource exclusion as defined in project settings page. + */ + public String[] getExclusionPatterns() { + return exclusionPatterns; + } + + /** + * Set exclusion patterns. Configuration is not saved, so this method must be used ONLY IN UNIT TESTS. + */ + public Project setExclusionPatterns(String[] s) { + this.exclusionPatterns = s; + return this; + } + + public ProjectFileSystem getFileSystem() { + return fileSystem; + } + + public Project setFileSystem(ProjectFileSystem fs) { + this.fileSystem = fs; + return this; + } + + /** + * @return the underlying maven project + */ + public MavenProject getPom() { + return pom; + } + + /** + * @return the project configuration + */ + public Configuration getConfiguration() { + return configuration; + } + + /** + * Sets the configuration + * + * @return the current object + */ + public final Project setConfiguration(Configuration configuration) { + this.configuration = configuration; + return this; + } + + public Object getProperty(String key) { + return configuration != null ? configuration.getProperty(key) : null; + } + + public static Project createFromMavenIds(String groupId, String artifactId) { + return new Project(String.format("%s:%s", groupId, artifactId)); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("id", getId()) + .append("key", getKey()) + .append("qualifier", getQualifier()) + .toString(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java new file mode 100644 index 00000000000..24a47bfe1a0 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java @@ -0,0 +1,104 @@ +/* + * 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.api.resources; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; + +/** + * @since 1.10 + */ +public interface ProjectFileSystem { + /** + * Source encoding. It's the default plateform charset if it is not defined in the project + * (Maven property 'project.build.sourceEncoding'). + */ + Charset getSourceCharset(); + + /** + * Project root directory. + */ + File getBasedir(); + + /** + * Build directory. It's "${basedir}/target" by default in Maven projects. + */ + File getBuildDir(); + + File getBuildOutputDir(); + + List<File> getSourceDirs(); + + ProjectFileSystem addSourceDir(File dir); + + List<File> getTestDirs(); + + ProjectFileSystem addTestDir(File dir); + + File getReportOutputDir(); + + File getSonarWorkingDirectory(); + + /** + * Get file from path. It can be absolute or relative to project basedir. For example resolvePath("pom.xml") or resolvePath("src/main/java") + */ + File resolvePath(String path); + + /** + * Source files, excluding unit tests and files matching project exclusion patterns. + * + * @param langs language filter. Check all files, whatever their language, if null or empty. + */ + List<File> getSourceFiles(Language... langs); + + /** + * Java source files, excluding unit tests and files matching project exclusion patterns. + * Shortcut for getSourceFiles(Java.INSTANCE) + */ + List<File> getJavaSourceFiles(); + + /** + * Check if the project has Java files, excluding unit tests and files matching project exclusion patterns. + */ + boolean hasJavaSourceFiles(); + + /** + * Unit test files, excluding files matching project exclusion patterns. + */ + List<File> getTestFiles(Language... langs); + + /** + * Check if the project has unit test files, excluding files matching project exclusion patterns. + */ + boolean hasTestFiles(Language lang); + + /** + * Save data into a new file of Sonar working directory. + * + * @return the created file + */ + File writeToWorkingDirectory(String content, String fileName) throws IOException; + + File getFileFromBuildDirectory(String filename); + + Resource toResource(File file); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectLink.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectLink.java new file mode 100644 index 00000000000..f8353c02f0d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectLink.java @@ -0,0 +1,134 @@ +/* + * 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.api.resources; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.database.BaseIdentifiable; +import org.sonar.api.database.model.ResourceModel; + +import javax.persistence.*; + +/** + * @since 1.10 + */ +@Entity(name = "ProjectLink") +@Table(name = "project_links") +public class ProjectLink extends BaseIdentifiable { + + public static final int NAME_COLUMN_SIZE = 128; + public static final int HREF_COLUMN_SIZE = 2048; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "project_id", updatable = false, nullable = false) + private ResourceModel resource; + + @Column(name = "link_type", updatable = true, nullable = true, length = 20) + private String key; + + @Column(name = "name", updatable = true, nullable = true, length = NAME_COLUMN_SIZE) + private String name; + + @Column(name = "href", updatable = true, nullable = false, length = HREF_COLUMN_SIZE) + private String href; + + public ProjectLink() { + } + + public ProjectLink(String key, String name, String href) { + this.key = key; + setName(name); + setHref(href); + } + + public ResourceModel getResource() { + return resource; + } + + public void setResource(ResourceModel resource) { + this.resource = resource; + } + + public String getName() { + return name; + } + + public final void setName(String name) { + this.name = StringUtils.abbreviate(name, NAME_COLUMN_SIZE); + } + + public String getHref() { + return href; + } + + public final void setHref(String href) { + if (href == null) { + throw new IllegalArgumentException("ProjectLink.href can not be null"); + } + this.href = StringUtils.abbreviate(href, HREF_COLUMN_SIZE); + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ProjectLink that = (ProjectLink) o; + if (!key.equals(that.key)) { + return false; + } + return resource.equals(that.resource); + + } + + @Override + public int hashCode() { + int result = resource != null ? resource.hashCode() : 0; + result = 31 * result + key.hashCode(); + return result; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("key", key) + .append("name", name) + .append("href", href) + .append("resource", resource) + .toString(); + } + + public void copyFieldsFrom(ProjectLink link) { + this.name = link.getName(); + this.href = link.getHref(); + } +}
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectUtils.java new file mode 100644 index 00000000000..1ad585acbe3 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectUtils.java @@ -0,0 +1,43 @@ +/* + * 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.api.resources; + +import org.sonar.api.batch.maven.MavenUtils; + +/** + * @since 1.10 + */ +public final class ProjectUtils { + + private ProjectUtils() { + // utility class with only static methods + } + + /** + * Java version as defined in maven-compiler-plugin + */ + public static String getJavaVersion(Project project) { + return MavenUtils.getJavaVersion(project.getPom()); + } + + public static String getJavaSourceVersion(Project project) { + return MavenUtils.getJavaSourceVersion(project.getPom()); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Resource.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Resource.java new file mode 100644 index 00000000000..32862e6bd7d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Resource.java @@ -0,0 +1,197 @@ +/* + * 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.api.resources; + +/** + * The interface to implement to create a resource in Sonar + * + * @since 1.10 + */ +public abstract class Resource<PARENT extends Resource> { + + public static final String SCOPE_SET = "PRJ"; + public static final String SCOPE_SPACE = "DIR"; + public static final String SCOPE_ENTITY = "FIL"; + + /** + * Use SCOPE_SET instead + */ + @Deprecated + public static final String SCOPE_PROJECT = SCOPE_SET; + + /** + * Use SCOPE_SPACE instead + */ + @Deprecated + public static final String SCOPE_DIRECTORY = SCOPE_SPACE; + + /** + * Use SCOPE_ENTITY instead + */ + @Deprecated + public static final String SCOPE_FILE = SCOPE_ENTITY; + + + public static final String QUALIFIER_VIEW = "VW"; + public static final String QUALIFIER_SUBVIEW = "SVW"; + public static final String QUALIFIER_LIB = "LIB"; + public static final String QUALIFIER_PROJECT = "TRK"; + public static final String QUALIFIER_MODULE = "BRC"; + public static final String QUALIFIER_PACKAGE = "PAC"; + public static final String QUALIFIER_DIRECTORY = "DIR"; + public static final String QUALIFIER_FILE = "FIL"; + public static final String QUALIFIER_CLASS = "CLA"; + public static final String QUALIFIER_FIELD = "FLD"; + public static final String QUALIFIER_METHOD = "MET"; + public static final String QUALIFIER_UNIT_TEST_CLASS = "UTS"; + + /** + * Use QUALIFIER_PROJECT instead + */ + @Deprecated + public static final String QUALIFIER_PROJECT_TRUNK = QUALIFIER_PROJECT; + + /** + * Use QUALIFIER_MODULE instead + */ + @Deprecated + public static final String QUALIFIER_PROJECT_BRANCH = QUALIFIER_MODULE; + + private Integer id = null; + + private String key = null; + + private String effectiveKey = null; + + private boolean isExcluded = false; + + + /** + * @return the resource key + */ + public final String getKey() { + return key; + } + + protected void setKey(String s) { + this.key = s; + } + + /** + * @return the resource name + */ + public abstract String getName(); + + /** + * @return the resource long name + */ + public abstract String getLongName(); + + /** + * @return the resource description + */ + public abstract String getDescription(); + + /** + * @return the language + */ + public abstract Language getLanguage(); + + /** + * @return the scope + */ + public abstract String getScope(); + + /** + * @return the qualifier + */ + public abstract String getQualifier(); + + /** + * The parent is used to build the resources tree, for example for relations between classes, packages and projects. + * <p>Return null if the parent is the project.</p> + */ + public abstract PARENT getParent(); + + /** + * Check resource against an Ant pattern, like mypackag?/*Foo.java. It's used for example + * to match resource exclusions. + * + * @param antPattern Ant-like pattern (with **, * and ?). It includes file suffixes. + * @return true if the resource matches the Ant pattern + */ + public abstract boolean matchFilePattern(String antPattern); + + + public final Integer getId() { + return id; + } + + /** + * Internal use only + */ + public Resource setId(Integer id) { + this.id = id; + return this; + } + + public final String getEffectiveKey() { + return effectiveKey; + } + + /** + * Internal use only + */ + public final Resource setEffectiveKey(String effectiveKey) { + this.effectiveKey = effectiveKey; + return this; + } + + public final boolean isExcluded() { + return isExcluded; + } + + /** + * Internal use only + */ + public final Resource setExcluded(boolean b) { + isExcluded = b; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Resource resource = (Resource) o; + return key.equals(resource.key); + + } + + @Override + public int hashCode() { + return key.hashCode(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java new file mode 100644 index 00000000000..830478bede9 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java @@ -0,0 +1,130 @@ +/* + * 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.api.resources; + +/** + * @since 1.10 + */ +public final class ResourceUtils { + + private ResourceUtils() { + } + + /** + * @return whether the resource is a view + */ + public static boolean isView(Resource resource) { + return isSet(resource) && Resource.QUALIFIER_VIEW.equals(resource.getQualifier()); + } + + /** + * @return whether the resource is a subview (in the view tree) + */ + public static boolean isSubview(Resource resource) { + return isSet(resource) && Resource.QUALIFIER_SUBVIEW.equals(resource.getQualifier()); + } + + /** + * @return whether the resource is the root project + */ + public static boolean isRootProject(Resource resource) { + return Resource.QUALIFIER_PROJECT.equals(resource.getQualifier()); + } + + /** + * @return whther a resource is a maven module of project + */ + public static boolean isModuleProject(Resource resource) { + return Resource.QUALIFIER_MODULE.equals(resource.getQualifier()); + } + + /** + * @return whether a resource is a package + */ + public static boolean isPackage(Resource resource) { + return resource != null && Resource.QUALIFIER_PACKAGE.equals(resource.getQualifier()); + } + + + /** + * @return whether a resource is a set + */ + public static boolean isSet(Resource resource) { + return resource != null && Resource.SCOPE_SET.equals(resource.getScope()); + } + + /** + * @return whether a resource is a space + */ + public static boolean isSpace(Resource resource) { + return resource != null && Resource.SCOPE_SPACE.equals(resource.getScope()); + } + + /** + * @return whether a resource is an entity. + */ + public static boolean isEntity(Resource resource) { + return resource != null && Resource.SCOPE_ENTITY.equals(resource.getScope()); + } + + /** + * This method equal isRootProject(resource) or isModuleProject(resource) + */ + public static boolean isProject(Resource resource) { + return isSet(resource); + } + + /** + * Alias for isDirectory(resource) + */ + public static boolean isDirectory(Resource resource) { + return isSpace(resource); + } + + /** + * Alias for isEntity(resource) + */ + public static boolean isFile(Resource resource) { + return isEntity(resource); + } + + + /* QUALIFIERS */ + + /** + * @return whether a resource is a class + */ + public static boolean isClass(Resource resource) { + return Resource.QUALIFIER_CLASS.equals(resource.getQualifier()); + } + + + /** + * @return whether a resource is a unit test class + */ + public static boolean isUnitTestClass(Resource resource) { + return Resource.QUALIFIER_UNIT_TEST_CLASS.equals(resource.getQualifier()); + } + + + public static boolean isLibrary(Resource resource) { + return Resource.QUALIFIER_LIB.equals(resource.getQualifier()); + } +} |