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.mybatismybatis
- 3.2.2
+ 3.2.7org.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 @@
-