From: Julien HENRY Date: Wed, 18 Jun 2014 08:10:36 +0000 (+0200) Subject: Try to improve performance of MeasurePersister X-Git-Tag: 4.4-RC1~348 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f3ce69889f1a33e07d81ba20e052eebe599a03bc;p=sonarqube.git Try to improve performance of MeasurePersister --- diff --git a/pom.xml b/pom.xml index 2b63e2a5021..907c04df713 100644 --- a/pom.xml +++ b/pom.xml @@ -813,7 +813,7 @@ org.mybatis mybatis - 3.2.2 + 3.2.7 org.picocontainer diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/Analyzer.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/Analyzer.java new file mode 100644 index 00000000000..612354560a3 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/Analyzer.java @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.analyzer; + +import org.sonar.batch.api.BatchExtension; + +/** + *

+ * An Analyzer is invoked once during the analysis of a project. The analyzer can parse a flat file, connect to a web server... Analyzers are + * used to add measure and issues at file level. + *

+ * + *

+ * For example the Cobertura Analyzer parses Cobertura report and saves the first-level of measures on files. + *

+ * + * @since 4.4 + */ +public interface Analyzer extends BatchExtension { + + /** + * Describe what this analyzer is doing. + * @return + */ + AnalyzerDescriptor describe(); + + /** + * The method that is going to be run when the analyzer is called + * + * @param context the context + */ + void analyse(AnalyzerContext context); + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/AnalyzerContext.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/AnalyzerContext.java new file mode 100644 index 00000000000..e29dfaf711d --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/AnalyzerContext.java @@ -0,0 +1,80 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.analyzer; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.batch.api.analyzer.issue.AnalyzerIssue; +import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure; +import org.sonar.batch.api.measures.Metric; + +import javax.annotation.CheckForNull; + +import java.io.Serializable; +import java.util.Collection; + +/** + * @since 4.4 + */ +public interface AnalyzerContext { + + // ----------- MEASURES -------------- + + /** + * Find a project measure. + */ + @CheckForNull + AnalyzerMeasure getMeasure(String metricKey); + + /** + * Find a project measure. + */ + @CheckForNull + AnalyzerMeasure getMeasure(Metric metric); + + /** + * Find a file measure. + */ + @CheckForNull + AnalyzerMeasure getMeasure(InputFile file, String metricKey); + + /** + * Find a file measure. + */ + @CheckForNull + AnalyzerMeasure getMeasure(InputFile file, Metric metric); + + /** + * Add a measure. + */ + void addMeasure(AnalyzerMeasure measure); + + // ----------- ISSUES -------------- + + /** + * Add an issue. + */ + void addIssue(AnalyzerIssue issue); + + /** + * Add a list of issues. + */ + void addIssues(Collection issues); + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/AnalyzerDescriptor.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/AnalyzerDescriptor.java new file mode 100644 index 00000000000..0b97200dd10 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/AnalyzerDescriptor.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.analyzer; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.batch.api.measures.Metric; + +import java.util.Arrays; +import java.util.Collection; + +public class AnalyzerDescriptor { + + private final String name; + private final Metric[] dependsOn; + private final Metric[] provides; + private final String[] languages; + private final InputFile.Type[] types; + + private AnalyzerDescriptor(Builder builder) { + this.name = builder.name; + this.dependsOn = builder.dependsOn != null ? builder.dependsOn : new Metric[0]; + this.provides = builder.provides != null ? builder.provides : new Metric[0]; + this.languages = builder.languages != null ? builder.languages : new String[0]; + this.types = builder.types; + } + + public String name() { + return name; + } + + public Metric[] dependsOn() { + return dependsOn; + } + + public Metric[] provides() { + return provides; + } + + public Collection languages() { + return Arrays.asList(languages); + } + + public InputFile.Type[] types() { + return types; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String name; + private Metric[] dependsOn; + private Metric[] provides; + private String[] languages; + private InputFile.Type[] types; + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder dependsOn(Metric... metrics) { + this.dependsOn = metrics; + return this; + } + + public Builder provides(Metric... metrics) { + this.provides = metrics; + return this; + } + + public Builder runOnLanguages(String... languageKeys) { + this.languages = languageKeys; + return this; + } + + public Builder runOnTypes(InputFile.Type... types) { + this.types = types; + return this; + } + + public AnalyzerDescriptor build() { + return new AnalyzerDescriptor(this); + } + + } + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/issue/AnalyzerIssue.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/issue/AnalyzerIssue.java new file mode 100644 index 00000000000..f39d88493fe --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/issue/AnalyzerIssue.java @@ -0,0 +1,126 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.analyzer.issue; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.batch.api.analyzer.Analyzer; +import org.sonar.batch.api.internal.Preconditions; +import org.sonar.batch.api.rules.RuleKey; + +import javax.annotation.Nullable; + +/** + * Issue reported by an {@link Analyzer} + * + * @since 4.4 + */ +public class AnalyzerIssue { + + private final InputFile inputFile; + private final RuleKey ruleKey; + private final String message; + private final Integer line; + private final Double effortToFix; + + private AnalyzerIssue(Builder builder) { + this.inputFile = builder.file; + this.ruleKey = builder.ruleKey; + this.message = builder.message; + this.line = builder.line; + this.effortToFix = builder.effortToFix; + } + + public static Builder builder() { + return new Builder(); + } + + @Nullable + public InputFile inputFile() { + return inputFile; + } + + public RuleKey ruleKey() { + return ruleKey; + } + + public String message() { + return message; + } + + public Integer line() { + return line; + } + + @Nullable + public Double effortToFix() { + return effortToFix; + } + + public static class Builder { + + private Boolean onProject = null; + private InputFile file; + private RuleKey ruleKey; + private String message; + private Integer line; + private Double effortToFix; + + public AnalyzerIssue build() { + return new AnalyzerIssue(this); + } + + public Builder ruleKey(RuleKey ruleKey) { + this.ruleKey = ruleKey; + return this; + } + + public Builder onFile(InputFile file) { + Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); + Preconditions.checkNotNull(file, "InputFile should be non null"); + this.file = file; + this.onProject = false; + return this; + } + + public Builder onProject() { + Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); + this.file = null; + this.onProject = true; + return this; + } + + public Builder atLine(int line) { + this.line = line; + return this; + } + + public Builder effortToFix(@Nullable Double effortToFix) { + this.effortToFix = effortToFix; + return this; + } + + public Builder message(String message) { + this.message = message; + return this; + } + + } + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/issue/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/issue/package-info.java new file mode 100644 index 00000000000..70a6600e6d1 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/issue/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.batch.api.analyzer.issue; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/measure/AnalyzerMeasure.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/measure/AnalyzerMeasure.java new file mode 100644 index 00000000000..3d74dca1b4c --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/measure/AnalyzerMeasure.java @@ -0,0 +1,129 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.analyzer.measure; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.batch.api.internal.Preconditions; +import org.sonar.batch.api.measures.Metric; + +import javax.annotation.Nullable; + +import java.io.Serializable; + +public class AnalyzerMeasure implements Serializable { + + private final InputFile inputFile; + private final String metricKey; + private final G value; + + private AnalyzerMeasure(Builder builder) { + Preconditions.checkNotNull(builder.value, "Measure value can't be null"); + Preconditions.checkNotNull(builder.metricKey, "Measure metricKey can't be null"); + this.inputFile = builder.file; + this.metricKey = builder.metricKey; + this.value = builder.value; + } + + @Nullable + public InputFile inputFile() { + return inputFile; + } + + public String metricKey() { + return metricKey; + } + + public Serializable value() { + return value; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private Boolean onProject = null; + private InputFile file; + private String metricKey; + private G value; + + public Builder onFile(InputFile file) { + Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); + Preconditions.checkNotNull(file, "InputFile should be non null"); + this.file = file; + this.onProject = false; + return this; + } + + public Builder onProject() { + Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); + this.file = null; + this.onProject = true; + return this; + } + + private Builder metricKey(String metricKey) { + Preconditions.checkState(metricKey != null, "Metric already defined"); + this.metricKey = metricKey; + return this; + } + + public Builder forMetric(Metric metric) { + return metricKey(metric.key()); + } + + public Builder withValue(G value) { + Preconditions.checkState(value != null, "Measure value already defined"); + Preconditions.checkNotNull(value, "Measure value can't be null"); + this.value = value; + return this; + } + + public AnalyzerMeasure build() { + return new AnalyzerMeasure(this); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof AnalyzerMeasure)) { + return false; + } + AnalyzerMeasure other = (AnalyzerMeasure) obj; + return metricKey.equals(other.metricKey) + && value.equals(other.value) + && (inputFile == null ? other.inputFile == null : inputFile.equals(other.inputFile)); + } + + @Override + public int hashCode() { + return metricKey.hashCode() + + value.hashCode() + + (inputFile != null ? inputFile.hashCode() : 0); + } + + @Override + public String toString() { + return "AnalyzerMeasure[" + (inputFile != null ? "inputFile=" + inputFile.toString() : "onProject") + + ",metricKey=" + metricKey + ",value=" + value + "]"; + } + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/measure/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/measure/package-info.java new file mode 100644 index 00000000000..b490662460a --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/measure/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.batch.api.analyzer.measure; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/package-info.java new file mode 100644 index 00000000000..5b72f8c6315 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/analyzer/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.batch.api.analyzer; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/FilenameUtils.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/FilenameUtils.java new file mode 100644 index 00000000000..0461255879b --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/FilenameUtils.java @@ -0,0 +1,244 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.internal; + +import java.io.File; + +/** + * Copied from commons io + * + */ +public class FilenameUtils { + + public static final char EXTENSION_SEPARATOR = '.'; + + private static final char UNIX_SEPARATOR = '/'; + + /** + * The Windows separator character. + */ + private static final char WINDOWS_SEPARATOR = '\\'; + + /** + * The system separator character. + */ + private static final char SYSTEM_SEPARATOR = File.separatorChar; + + /** + * The separator character that is the opposite of the system separator. + */ + private static final char OTHER_SEPARATOR; + static { + if (isSystemWindows()) { + OTHER_SEPARATOR = UNIX_SEPARATOR; + } else { + OTHER_SEPARATOR = WINDOWS_SEPARATOR; + } + } + + static boolean isSystemWindows() { + return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR; + } + + public static String normalize(String filename) { + return doNormalize(filename, UNIX_SEPARATOR, true); + } + + private static String doNormalize(String filename, char separator, boolean keepSeparator) { + if (filename == null) { + return null; + } + int size = filename.length(); + if (size == 0) { + return filename; + } + int prefix = getPrefixLength(filename); + if (prefix < 0) { + return null; + } + + char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy + filename.getChars(0, filename.length(), array, 0); + + // fix separators throughout + char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR; + for (int i = 0; i < array.length; i++) { + if (array[i] == otherSeparator) { + array[i] = separator; + } + } + + // add extra separator on the end to simplify code below + boolean lastIsDirectory = true; + if (array[size - 1] != separator) { + array[size++] = separator; + lastIsDirectory = false; + } + + // adjoining slashes + for (int i = prefix + 1; i < size; i++) { + if (array[i] == separator && array[i - 1] == separator) { + System.arraycopy(array, i, array, i - 1, size - i); + size--; + i--; + } + } + + // dot slash + for (int i = prefix + 1; i < size; i++) { + if (array[i] == separator && array[i - 1] == '.' && + (i == prefix + 1 || array[i - 2] == separator)) { + if (i == size - 1) { + lastIsDirectory = true; + } + System.arraycopy(array, i + 1, array, i - 1, size - i); + size -= 2; + i--; + } + } + + // double dot slash + outer: for (int i = prefix + 2; i < size; i++) { + if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' && + (i == prefix + 2 || array[i - 3] == separator)) { + if (i == prefix + 2) { + return null; + } + if (i == size - 1) { + lastIsDirectory = true; + } + int j; + for (j = i - 4; j >= prefix; j--) { + if (array[j] == separator) { + // remove b/../ from a/b/../c + System.arraycopy(array, i + 1, array, j + 1, size - i); + size -= i - j; + i = j + 1; + continue outer; + } + } + // remove a/../ from a/../c + System.arraycopy(array, i + 1, array, prefix, size - i); + size -= i + 1 - prefix; + i = prefix + 1; + } + } + + if (size <= 0) { // should never be less than 0 + return ""; + } + if (size <= prefix) { // should never be less than prefix + return new String(array, 0, size); + } + if (lastIsDirectory && keepSeparator) { + return new String(array, 0, size); // keep trailing separator + } + return new String(array, 0, size - 1); // lose trailing separator + } + + public static int getPrefixLength(String filename) { + if (filename == null) { + return -1; + } + int len = filename.length(); + if (len == 0) { + return 0; + } + char ch0 = filename.charAt(0); + if (ch0 == ':') { + return -1; + } + if (len == 1) { + if (ch0 == '~') { + return 2; // return a length greater than the input + } + return isSeparator(ch0) ? 1 : 0; + } else { + if (ch0 == '~') { + int posUnix = filename.indexOf(UNIX_SEPARATOR, 1); + int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1); + if (posUnix == -1 && posWin == -1) { + return len + 1; // return a length greater than the input + } + posUnix = posUnix == -1 ? posWin : posUnix; + posWin = posWin == -1 ? posUnix : posWin; + return Math.min(posUnix, posWin) + 1; + } + char ch1 = filename.charAt(1); + if (ch1 == ':') { + ch0 = Character.toUpperCase(ch0); + if (ch0 >= 'A' && ch0 <= 'Z') { + if (len == 2 || isSeparator(filename.charAt(2)) == false) { + return 2; + } + return 3; + } + return -1; + + } else if (isSeparator(ch0) && isSeparator(ch1)) { + int posUnix = filename.indexOf(UNIX_SEPARATOR, 2); + int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2); + if (posUnix == -1 && posWin == -1 || posUnix == 2 || posWin == 2) { + return -1; + } + posUnix = posUnix == -1 ? posWin : posUnix; + posWin = posWin == -1 ? posUnix : posWin; + return Math.min(posUnix, posWin) + 1; + } else { + return isSeparator(ch0) ? 1 : 0; + } + } + } + + private static boolean isSeparator(char ch) { + return ch == UNIX_SEPARATOR || ch == WINDOWS_SEPARATOR; + } + + public static String getExtension(String filename) { + if (filename == null) { + return null; + } + int index = indexOfExtension(filename); + if (index == -1) { + return ""; + } else { + return filename.substring(index + 1); + } + } + + public static int indexOfExtension(String filename) { + if (filename == null) { + return -1; + } + int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR); + int lastSeparator = indexOfLastSeparator(filename); + return lastSeparator > extensionPos ? -1 : extensionPos; + } + + public static int indexOfLastSeparator(String filename) { + if (filename == null) { + return -1; + } + int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR); + int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR); + return Math.max(lastUnixPos, lastWindowsPos); + } + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/Preconditions.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/Preconditions.java new file mode 100644 index 00000000000..75ac73f46f3 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/Preconditions.java @@ -0,0 +1,413 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.internal; + +import javax.annotation.Nullable; + +/** + * Copied from Guava + */ +public final class Preconditions { + private Preconditions() { + } + + /** + * Ensures the truth of an expression involving one or more parameters to the + * calling method. + * + * @param expression a boolean expression + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the + * calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will + * be converted to a string using {@link String#valueOf(Object)} + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument( + boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the + * calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the + * check fail. The message is formed by replacing each {@code %s} + * placeholder in the template with an argument. These are matched by + * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. + * Unmatched arguments will be appended to the formatted message in square + * braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message + * template. Arguments are converted to strings using + * {@link String#valueOf(Object)}. + * @throws IllegalArgumentException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code + * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let + * this happen) + */ + public static void checkArgument(boolean expression, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (!expression) { + throw new IllegalArgumentException( + format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling + * instance, but not involving any parameters to the calling method. + * + * @param expression a boolean expression + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState(boolean expression) { + if (!expression) { + throw new IllegalStateException(); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling + * instance, but not involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will + * be converted to a string using {@link String#valueOf(Object)} + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState( + boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling + * instance, but not involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the + * check fail. The message is formed by replacing each {@code %s} + * placeholder in the template with an argument. These are matched by + * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. + * Unmatched arguments will be appended to the formatted message in square + * braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message + * template. Arguments are converted to strings using + * {@link String#valueOf(Object)}. + * @throws IllegalStateException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code + * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let + * this happen) + */ + public static void checkState(boolean expression, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (!expression) { + throw new IllegalStateException( + format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures that an object reference passed as a parameter to the calling + * method is not null. + * + * @param reference an object reference + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling + * method is not null. + * + * @param reference an object reference + * @param errorMessage the exception message to use if the check fails; will + * be converted to a string using {@link String#valueOf(Object)} + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, @Nullable Object errorMessage) { + if (reference == null) { + throw new NullPointerException(String.valueOf(errorMessage)); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling + * method is not null. + * + * @param reference an object reference + * @param errorMessageTemplate a template for the exception message should the + * check fail. The message is formed by replacing each {@code %s} + * placeholder in the template with an argument. These are matched by + * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. + * Unmatched arguments will be appended to the formatted message in square + * braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message + * template. Arguments are converted to strings using + * {@link String#valueOf(Object)}. + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (reference == null) { + // If either of these parameters is null, the right thing happens anyway + throw new NullPointerException( + format(errorMessageTemplate, errorMessageArgs)); + } + return reference; + } + + /* + * All recent hotspots (as of 2009) *really* like to have the natural code + * + * if (guardExpression) { + * throw new BadException(messageExpression); + * } + * + * refactored so that messageExpression is moved to a separate + * String-returning method. + * + * if (guardExpression) { + * throw new BadException(badMsg(...)); + * } + * + * The alternative natural refactorings into void or Exception-returning + * methods are much slower. This is a big deal - we're talking factors of + * 2-8 in microbenchmarks, not just 10-20%. (This is a hotspot optimizer + * bug, which should be fixed, but that's a separate, big project). + * + * The coding pattern above is heavily used in java.util, e.g. in ArrayList. + * There is a RangeCheckMicroBenchmark in the JDK that was used to test this. + * + * But the methods in this class want to throw different exceptions, + * depending on the args, so it appears that this pattern is not directly + * applicable. But we can use the ridiculous, devious trick of throwing an + * exception in the middle of the construction of another exception. + * Hotspot is fine with that. + */ + + /** + * Ensures that {@code index} specifies a valid element in an array, + * list or string of size {@code size}. An element index may range from zero, + * inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list + * or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not + * less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex(int index, int size) { + return checkElementIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid element in an array, + * list or string of size {@code size}. An element index may range from zero, + * inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list + * or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not + * less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex( + int index, int size, @Nullable String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); + } + return index; + } + + private static String badElementIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index >= size + return format("%s (%s) must be less than size (%s)", desc, index, size); + } + } + + /** + * Ensures that {@code index} specifies a valid position in an array, + * list or string of size {@code size}. A position index may range from zero + * to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list + * or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is + * greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex(int index, int size) { + return checkPositionIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid position in an array, + * list or string of size {@code size}. A position index may range from zero + * to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list + * or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is + * greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex( + int index, int size, @Nullable String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); + } + return index; + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index > size + return format("%s (%s) must not be greater than size (%s)", + desc, index, size); + } + } + + /** + * Ensures that {@code start} and {@code end} specify a valid positions + * in an array, list or string of size {@code size}, and are in order. A + * position index may range from zero to {@code size}, inclusive. + * + * @param start a user-supplied index identifying a starting position in an + * array, list or string + * @param end a user-supplied index identifying a ending position in an array, + * list or string + * @param size the size of that array, list or string + * @throws IndexOutOfBoundsException if either index is negative or is + * greater than {@code size}, or if {@code end} is less than {@code start} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static void checkPositionIndexes(int start, int end, int size) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if (start < 0 || start > size) { + return badPositionIndex(start, size, "start index"); + } + if (end < 0 || end > size) { + return badPositionIndex(end, size, "end index"); + } + // end < start + return format("end index (%s) must not be less than start index (%s)", + end, start); + } + + /** + * Substitutes each {@code %s} in {@code template} with an argument. These + * are matched by position - the first {@code %s} gets {@code args[0]}, etc. + * If there are more arguments than placeholders, the unmatched arguments will + * be appended to the end of the formatted message in square braces. + * + * @param template a non-null string containing 0 or more {@code %s} + * placeholders. + * @param args the arguments to be substituted into the message + * template. Arguments are converted to strings using + * {@link String#valueOf(Object)}. Arguments can be null. + */ + static String format(String template, + @Nullable Object... args) { + template = String.valueOf(template); // null -> "null" + + // start substituting the arguments into the '%s' placeholders + StringBuilder builder = new StringBuilder( + template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + + // if we run out of placeholders, append the extra args in square braces + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + + return builder.toString(); + } +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/StringUtils.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/StringUtils.java new file mode 100644 index 00000000000..ab279ae34e5 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/StringUtils.java @@ -0,0 +1,140 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.internal; + +/** + * Copied from commons lang + */ +public class StringUtils { + + public static final String EMPTY = ""; + + public static String trim(String str) { + return str == null ? null : str.trim(); + } + + public static String removeStart(String str, String remove) { + if (isEmpty(str) || isEmpty(remove)) { + return str; + } + if (str.startsWith(remove)) { + return str.substring(remove.length()); + } + return str; + } + + public static String removeEnd(String str, String remove) { + if (isEmpty(str) || isEmpty(remove)) { + return str; + } + if (str.endsWith(remove)) { + return str.substring(0, str.length() - remove.length()); + } + return str; + } + + public static boolean isEmpty(String str) { + return str == null || str.length() == 0; + } + + public static boolean startsWithIgnoreCase(String str, String prefix) { + return startsWith(str, prefix, true); + } + + private static boolean startsWith(String str, String prefix, boolean ignoreCase) { + if (str == null || prefix == null) { + return (str == null && prefix == null); + } + if (prefix.length() > str.length()) { + return false; + } + return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length()); + } + + public static String substring(String str, int start) { + if (str == null) { + return null; + } + + // handle negatives, which means last n characters + if (start < 0) { + start = str.length() + start; // remember start is negative + } + + if (start < 0) { + start = 0; + } + if (start > str.length()) { + return EMPTY; + } + + return str.substring(start); + } + + public static boolean isBlank(String str) { + int strLen; + if (str == null || (strLen = str.length()) == 0) { + return true; + } + for (int i = 0; i < strLen; i++) { + if ((Character.isWhitespace(str.charAt(i)) == false)) { + return false; + } + } + return true; + } + + public static boolean isNotBlank(String str) { + return !StringUtils.isBlank(str); + } + + public static String removeEndIgnoreCase(String str, String remove) { + if (isEmpty(str) || isEmpty(remove)) { + return str; + } + if (endsWithIgnoreCase(str, remove)) { + return str.substring(0, str.length() - remove.length()); + } + return str; + } + + public static boolean endsWithIgnoreCase(String str, String suffix) { + return endsWith(str, suffix, true); + } + + private static boolean endsWith(String str, String suffix, boolean ignoreCase) { + if (str == null || suffix == null) { + return (str == null && suffix == null); + } + if (suffix.length() > str.length()) { + return false; + } + int strOffset = str.length() - suffix.length(); + return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length()); + } + + public static String lowerCase(String str) { + if (str == null) { + return null; + } + return str.toLowerCase(); + } + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/WildcardPattern.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/WildcardPattern.java new file mode 100644 index 00000000000..f179fd73571 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/WildcardPattern.java @@ -0,0 +1,205 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.internal; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * Implementation of Ant-style matching patterns. + * Contrary to other implementations (like AntPathMatcher from Spring Framework) it is based on {@link Pattern Java Regular Expressions}. + * To increase performance it holds an internal cache of all processed patterns. + *

+ * Following rules are applied: + *

    + *
  • ? matches single character
  • + *
  • * matches zero or more characters
  • + *
  • ** matches zero or more 'directories'
  • + *
+ *

+ *

+ * Some examples of patterns: + *

    + *
  • org/T?st.java - matches org/Test.java and also org/Tost.java
  • + *
  • org/*.java - matches all .java files in the org directory, + * e.g. org/Foo.java or org/Bar.java
  • + *
  • org/** - matches all files underneath the org directory, + * e.g. org/Foo.java or org/foo/bar.jsp
  • + *
  • org/**/Test.java - matches all Test.java files underneath the org directory, + * e.g. org/Test.java or org/foo/Test.java or org/foo/bar/Test.java
  • + *
  • org/**/*.java - matches all .java files underneath the org directory, + * e.g. org/Foo.java or org/foo/Bar.java or org/foo/bar/Baz.java
  • + *
+ *

+ *

+ * Another implementation, which is also based on Java Regular Expressions, can be found in + * FileUtil + * from IntelliJ OpenAPI. + *

+ * + */ +public class WildcardPattern { + + private static final Map CACHE = new HashMap(); + private static final String SPECIAL_CHARS = "()[]^$.{}+|"; + + private Pattern pattern; + private String stringRepresentation; + + protected WildcardPattern(String pattern, String directorySeparator) { + this.stringRepresentation = pattern; + this.pattern = Pattern.compile(toRegexp(pattern, directorySeparator)); + } + + private static String toRegexp(String antPattern, String directorySeparator) { + final String escapedDirectorySeparator = '\\' + directorySeparator; + + final StringBuilder sb = new StringBuilder(antPattern.length()); + + sb.append('^'); + + int i = antPattern.startsWith("/") || antPattern.startsWith("\\") ? 1 : 0; + while (i < antPattern.length()) { + final char ch = antPattern.charAt(i); + + if (SPECIAL_CHARS.indexOf(ch) != -1) { + // Escape regexp-specific characters + sb.append('\\').append(ch); + } else if (ch == '*') { + if (i + 1 < antPattern.length() && antPattern.charAt(i + 1) == '*') { + // Double asterisk + // Zero or more directories + if (i + 2 < antPattern.length() && isSlash(antPattern.charAt(i + 2))) { + sb.append("(?:.*").append(escapedDirectorySeparator).append("|)"); + i += 2; + } else { + sb.append(".*"); + i += 1; + } + } else { + // Single asterisk + // Zero or more characters excluding directory separator + sb.append("[^").append(escapedDirectorySeparator).append("]*?"); + } + } else if (ch == '?') { + // Any single character excluding directory separator + sb.append("[^").append(escapedDirectorySeparator).append("]"); + } else if (isSlash(ch)) { + // Directory separator + sb.append(escapedDirectorySeparator); + } else { + // Single character + sb.append(ch); + } + + i++; + } + + sb.append('$'); + + return sb.toString(); + } + + private static boolean isSlash(char ch) { + return ch == '/' || ch == '\\'; + } + + /** + * Returns string representation of this pattern. + * + * @since 2.5 + */ + @Override + public String toString() { + return stringRepresentation; + } + + /** + * Returns true if specified value matches this pattern. + */ + public boolean match(String value) { + value = StringUtils.removeStart(value, "/"); + value = StringUtils.removeEnd(value, "/"); + return pattern.matcher(value).matches(); + } + + /** + * Returns true if specified value matches one of specified patterns. + * + * @since 2.4 + */ + public static boolean match(WildcardPattern[] patterns, String value) { + for (WildcardPattern pattern : patterns) { + if (pattern.match(value)) { + return true; + } + } + return false; + } + + /** + * Creates pattern with "/" as a directory separator. + * + * @see #create(String, String) + */ + public static WildcardPattern create(String pattern) { + return create(pattern, "/"); + } + + /** + * Creates array of patterns with "/" as a directory separator. + * + * @see #create(String, String) + */ + public static WildcardPattern[] create(String[] patterns) { + if (patterns == null) { + return new WildcardPattern[0]; + } + WildcardPattern[] exclusionPAtterns = new WildcardPattern[patterns.length]; + for (int i = 0; i < patterns.length; i++) { + exclusionPAtterns[i] = create(patterns[i]); + } + return exclusionPAtterns; + } + + /** + * Creates pattern with specified separator for directories. + *

+ * This is used to match Java-classes, i.e. org.foo.Bar against org/**. + * However usage of character other than "/" as a directory separator is misleading and should be avoided, + * so method {@link #create(String)} is preferred over this one. + *

+ *

+ * Also note that no matter whether forward or backward slashes were used in the antPattern + * the returned pattern will use directorySeparator. + * Thus to match Windows-style path "dir\file.ext" against pattern "dir/file.ext" normalization should be performed. + *

+ */ + public static WildcardPattern create(String pattern, String directorySeparator) { + String key = pattern + directorySeparator; + WildcardPattern wildcardPattern = CACHE.get(key); + if (wildcardPattern == null) { + wildcardPattern = new WildcardPattern(pattern, directorySeparator); + CACHE.put(key, wildcardPattern); + } + return wildcardPattern; + } +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/package-info.java new file mode 100644 index 00000000000..9870b99bffc --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/internal/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.batch.api.internal; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/languages/Language.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/languages/Language.java new file mode 100644 index 00000000000..7dd6c8b4e6b --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/languages/Language.java @@ -0,0 +1,57 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.languages; + +import java.util.Arrays; +import java.util.Collection; + +public final class Language { + + private final String key, name; + private final String[] fileSuffixes; + + public Language(String key, String name, String... fileSuffixes) { + this.key = key; + this.name = name; + this.fileSuffixes = fileSuffixes; + } + + /** + * For example "java". + */ + public String key() { + return key; + } + + /** + * For example "Java" + */ + public String name() { + return name; + } + + /** + * For example ["jav", "java"]. + */ + public Collection fileSuffixes() { + return Arrays.asList(fileSuffixes); + } + +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/languages/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/languages/package-info.java new file mode 100644 index 00000000000..a36d1c13de5 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/languages/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.batch.api.languages; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/measures/Metric.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/measures/Metric.java new file mode 100644 index 00000000000..52dc17c1718 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/measures/Metric.java @@ -0,0 +1,29 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.measures; + +import java.io.Serializable; + +public interface Metric { + + Class type(); + + String key(); +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/measures/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/measures/package-info.java new file mode 100644 index 00000000000..e684b549c5f --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/measures/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.batch.api.measures; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/QProfile.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/QProfile.java new file mode 100644 index 00000000000..1d074e105f2 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/QProfile.java @@ -0,0 +1,43 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.rules; + +public class QProfile { + private final String name, language; + private final Integer version; + + public QProfile(String name, String language, Integer version) { + this.name = name; + this.language = language; + this.version = version; + } + + public String name() { + return name; + } + + public String language() { + return language; + } + + public Integer version() { + return version; + } +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/RuleKey.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/RuleKey.java new file mode 100644 index 00000000000..3af1337a752 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/RuleKey.java @@ -0,0 +1,90 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.api.rules; + +import java.io.Serializable; + +/** + * Key of a rule. Unique among all the rule repositories. + * + * @since 3.6 + */ +public class RuleKey implements Serializable { + private final String repository, rule; + + protected RuleKey(String repositoryKey, String ruleKey) { + this.repository = repositoryKey; + this.rule = ruleKey; + } + + /** + * Create a key. Parameters are NOT null. + */ + public static RuleKey of(String repository, String rule) { + return new RuleKey(repository, rule); + } + + /** + * Never null + */ + public String repository() { + return repository; + } + + /** + * Never null + */ + public String rule() { + return rule; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RuleKey ruleKey = (RuleKey) o; + if (!repository.equals(ruleKey.repository)) { + return false; + } + if (!rule.equals(ruleKey.rule)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = repository.hashCode(); + result = 31 * result + rule.hashCode(); + return result; + } + + /** + * Format is "repository:rule", for example "squid:AvoidCycle" + */ + @Override + public String toString() { + return String.format("%s:%s", repository, rule); + } +} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/package-info.java new file mode 100644 index 00000000000..d91eb3485c9 --- /dev/null +++ b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/rules/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.batch.api.rules; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java deleted file mode 100644 index d48e2253190..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api; - -/** - * Dependency Injection : all the classes implementing this interface are available in the batch IoC container. - * Just add a parameter to the constructor of your component. - * - * @since 4.4 - */ -public interface BatchComponent { -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java deleted file mode 100644 index 1a774a16f5d..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api; - - -/** - * Batch extension point. - * - * @since 4.4 - */ -public interface BatchExtension extends BatchComponent { - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java deleted file mode 100644 index 521c6ddd61f..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Define instantiation strategy of batch extensions. If an extension is not annotated, then default value - * is {@link #PER_PROJECT}. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface InstantiationStrategy { - - /** - * Shared extension. Lifecycle is the full analysis. - */ - String PER_BATCH = "PER_BATCH"; - - /** - * Created and initialized for each project and sub-project (a project is a module in Maven terminology). - */ - String PER_PROJECT = "PER_PROJECT"; - - String value(); -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java deleted file mode 100644 index 612354560a3..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.analyzer; - -import org.sonar.batch.api.BatchExtension; - -/** - *

- * An Analyzer is invoked once during the analysis of a project. The analyzer can parse a flat file, connect to a web server... Analyzers are - * used to add measure and issues at file level. - *

- * - *

- * For example the Cobertura Analyzer parses Cobertura report and saves the first-level of measures on files. - *

- * - * @since 4.4 - */ -public interface Analyzer extends BatchExtension { - - /** - * Describe what this analyzer is doing. - * @return - */ - AnalyzerDescriptor describe(); - - /** - * The method that is going to be run when the analyzer is called - * - * @param context the context - */ - void analyse(AnalyzerContext context); - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java deleted file mode 100644 index e29dfaf711d..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.analyzer; - -import org.sonar.api.batch.fs.InputFile; -import org.sonar.batch.api.analyzer.issue.AnalyzerIssue; -import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure; -import org.sonar.batch.api.measures.Metric; - -import javax.annotation.CheckForNull; - -import java.io.Serializable; -import java.util.Collection; - -/** - * @since 4.4 - */ -public interface AnalyzerContext { - - // ----------- MEASURES -------------- - - /** - * Find a project measure. - */ - @CheckForNull - AnalyzerMeasure getMeasure(String metricKey); - - /** - * Find a project measure. - */ - @CheckForNull - AnalyzerMeasure getMeasure(Metric metric); - - /** - * Find a file measure. - */ - @CheckForNull - AnalyzerMeasure getMeasure(InputFile file, String metricKey); - - /** - * Find a file measure. - */ - @CheckForNull - AnalyzerMeasure getMeasure(InputFile file, Metric metric); - - /** - * Add a measure. - */ - void addMeasure(AnalyzerMeasure measure); - - // ----------- ISSUES -------------- - - /** - * Add an issue. - */ - void addIssue(AnalyzerIssue issue); - - /** - * Add a list of issues. - */ - void addIssues(Collection issues); - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java deleted file mode 100644 index 0b97200dd10..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.analyzer; - -import org.sonar.api.batch.fs.InputFile; -import org.sonar.batch.api.measures.Metric; - -import java.util.Arrays; -import java.util.Collection; - -public class AnalyzerDescriptor { - - private final String name; - private final Metric[] dependsOn; - private final Metric[] provides; - private final String[] languages; - private final InputFile.Type[] types; - - private AnalyzerDescriptor(Builder builder) { - this.name = builder.name; - this.dependsOn = builder.dependsOn != null ? builder.dependsOn : new Metric[0]; - this.provides = builder.provides != null ? builder.provides : new Metric[0]; - this.languages = builder.languages != null ? builder.languages : new String[0]; - this.types = builder.types; - } - - public String name() { - return name; - } - - public Metric[] dependsOn() { - return dependsOn; - } - - public Metric[] provides() { - return provides; - } - - public Collection languages() { - return Arrays.asList(languages); - } - - public InputFile.Type[] types() { - return types; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - - private String name; - private Metric[] dependsOn; - private Metric[] provides; - private String[] languages; - private InputFile.Type[] types; - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder dependsOn(Metric... metrics) { - this.dependsOn = metrics; - return this; - } - - public Builder provides(Metric... metrics) { - this.provides = metrics; - return this; - } - - public Builder runOnLanguages(String... languageKeys) { - this.languages = languageKeys; - return this; - } - - public Builder runOnTypes(InputFile.Type... types) { - this.types = types; - return this; - } - - public AnalyzerDescriptor build() { - return new AnalyzerDescriptor(this); - } - - } - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java deleted file mode 100644 index f39d88493fe..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.analyzer.issue; - -import org.sonar.api.batch.fs.InputFile; -import org.sonar.batch.api.analyzer.Analyzer; -import org.sonar.batch.api.internal.Preconditions; -import org.sonar.batch.api.rules.RuleKey; - -import javax.annotation.Nullable; - -/** - * Issue reported by an {@link Analyzer} - * - * @since 4.4 - */ -public class AnalyzerIssue { - - private final InputFile inputFile; - private final RuleKey ruleKey; - private final String message; - private final Integer line; - private final Double effortToFix; - - private AnalyzerIssue(Builder builder) { - this.inputFile = builder.file; - this.ruleKey = builder.ruleKey; - this.message = builder.message; - this.line = builder.line; - this.effortToFix = builder.effortToFix; - } - - public static Builder builder() { - return new Builder(); - } - - @Nullable - public InputFile inputFile() { - return inputFile; - } - - public RuleKey ruleKey() { - return ruleKey; - } - - public String message() { - return message; - } - - public Integer line() { - return line; - } - - @Nullable - public Double effortToFix() { - return effortToFix; - } - - public static class Builder { - - private Boolean onProject = null; - private InputFile file; - private RuleKey ruleKey; - private String message; - private Integer line; - private Double effortToFix; - - public AnalyzerIssue build() { - return new AnalyzerIssue(this); - } - - public Builder ruleKey(RuleKey ruleKey) { - this.ruleKey = ruleKey; - return this; - } - - public Builder onFile(InputFile file) { - Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); - Preconditions.checkNotNull(file, "InputFile should be non null"); - this.file = file; - this.onProject = false; - return this; - } - - public Builder onProject() { - Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); - this.file = null; - this.onProject = true; - return this; - } - - public Builder atLine(int line) { - this.line = line; - return this; - } - - public Builder effortToFix(@Nullable Double effortToFix) { - this.effortToFix = effortToFix; - return this; - } - - public Builder message(String message) { - this.message = message; - return this; - } - - } - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java deleted file mode 100644 index 70a6600e6d1..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.batch.api.analyzer.issue; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java deleted file mode 100644 index 3d74dca1b4c..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.analyzer.measure; - -import org.sonar.api.batch.fs.InputFile; -import org.sonar.batch.api.internal.Preconditions; -import org.sonar.batch.api.measures.Metric; - -import javax.annotation.Nullable; - -import java.io.Serializable; - -public class AnalyzerMeasure implements Serializable { - - private final InputFile inputFile; - private final String metricKey; - private final G value; - - private AnalyzerMeasure(Builder builder) { - Preconditions.checkNotNull(builder.value, "Measure value can't be null"); - Preconditions.checkNotNull(builder.metricKey, "Measure metricKey can't be null"); - this.inputFile = builder.file; - this.metricKey = builder.metricKey; - this.value = builder.value; - } - - @Nullable - public InputFile inputFile() { - return inputFile; - } - - public String metricKey() { - return metricKey; - } - - public Serializable value() { - return value; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - - private Boolean onProject = null; - private InputFile file; - private String metricKey; - private G value; - - public Builder onFile(InputFile file) { - Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); - Preconditions.checkNotNull(file, "InputFile should be non null"); - this.file = file; - this.onProject = false; - return this; - } - - public Builder onProject() { - Preconditions.checkState(onProject == null, "onFile or onProject can be called only once"); - this.file = null; - this.onProject = true; - return this; - } - - private Builder metricKey(String metricKey) { - Preconditions.checkState(metricKey != null, "Metric already defined"); - this.metricKey = metricKey; - return this; - } - - public Builder forMetric(Metric metric) { - return metricKey(metric.key()); - } - - public Builder withValue(G value) { - Preconditions.checkState(value != null, "Measure value already defined"); - Preconditions.checkNotNull(value, "Measure value can't be null"); - this.value = value; - return this; - } - - public AnalyzerMeasure build() { - return new AnalyzerMeasure(this); - } - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof AnalyzerMeasure)) { - return false; - } - AnalyzerMeasure other = (AnalyzerMeasure) obj; - return metricKey.equals(other.metricKey) - && value.equals(other.value) - && (inputFile == null ? other.inputFile == null : inputFile.equals(other.inputFile)); - } - - @Override - public int hashCode() { - return metricKey.hashCode() - + value.hashCode() - + (inputFile != null ? inputFile.hashCode() : 0); - } - - @Override - public String toString() { - return "AnalyzerMeasure[" + (inputFile != null ? "inputFile=" + inputFile.toString() : "onProject") - + ",metricKey=" + metricKey + ",value=" + value + "]"; - } - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java deleted file mode 100644 index b490662460a..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.batch.api.analyzer.measure; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java deleted file mode 100644 index 5b72f8c6315..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.batch.api.analyzer; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java deleted file mode 100644 index 0461255879b..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.internal; - -import java.io.File; - -/** - * Copied from commons io - * - */ -public class FilenameUtils { - - public static final char EXTENSION_SEPARATOR = '.'; - - private static final char UNIX_SEPARATOR = '/'; - - /** - * The Windows separator character. - */ - private static final char WINDOWS_SEPARATOR = '\\'; - - /** - * The system separator character. - */ - private static final char SYSTEM_SEPARATOR = File.separatorChar; - - /** - * The separator character that is the opposite of the system separator. - */ - private static final char OTHER_SEPARATOR; - static { - if (isSystemWindows()) { - OTHER_SEPARATOR = UNIX_SEPARATOR; - } else { - OTHER_SEPARATOR = WINDOWS_SEPARATOR; - } - } - - static boolean isSystemWindows() { - return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR; - } - - public static String normalize(String filename) { - return doNormalize(filename, UNIX_SEPARATOR, true); - } - - private static String doNormalize(String filename, char separator, boolean keepSeparator) { - if (filename == null) { - return null; - } - int size = filename.length(); - if (size == 0) { - return filename; - } - int prefix = getPrefixLength(filename); - if (prefix < 0) { - return null; - } - - char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy - filename.getChars(0, filename.length(), array, 0); - - // fix separators throughout - char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR; - for (int i = 0; i < array.length; i++) { - if (array[i] == otherSeparator) { - array[i] = separator; - } - } - - // add extra separator on the end to simplify code below - boolean lastIsDirectory = true; - if (array[size - 1] != separator) { - array[size++] = separator; - lastIsDirectory = false; - } - - // adjoining slashes - for (int i = prefix + 1; i < size; i++) { - if (array[i] == separator && array[i - 1] == separator) { - System.arraycopy(array, i, array, i - 1, size - i); - size--; - i--; - } - } - - // dot slash - for (int i = prefix + 1; i < size; i++) { - if (array[i] == separator && array[i - 1] == '.' && - (i == prefix + 1 || array[i - 2] == separator)) { - if (i == size - 1) { - lastIsDirectory = true; - } - System.arraycopy(array, i + 1, array, i - 1, size - i); - size -= 2; - i--; - } - } - - // double dot slash - outer: for (int i = prefix + 2; i < size; i++) { - if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' && - (i == prefix + 2 || array[i - 3] == separator)) { - if (i == prefix + 2) { - return null; - } - if (i == size - 1) { - lastIsDirectory = true; - } - int j; - for (j = i - 4; j >= prefix; j--) { - if (array[j] == separator) { - // remove b/../ from a/b/../c - System.arraycopy(array, i + 1, array, j + 1, size - i); - size -= i - j; - i = j + 1; - continue outer; - } - } - // remove a/../ from a/../c - System.arraycopy(array, i + 1, array, prefix, size - i); - size -= i + 1 - prefix; - i = prefix + 1; - } - } - - if (size <= 0) { // should never be less than 0 - return ""; - } - if (size <= prefix) { // should never be less than prefix - return new String(array, 0, size); - } - if (lastIsDirectory && keepSeparator) { - return new String(array, 0, size); // keep trailing separator - } - return new String(array, 0, size - 1); // lose trailing separator - } - - public static int getPrefixLength(String filename) { - if (filename == null) { - return -1; - } - int len = filename.length(); - if (len == 0) { - return 0; - } - char ch0 = filename.charAt(0); - if (ch0 == ':') { - return -1; - } - if (len == 1) { - if (ch0 == '~') { - return 2; // return a length greater than the input - } - return isSeparator(ch0) ? 1 : 0; - } else { - if (ch0 == '~') { - int posUnix = filename.indexOf(UNIX_SEPARATOR, 1); - int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1); - if (posUnix == -1 && posWin == -1) { - return len + 1; // return a length greater than the input - } - posUnix = posUnix == -1 ? posWin : posUnix; - posWin = posWin == -1 ? posUnix : posWin; - return Math.min(posUnix, posWin) + 1; - } - char ch1 = filename.charAt(1); - if (ch1 == ':') { - ch0 = Character.toUpperCase(ch0); - if (ch0 >= 'A' && ch0 <= 'Z') { - if (len == 2 || isSeparator(filename.charAt(2)) == false) { - return 2; - } - return 3; - } - return -1; - - } else if (isSeparator(ch0) && isSeparator(ch1)) { - int posUnix = filename.indexOf(UNIX_SEPARATOR, 2); - int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2); - if (posUnix == -1 && posWin == -1 || posUnix == 2 || posWin == 2) { - return -1; - } - posUnix = posUnix == -1 ? posWin : posUnix; - posWin = posWin == -1 ? posUnix : posWin; - return Math.min(posUnix, posWin) + 1; - } else { - return isSeparator(ch0) ? 1 : 0; - } - } - } - - private static boolean isSeparator(char ch) { - return ch == UNIX_SEPARATOR || ch == WINDOWS_SEPARATOR; - } - - public static String getExtension(String filename) { - if (filename == null) { - return null; - } - int index = indexOfExtension(filename); - if (index == -1) { - return ""; - } else { - return filename.substring(index + 1); - } - } - - public static int indexOfExtension(String filename) { - if (filename == null) { - return -1; - } - int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR); - int lastSeparator = indexOfLastSeparator(filename); - return lastSeparator > extensionPos ? -1 : extensionPos; - } - - public static int indexOfLastSeparator(String filename) { - if (filename == null) { - return -1; - } - int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR); - int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR); - return Math.max(lastUnixPos, lastWindowsPos); - } - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java deleted file mode 100644 index 75ac73f46f3..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.internal; - -import javax.annotation.Nullable; - -/** - * Copied from Guava - */ -public final class Preconditions { - private Preconditions() { - } - - /** - * Ensures the truth of an expression involving one or more parameters to the - * calling method. - * - * @param expression a boolean expression - * @throws IllegalArgumentException if {@code expression} is false - */ - public static void checkArgument(boolean expression) { - if (!expression) { - throw new IllegalArgumentException(); - } - } - - /** - * Ensures the truth of an expression involving one or more parameters to the - * calling method. - * - * @param expression a boolean expression - * @param errorMessage the exception message to use if the check fails; will - * be converted to a string using {@link String#valueOf(Object)} - * @throws IllegalArgumentException if {@code expression} is false - */ - public static void checkArgument( - boolean expression, @Nullable Object errorMessage) { - if (!expression) { - throw new IllegalArgumentException(String.valueOf(errorMessage)); - } - } - - /** - * Ensures the truth of an expression involving one or more parameters to the - * calling method. - * - * @param expression a boolean expression - * @param errorMessageTemplate a template for the exception message should the - * check fail. The message is formed by replacing each {@code %s} - * placeholder in the template with an argument. These are matched by - * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. - * Unmatched arguments will be appended to the formatted message in square - * braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message - * template. Arguments are converted to strings using - * {@link String#valueOf(Object)}. - * @throws IllegalArgumentException if {@code expression} is false - * @throws NullPointerException if the check fails and either {@code - * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let - * this happen) - */ - public static void checkArgument(boolean expression, - @Nullable String errorMessageTemplate, - @Nullable Object... errorMessageArgs) { - if (!expression) { - throw new IllegalArgumentException( - format(errorMessageTemplate, errorMessageArgs)); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling - * instance, but not involving any parameters to the calling method. - * - * @param expression a boolean expression - * @throws IllegalStateException if {@code expression} is false - */ - public static void checkState(boolean expression) { - if (!expression) { - throw new IllegalStateException(); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling - * instance, but not involving any parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessage the exception message to use if the check fails; will - * be converted to a string using {@link String#valueOf(Object)} - * @throws IllegalStateException if {@code expression} is false - */ - public static void checkState( - boolean expression, @Nullable Object errorMessage) { - if (!expression) { - throw new IllegalStateException(String.valueOf(errorMessage)); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling - * instance, but not involving any parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessageTemplate a template for the exception message should the - * check fail. The message is formed by replacing each {@code %s} - * placeholder in the template with an argument. These are matched by - * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. - * Unmatched arguments will be appended to the formatted message in square - * braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message - * template. Arguments are converted to strings using - * {@link String#valueOf(Object)}. - * @throws IllegalStateException if {@code expression} is false - * @throws NullPointerException if the check fails and either {@code - * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let - * this happen) - */ - public static void checkState(boolean expression, - @Nullable String errorMessageTemplate, - @Nullable Object... errorMessageArgs) { - if (!expression) { - throw new IllegalStateException( - format(errorMessageTemplate, errorMessageArgs)); - } - } - - /** - * Ensures that an object reference passed as a parameter to the calling - * method is not null. - * - * @param reference an object reference - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference) { - if (reference == null) { - throw new NullPointerException(); - } - return reference; - } - - /** - * Ensures that an object reference passed as a parameter to the calling - * method is not null. - * - * @param reference an object reference - * @param errorMessage the exception message to use if the check fails; will - * be converted to a string using {@link String#valueOf(Object)} - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference, @Nullable Object errorMessage) { - if (reference == null) { - throw new NullPointerException(String.valueOf(errorMessage)); - } - return reference; - } - - /** - * Ensures that an object reference passed as a parameter to the calling - * method is not null. - * - * @param reference an object reference - * @param errorMessageTemplate a template for the exception message should the - * check fail. The message is formed by replacing each {@code %s} - * placeholder in the template with an argument. These are matched by - * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. - * Unmatched arguments will be appended to the formatted message in square - * braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message - * template. Arguments are converted to strings using - * {@link String#valueOf(Object)}. - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference, - @Nullable String errorMessageTemplate, - @Nullable Object... errorMessageArgs) { - if (reference == null) { - // If either of these parameters is null, the right thing happens anyway - throw new NullPointerException( - format(errorMessageTemplate, errorMessageArgs)); - } - return reference; - } - - /* - * All recent hotspots (as of 2009) *really* like to have the natural code - * - * if (guardExpression) { - * throw new BadException(messageExpression); - * } - * - * refactored so that messageExpression is moved to a separate - * String-returning method. - * - * if (guardExpression) { - * throw new BadException(badMsg(...)); - * } - * - * The alternative natural refactorings into void or Exception-returning - * methods are much slower. This is a big deal - we're talking factors of - * 2-8 in microbenchmarks, not just 10-20%. (This is a hotspot optimizer - * bug, which should be fixed, but that's a separate, big project). - * - * The coding pattern above is heavily used in java.util, e.g. in ArrayList. - * There is a RangeCheckMicroBenchmark in the JDK that was used to test this. - * - * But the methods in this class want to throw different exceptions, - * depending on the args, so it appears that this pattern is not directly - * applicable. But we can use the ridiculous, devious trick of throwing an - * exception in the middle of the construction of another exception. - * Hotspot is fine with that. - */ - - /** - * Ensures that {@code index} specifies a valid element in an array, - * list or string of size {@code size}. An element index may range from zero, - * inclusive, to {@code size}, exclusive. - * - * @param index a user-supplied index identifying an element of an array, list - * or string - * @param size the size of that array, list or string - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is not - * less than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkElementIndex(int index, int size) { - return checkElementIndex(index, size, "index"); - } - - /** - * Ensures that {@code index} specifies a valid element in an array, - * list or string of size {@code size}. An element index may range from zero, - * inclusive, to {@code size}, exclusive. - * - * @param index a user-supplied index identifying an element of an array, list - * or string - * @param size the size of that array, list or string - * @param desc the text to use to describe this index in an error message - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is not - * less than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkElementIndex( - int index, int size, @Nullable String desc) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); - } - return index; - } - - private static String badElementIndex(int index, int size, String desc) { - if (index < 0) { - return format("%s (%s) must not be negative", desc, index); - } else if (size < 0) { - throw new IllegalArgumentException("negative size: " + size); - } else { // index >= size - return format("%s (%s) must be less than size (%s)", desc, index, size); - } - } - - /** - * Ensures that {@code index} specifies a valid position in an array, - * list or string of size {@code size}. A position index may range from zero - * to {@code size}, inclusive. - * - * @param index a user-supplied index identifying a position in an array, list - * or string - * @param size the size of that array, list or string - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is - * greater than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkPositionIndex(int index, int size) { - return checkPositionIndex(index, size, "index"); - } - - /** - * Ensures that {@code index} specifies a valid position in an array, - * list or string of size {@code size}. A position index may range from zero - * to {@code size}, inclusive. - * - * @param index a user-supplied index identifying a position in an array, list - * or string - * @param size the size of that array, list or string - * @param desc the text to use to describe this index in an error message - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is - * greater than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkPositionIndex( - int index, int size, @Nullable String desc) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (index < 0 || index > size) { - throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); - } - return index; - } - - private static String badPositionIndex(int index, int size, String desc) { - if (index < 0) { - return format("%s (%s) must not be negative", desc, index); - } else if (size < 0) { - throw new IllegalArgumentException("negative size: " + size); - } else { // index > size - return format("%s (%s) must not be greater than size (%s)", - desc, index, size); - } - } - - /** - * Ensures that {@code start} and {@code end} specify a valid positions - * in an array, list or string of size {@code size}, and are in order. A - * position index may range from zero to {@code size}, inclusive. - * - * @param start a user-supplied index identifying a starting position in an - * array, list or string - * @param end a user-supplied index identifying a ending position in an array, - * list or string - * @param size the size of that array, list or string - * @throws IndexOutOfBoundsException if either index is negative or is - * greater than {@code size}, or if {@code end} is less than {@code start} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static void checkPositionIndexes(int start, int end, int size) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (start < 0 || end < start || end > size) { - throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); - } - } - - private static String badPositionIndexes(int start, int end, int size) { - if (start < 0 || start > size) { - return badPositionIndex(start, size, "start index"); - } - if (end < 0 || end > size) { - return badPositionIndex(end, size, "end index"); - } - // end < start - return format("end index (%s) must not be less than start index (%s)", - end, start); - } - - /** - * Substitutes each {@code %s} in {@code template} with an argument. These - * are matched by position - the first {@code %s} gets {@code args[0]}, etc. - * If there are more arguments than placeholders, the unmatched arguments will - * be appended to the end of the formatted message in square braces. - * - * @param template a non-null string containing 0 or more {@code %s} - * placeholders. - * @param args the arguments to be substituted into the message - * template. Arguments are converted to strings using - * {@link String#valueOf(Object)}. Arguments can be null. - */ - static String format(String template, - @Nullable Object... args) { - template = String.valueOf(template); // null -> "null" - - // start substituting the arguments into the '%s' placeholders - StringBuilder builder = new StringBuilder( - template.length() + 16 * args.length); - int templateStart = 0; - int i = 0; - while (i < args.length) { - int placeholderStart = template.indexOf("%s", templateStart); - if (placeholderStart == -1) { - break; - } - builder.append(template.substring(templateStart, placeholderStart)); - builder.append(args[i++]); - templateStart = placeholderStart + 2; - } - builder.append(template.substring(templateStart)); - - // if we run out of placeholders, append the extra args in square braces - if (i < args.length) { - builder.append(" ["); - builder.append(args[i++]); - while (i < args.length) { - builder.append(", "); - builder.append(args[i++]); - } - builder.append(']'); - } - - return builder.toString(); - } -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java deleted file mode 100644 index ab279ae34e5..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.internal; - -/** - * Copied from commons lang - */ -public class StringUtils { - - public static final String EMPTY = ""; - - public static String trim(String str) { - return str == null ? null : str.trim(); - } - - public static String removeStart(String str, String remove) { - if (isEmpty(str) || isEmpty(remove)) { - return str; - } - if (str.startsWith(remove)) { - return str.substring(remove.length()); - } - return str; - } - - public static String removeEnd(String str, String remove) { - if (isEmpty(str) || isEmpty(remove)) { - return str; - } - if (str.endsWith(remove)) { - return str.substring(0, str.length() - remove.length()); - } - return str; - } - - public static boolean isEmpty(String str) { - return str == null || str.length() == 0; - } - - public static boolean startsWithIgnoreCase(String str, String prefix) { - return startsWith(str, prefix, true); - } - - private static boolean startsWith(String str, String prefix, boolean ignoreCase) { - if (str == null || prefix == null) { - return (str == null && prefix == null); - } - if (prefix.length() > str.length()) { - return false; - } - return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length()); - } - - public static String substring(String str, int start) { - if (str == null) { - return null; - } - - // handle negatives, which means last n characters - if (start < 0) { - start = str.length() + start; // remember start is negative - } - - if (start < 0) { - start = 0; - } - if (start > str.length()) { - return EMPTY; - } - - return str.substring(start); - } - - public static boolean isBlank(String str) { - int strLen; - if (str == null || (strLen = str.length()) == 0) { - return true; - } - for (int i = 0; i < strLen; i++) { - if ((Character.isWhitespace(str.charAt(i)) == false)) { - return false; - } - } - return true; - } - - public static boolean isNotBlank(String str) { - return !StringUtils.isBlank(str); - } - - public static String removeEndIgnoreCase(String str, String remove) { - if (isEmpty(str) || isEmpty(remove)) { - return str; - } - if (endsWithIgnoreCase(str, remove)) { - return str.substring(0, str.length() - remove.length()); - } - return str; - } - - public static boolean endsWithIgnoreCase(String str, String suffix) { - return endsWith(str, suffix, true); - } - - private static boolean endsWith(String str, String suffix, boolean ignoreCase) { - if (str == null || suffix == null) { - return (str == null && suffix == null); - } - if (suffix.length() > str.length()) { - return false; - } - int strOffset = str.length() - suffix.length(); - return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length()); - } - - public static String lowerCase(String str) { - if (str == null) { - return null; - } - return str.toLowerCase(); - } - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java deleted file mode 100644 index f179fd73571..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.internal; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -/** - * Implementation of Ant-style matching patterns. - * Contrary to other implementations (like AntPathMatcher from Spring Framework) it is based on {@link Pattern Java Regular Expressions}. - * To increase performance it holds an internal cache of all processed patterns. - *

- * Following rules are applied: - *

    - *
  • ? matches single character
  • - *
  • * matches zero or more characters
  • - *
  • ** matches zero or more 'directories'
  • - *
- *

- *

- * Some examples of patterns: - *

    - *
  • org/T?st.java - matches org/Test.java and also org/Tost.java
  • - *
  • org/*.java - matches all .java files in the org directory, - * e.g. org/Foo.java or org/Bar.java
  • - *
  • org/** - matches all files underneath the org directory, - * e.g. org/Foo.java or org/foo/bar.jsp
  • - *
  • org/**/Test.java - matches all Test.java files underneath the org directory, - * e.g. org/Test.java or org/foo/Test.java or org/foo/bar/Test.java
  • - *
  • org/**/*.java - matches all .java files underneath the org directory, - * e.g. org/Foo.java or org/foo/Bar.java or org/foo/bar/Baz.java
  • - *
- *

- *

- * Another implementation, which is also based on Java Regular Expressions, can be found in - * FileUtil - * from IntelliJ OpenAPI. - *

- * - */ -public class WildcardPattern { - - private static final Map CACHE = new HashMap(); - private static final String SPECIAL_CHARS = "()[]^$.{}+|"; - - private Pattern pattern; - private String stringRepresentation; - - protected WildcardPattern(String pattern, String directorySeparator) { - this.stringRepresentation = pattern; - this.pattern = Pattern.compile(toRegexp(pattern, directorySeparator)); - } - - private static String toRegexp(String antPattern, String directorySeparator) { - final String escapedDirectorySeparator = '\\' + directorySeparator; - - final StringBuilder sb = new StringBuilder(antPattern.length()); - - sb.append('^'); - - int i = antPattern.startsWith("/") || antPattern.startsWith("\\") ? 1 : 0; - while (i < antPattern.length()) { - final char ch = antPattern.charAt(i); - - if (SPECIAL_CHARS.indexOf(ch) != -1) { - // Escape regexp-specific characters - sb.append('\\').append(ch); - } else if (ch == '*') { - if (i + 1 < antPattern.length() && antPattern.charAt(i + 1) == '*') { - // Double asterisk - // Zero or more directories - if (i + 2 < antPattern.length() && isSlash(antPattern.charAt(i + 2))) { - sb.append("(?:.*").append(escapedDirectorySeparator).append("|)"); - i += 2; - } else { - sb.append(".*"); - i += 1; - } - } else { - // Single asterisk - // Zero or more characters excluding directory separator - sb.append("[^").append(escapedDirectorySeparator).append("]*?"); - } - } else if (ch == '?') { - // Any single character excluding directory separator - sb.append("[^").append(escapedDirectorySeparator).append("]"); - } else if (isSlash(ch)) { - // Directory separator - sb.append(escapedDirectorySeparator); - } else { - // Single character - sb.append(ch); - } - - i++; - } - - sb.append('$'); - - return sb.toString(); - } - - private static boolean isSlash(char ch) { - return ch == '/' || ch == '\\'; - } - - /** - * Returns string representation of this pattern. - * - * @since 2.5 - */ - @Override - public String toString() { - return stringRepresentation; - } - - /** - * Returns true if specified value matches this pattern. - */ - public boolean match(String value) { - value = StringUtils.removeStart(value, "/"); - value = StringUtils.removeEnd(value, "/"); - return pattern.matcher(value).matches(); - } - - /** - * Returns true if specified value matches one of specified patterns. - * - * @since 2.4 - */ - public static boolean match(WildcardPattern[] patterns, String value) { - for (WildcardPattern pattern : patterns) { - if (pattern.match(value)) { - return true; - } - } - return false; - } - - /** - * Creates pattern with "/" as a directory separator. - * - * @see #create(String, String) - */ - public static WildcardPattern create(String pattern) { - return create(pattern, "/"); - } - - /** - * Creates array of patterns with "/" as a directory separator. - * - * @see #create(String, String) - */ - public static WildcardPattern[] create(String[] patterns) { - if (patterns == null) { - return new WildcardPattern[0]; - } - WildcardPattern[] exclusionPAtterns = new WildcardPattern[patterns.length]; - for (int i = 0; i < patterns.length; i++) { - exclusionPAtterns[i] = create(patterns[i]); - } - return exclusionPAtterns; - } - - /** - * Creates pattern with specified separator for directories. - *

- * This is used to match Java-classes, i.e. org.foo.Bar against org/**. - * However usage of character other than "/" as a directory separator is misleading and should be avoided, - * so method {@link #create(String)} is preferred over this one. - *

- *

- * Also note that no matter whether forward or backward slashes were used in the antPattern - * the returned pattern will use directorySeparator. - * Thus to match Windows-style path "dir\file.ext" against pattern "dir/file.ext" normalization should be performed. - *

- */ - public static WildcardPattern create(String pattern, String directorySeparator) { - String key = pattern + directorySeparator; - WildcardPattern wildcardPattern = CACHE.get(key); - if (wildcardPattern == null) { - wildcardPattern = new WildcardPattern(pattern, directorySeparator); - CACHE.put(key, wildcardPattern); - } - return wildcardPattern; - } -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java deleted file mode 100644 index 9870b99bffc..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.batch.api.internal; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java deleted file mode 100644 index 7dd6c8b4e6b..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.languages; - -import java.util.Arrays; -import java.util.Collection; - -public final class Language { - - private final String key, name; - private final String[] fileSuffixes; - - public Language(String key, String name, String... fileSuffixes) { - this.key = key; - this.name = name; - this.fileSuffixes = fileSuffixes; - } - - /** - * For example "java". - */ - public String key() { - return key; - } - - /** - * For example "Java" - */ - public String name() { - return name; - } - - /** - * For example ["jav", "java"]. - */ - public Collection fileSuffixes() { - return Arrays.asList(fileSuffixes); - } - -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java deleted file mode 100644 index a36d1c13de5..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.batch.api.languages; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java deleted file mode 100644 index 52dc17c1718..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.measures; - -import java.io.Serializable; - -public interface Metric { - - Class type(); - - String key(); -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java deleted file mode 100644 index e684b549c5f..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.batch.api.measures; \ No newline at end of file diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java deleted file mode 100644 index 1d074e105f2..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.rules; - -public class QProfile { - private final String name, language; - private final Integer version; - - public QProfile(String name, String language, Integer version) { - this.name = name; - this.language = language; - this.version = version; - } - - public String name() { - return name; - } - - public String language() { - return language; - } - - public Integer version() { - return version; - } -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java deleted file mode 100644 index 3af1337a752..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.api.rules; - -import java.io.Serializable; - -/** - * Key of a rule. Unique among all the rule repositories. - * - * @since 3.6 - */ -public class RuleKey implements Serializable { - private final String repository, rule; - - protected RuleKey(String repositoryKey, String ruleKey) { - this.repository = repositoryKey; - this.rule = ruleKey; - } - - /** - * Create a key. Parameters are NOT null. - */ - public static RuleKey of(String repository, String rule) { - return new RuleKey(repository, rule); - } - - /** - * Never null - */ - public String repository() { - return repository; - } - - /** - * Never null - */ - public String rule() { - return rule; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - RuleKey ruleKey = (RuleKey) o; - if (!repository.equals(ruleKey.repository)) { - return false; - } - if (!rule.equals(ruleKey.rule)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - int result = repository.hashCode(); - result = 31 * result + rule.hashCode(); - return result; - } - - /** - * Format is "repository:rule", for example "squid:AvoidCycle" - */ - @Override - public String toString() { - return String.format("%s:%s", repository, rule); - } -} diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java deleted file mode 100644 index d91eb3485c9..00000000000 --- a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.batch.api.rules; \ No newline at end of file diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java index ab32231dbea..1e8c53d8853 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java @@ -25,6 +25,8 @@ import com.persistit.Exchange; import com.persistit.Persistit; import com.persistit.Value; import com.persistit.Volume; +import com.persistit.encoding.CoderManager; +import com.persistit.encoding.ValueCoder; import com.persistit.exception.PersistitException; import com.persistit.logging.Slf4jAdapter; import org.apache.commons.io.FileUtils; @@ -78,6 +80,11 @@ public class Caches implements BatchComponent, Startable { } } + public void registerValueCoder(Class clazz, ValueCoder coder) { + CoderManager cm = persistit.getCoderManager(); + cm.registerValueCoder(clazz, coder); + } + public Cache createCache(String cacheName) { Preconditions.checkState(volume != null && volume.isOpened(), "Caches are not initialized"); Preconditions.checkState(!cacheNames.contains(cacheName), "Cache is already created: " + cacheName); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java index e3732308cf5..a3d23bf4fde 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java @@ -22,8 +22,10 @@ package org.sonar.batch.scan.measure; import com.google.common.base.Preconditions; import org.sonar.api.BatchComponent; import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MetricFinder; import org.sonar.api.measures.RuleMeasure; import org.sonar.api.resources.Resource; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.batch.index.Cache; import org.sonar.batch.index.Cache.Entry; import org.sonar.batch.index.Caches; @@ -35,7 +37,8 @@ public class MeasureCache implements BatchComponent { private final Cache cache; - public MeasureCache(Caches caches) { + public MeasureCache(Caches caches, MetricFinder metricFinder, TechnicalDebtModel techDebtModel) { + caches.registerValueCoder(Measure.class, new MeasureValueCoder(metricFinder, techDebtModel)); cache = caches.createCache("measures"); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java new file mode 100644 index 00000000000..ccda40c429b --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.scan.measure; + +import com.persistit.Value; +import com.persistit.encoding.CoderContext; +import com.persistit.encoding.ValueCoder; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.MetricFinder; +import org.sonar.api.measures.PersistenceMode; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; + +class MeasureValueCoder implements ValueCoder { + + private final MetricFinder metricFinder; + private final TechnicalDebtModel techDebtModel; + + public MeasureValueCoder(MetricFinder metricFinder, TechnicalDebtModel techDebtModel) { + this.metricFinder = metricFinder; + this.techDebtModel = techDebtModel; + } + + public void put(Value value, Object object, CoderContext context) { + Measure m = (Measure) object; + value.putString(m.getMetricKey()); + value.put(m.getValue()); + value.putString(m.getData()); + value.putString(m.getDescription()); + value.putString(m.getAlertStatus() != null ? m.getAlertStatus().name() : null); + value.putString(m.getAlertText()); + value.put(m.getTendency()); + value.putDate(m.getDate()); + value.put(m.getVariation1()); + value.put(m.getVariation2()); + value.put(m.getVariation3()); + value.put(m.getVariation4()); + value.put(m.getVariation5()); + value.putString(m.getUrl()); + value.put(m.getCharacteristic() != null ? m.getCharacteristic().id() : null); + value.put(m.getRequirement() != null ? m.getRequirement().id() : null); + value.put(m.getPersonId() != null ? m.getPersonId().intValue() : null); + value.putString(m.getPersistenceMode() != null ? m.getPersistenceMode().name() : null); + } + + public Object get(Value value, Class clazz, CoderContext context) { + Measure m = new Measure(); + String metricKey = value.getString(); + m.setMetric(metricFinder.findByKey(metricKey)); + m.setRawValue(value.isNull(true) ? null : value.getDouble()); + m.setData(value.getString()); + m.setDescription(value.getString()); + m.setAlertStatus(value.isNull(true) ? null : Metric.Level.valueOf(value.getString())); + m.setAlertText(value.getString()); + m.setTendency(value.isNull(true) ? null : value.getInt()); + m.setDate(value.getDate()); + m.setVariation1(value.isNull(true) ? null : value.getDouble()); + m.setVariation2(value.isNull(true) ? null : value.getDouble()); + m.setVariation3(value.isNull(true) ? null : value.getDouble()); + m.setVariation4(value.isNull(true) ? null : value.getDouble()); + m.setVariation5(value.isNull(true) ? null : value.getDouble()); + m.setUrl(value.getString()); + m.setCharacteristic(value.isNull(true) ? null : techDebtModel.characteristicById(value.getInt())); + m.setRequirement(value.isNull(true) ? null : techDebtModel.requirementsById(value.getInt())); + m.setPersonId(value.isNull(true) ? null : value.getInt()); + m.setPersistenceMode(value.isNull(true) ? null : PersistenceMode.valueOf(value.getString())); + return m; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java index 2e086f16627..82653d849fc 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java @@ -19,6 +19,7 @@ */ package org.sonar.batch.scan.measure; +import org.apache.commons.lang.builder.EqualsBuilder; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -27,6 +28,8 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric.Level; +import org.sonar.api.measures.MetricFinder; import org.sonar.api.measures.RuleMeasure; import org.sonar.api.resources.Directory; import org.sonar.api.resources.File; @@ -34,6 +37,9 @@ import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.RulePriority; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; +import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; import org.sonar.batch.index.Cache.Entry; import org.sonar.batch.index.Caches; @@ -43,6 +49,8 @@ import java.util.Date; import java.util.Iterator; import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class MeasureCacheTest { @@ -54,10 +62,17 @@ public class MeasureCacheTest { Caches caches; + private MetricFinder metricFinder; + + private TechnicalDebtModel techDebtModel; + @Before public void start() throws Exception { caches = CachesTest.createCacheOnTemp(temp); caches.start(); + metricFinder = mock(MetricFinder.class); + when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC); + techDebtModel = mock(TechnicalDebtModel.class); } @After @@ -67,7 +82,7 @@ public class MeasureCacheTest { @Test public void should_add_measure() throws Exception { - MeasureCache cache = new MeasureCache(caches); + MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel); Project p = new Project("struts"); assertThat(cache.entries()).hasSize(0); @@ -102,7 +117,7 @@ public class MeasureCacheTest { */ @Test public void should_add_measure_with_big_data() throws Exception { - MeasureCache cache = new MeasureCache(caches); + MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel); Project p = new Project("struts"); assertThat(cache.entries()).hasSize(0); @@ -142,7 +157,7 @@ public class MeasureCacheTest { */ @Test public void should_add_measure_with_too_big_data_for_persistit_pre_patch() throws Exception { - MeasureCache cache = new MeasureCache(caches); + MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel); Project p = new Project("struts"); assertThat(cache.entries()).hasSize(0); @@ -178,7 +193,7 @@ public class MeasureCacheTest { @Test public void should_add_measure_with_too_big_data_for_persistit() throws Exception { - MeasureCache cache = new MeasureCache(caches); + MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel); Project p = new Project("struts"); assertThat(cache.entries()).hasSize(0); @@ -201,7 +216,7 @@ public class MeasureCacheTest { @Test public void should_add_measure_with_same_metric() throws Exception { - MeasureCache cache = new MeasureCache(caches); + MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel); Project p = new Project("struts"); assertThat(cache.entries()).hasSize(0); @@ -223,7 +238,7 @@ public class MeasureCacheTest { @Test public void should_get_measures() throws Exception { - MeasureCache cache = new MeasureCache(caches); + MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel); Project p = new Project("struts"); Resource dir = new Directory("foo/bar").setEffectiveKey("struts:foo/bar"); Resource file1 = new File("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt"); @@ -260,4 +275,46 @@ public class MeasureCacheTest { assertThat(cache.byResource(dir)).hasSize(1); assertThat(cache.byResource(dir).iterator().next()).isEqualTo(mDir); } + + @Test + public void test_measure_coder() throws Exception { + MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel); + Resource file1 = new File("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt"); + + Measure measure = new Measure(CoreMetrics.NCLOC, 1.786, 5); + cache.put(file1, measure); + + Measure savedMeasure = cache.byResource(file1).iterator().next(); + + assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue(); + + measure = new Measure(CoreMetrics.NCLOC); + measure.setData("data"); + measure.setAlertStatus(Level.ERROR); + measure.setAlertText("alert"); + Characteristic c = mock(Characteristic.class); + when(c.id()).thenReturn(1); + when(techDebtModel.characteristicById(1)).thenReturn(c); + measure.setCharacteristic(c); + measure.setDate(new Date()); + measure.setDescription("description"); + measure.setPersistenceMode(null); + measure.setPersonId(3); + Requirement r = mock(Requirement.class); + when(r.id()).thenReturn(7); + when(techDebtModel.requirementsById(7)).thenReturn(r); + measure.setRequirement(r); + measure.setTendency(4); + measure.setUrl("http://foo"); + measure.setVariation1(11.0); + measure.setVariation2(12.0); + measure.setVariation3(13.0); + measure.setVariation4(14.0); + measure.setVariation5(15.0); + cache.put(file1, measure); + + savedMeasure = cache.byResource(file1).iterator().next(); + assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue(); + + } } diff --git a/sonar-core/src/main/resources/org/sonar/core/source/db/SnapshotSourceMapper.xml b/sonar-core/src/main/resources/org/sonar/core/source/db/SnapshotSourceMapper.xml index defb4eb4f69..de072269330 100644 --- a/sonar-core/src/main/resources/org/sonar/core/source/db/SnapshotSourceMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/source/db/SnapshotSourceMapper.xml @@ -4,7 +4,7 @@ - SELECT data FROM snapshot_sources WHERE snapshot_id = #{sid} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java index b6a90add399..170b2c5531b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java @@ -289,6 +289,14 @@ public class Measure implements Serializable { return setValue(v, DEFAULT_PRECISION); } + /** + * For internal use + */ + public Measure setRawValue(@Nullable Double v) { + this.value = v; + return this; + } + /** * Sets the measure value as an int *