<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
- <version>3.2.2</version>
+ <version>3.2.7</version>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
--- /dev/null
+/*
+ * 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;
+
+/**
+ * <p>
+ * 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.
+ * </p>
+ *
+ * <p>
+ * For example the Cobertura Analyzer parses Cobertura report and saves the first-level of measures on files.
+ * </p>
+ *
+ * @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);
+
+}
--- /dev/null
+/*
+ * 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
+ <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric);
+
+ /**
+ * Find a file measure.
+ */
+ @CheckForNull
+ AnalyzerMeasure<?> getMeasure(InputFile file, String metricKey);
+
+ /**
+ * Find a file measure.
+ */
+ @CheckForNull
+ <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric);
+
+ /**
+ * Add a measure.
+ */
+ void addMeasure(AnalyzerMeasure<?> measure);
+
+ // ----------- ISSUES --------------
+
+ /**
+ * Add an issue.
+ */
+ void addIssue(AnalyzerIssue issue);
+
+ /**
+ * Add a list of issues.
+ */
+ void addIssues(Collection<AnalyzerIssue> issues);
+
+}
--- /dev/null
+/*
+ * 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<String> 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);
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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<G extends Serializable> implements Serializable {
+
+ private final InputFile inputFile;
+ private final String metricKey;
+ private final G value;
+
+ private AnalyzerMeasure(Builder<G> 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 <G extends Serializable> Builder<G> builder() {
+ return new Builder<G>();
+ }
+
+ public static class Builder<G extends Serializable> {
+
+ private Boolean onProject = null;
+ private InputFile file;
+ private String metricKey;
+ private G value;
+
+ public Builder<G> 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<G> onProject() {
+ Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+ this.file = null;
+ this.onProject = true;
+ return this;
+ }
+
+ private Builder<G> metricKey(String metricKey) {
+ Preconditions.checkState(metricKey != null, "Metric already defined");
+ this.metricKey = metricKey;
+ return this;
+ }
+
+ public Builder<G> forMetric(Metric<G> metric) {
+ return metricKey(metric.key());
+ }
+
+ public Builder<G> 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<G> build() {
+ return new AnalyzerMeasure<G>(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 + "]";
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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> 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> 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> 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 <i>element</i> 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 <i>element</i> 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 <i>position</i> 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 <i>position</i> 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 <i>positions</i>
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*
+ * 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.
+ * <p>
+ * Following rules are applied:
+ * <ul>
+ * <li>? matches single character</li>
+ * <li>* matches zero or more characters</li>
+ * <li>** matches zero or more 'directories'</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Some examples of patterns:
+ * <ul>
+ * <li><code>org/T?st.java</code> - matches <code>org/Test.java</code> and also <code>org/Tost.java</code></li>
+ * <li><code>org/*.java</code> - matches all <code>.java</code> files in the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/Bar.java</code></li>
+ * <li><code>org/**</code> - matches all files underneath the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/foo/bar.jsp</code></li>
+ * <li><code>org/**/Test.java</code> - matches all <code>Test.java</code> files underneath the <code>org</code> directory,
+ * e.g. <code>org/Test.java</code> or <code>org/foo/Test.java</code> or <code>org/foo/bar/Test.java</code></li>
+ * <li><code>org/**/*.java</code> - matches all <code>.java</code> files underneath the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/foo/Bar.java</code> or <code>org/foo/bar/Baz.java</code></li>
+ * </ul>
+ * </p>
+ * <p>
+ * Another implementation, which is also based on Java Regular Expressions, can be found in
+ * <a href="https://github.com/JetBrains/intellij-community/blob/idea/107.743/platform/util/src/com/intellij/openapi/util/io/FileUtil.java#L847">FileUtil</a>
+ * from IntelliJ OpenAPI.
+ * </p>
+ *
+ */
+public class WildcardPattern {
+
+ private static final Map<String, WildcardPattern> CACHE = new HashMap<String, WildcardPattern>();
+ 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.
+ * <p>
+ * This is used to match Java-classes, i.e. <code>org.foo.Bar</code> against <code>org/**</code>.
+ * <b>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.</b>
+ * </p>
+ * <p>
+ * Also note that no matter whether forward or backward slashes were used in the <code>antPattern</code>
+ * the returned pattern will use <code>directorySeparator</code>.
+ * Thus to match Windows-style path "dir\file.ext" against pattern "dir/file.ext" normalization should be performed.
+ * </p>
+ */
+ 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;
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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<String> fileSuffixes() {
+ return Arrays.asList(fileSuffixes);
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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<G extends Serializable> {
+
+ Class<G> type();
+
+ String key();
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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
+++ /dev/null
-/*
- * 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 {
-}
+++ /dev/null
-/*
- * 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 {
-
-}
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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;
-
-/**
- * <p>
- * 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.
- * </p>
- *
- * <p>
- * For example the Cobertura Analyzer parses Cobertura report and saves the first-level of measures on files.
- * </p>
- *
- * @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);
-
-}
+++ /dev/null
-/*
- * 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
- <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric);
-
- /**
- * Find a file measure.
- */
- @CheckForNull
- AnalyzerMeasure<?> getMeasure(InputFile file, String metricKey);
-
- /**
- * Find a file measure.
- */
- @CheckForNull
- <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric);
-
- /**
- * Add a measure.
- */
- void addMeasure(AnalyzerMeasure<?> measure);
-
- // ----------- ISSUES --------------
-
- /**
- * Add an issue.
- */
- void addIssue(AnalyzerIssue issue);
-
- /**
- * Add a list of issues.
- */
- void addIssues(Collection<AnalyzerIssue> issues);
-
-}
+++ /dev/null
-/*
- * 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<String> 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);
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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<G extends Serializable> implements Serializable {
-
- private final InputFile inputFile;
- private final String metricKey;
- private final G value;
-
- private AnalyzerMeasure(Builder<G> 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 <G extends Serializable> Builder<G> builder() {
- return new Builder<G>();
- }
-
- public static class Builder<G extends Serializable> {
-
- private Boolean onProject = null;
- private InputFile file;
- private String metricKey;
- private G value;
-
- public Builder<G> 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<G> onProject() {
- Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
- this.file = null;
- this.onProject = true;
- return this;
- }
-
- private Builder<G> metricKey(String metricKey) {
- Preconditions.checkState(metricKey != null, "Metric already defined");
- this.metricKey = metricKey;
- return this;
- }
-
- public Builder<G> forMetric(Metric<G> metric) {
- return metricKey(metric.key());
- }
-
- public Builder<G> 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<G> build() {
- return new AnalyzerMeasure<G>(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 + "]";
- }
-
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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> 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> 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> 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 <i>element</i> 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 <i>element</i> 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 <i>position</i> 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 <i>position</i> 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 <i>positions</i>
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-
-}
+++ /dev/null
-/*
- * 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.
- * <p>
- * Following rules are applied:
- * <ul>
- * <li>? matches single character</li>
- * <li>* matches zero or more characters</li>
- * <li>** matches zero or more 'directories'</li>
- * </ul>
- * </p>
- * <p>
- * Some examples of patterns:
- * <ul>
- * <li><code>org/T?st.java</code> - matches <code>org/Test.java</code> and also <code>org/Tost.java</code></li>
- * <li><code>org/*.java</code> - matches all <code>.java</code> files in the <code>org</code> directory,
- * e.g. <code>org/Foo.java</code> or <code>org/Bar.java</code></li>
- * <li><code>org/**</code> - matches all files underneath the <code>org</code> directory,
- * e.g. <code>org/Foo.java</code> or <code>org/foo/bar.jsp</code></li>
- * <li><code>org/**/Test.java</code> - matches all <code>Test.java</code> files underneath the <code>org</code> directory,
- * e.g. <code>org/Test.java</code> or <code>org/foo/Test.java</code> or <code>org/foo/bar/Test.java</code></li>
- * <li><code>org/**/*.java</code> - matches all <code>.java</code> files underneath the <code>org</code> directory,
- * e.g. <code>org/Foo.java</code> or <code>org/foo/Bar.java</code> or <code>org/foo/bar/Baz.java</code></li>
- * </ul>
- * </p>
- * <p>
- * Another implementation, which is also based on Java Regular Expressions, can be found in
- * <a href="https://github.com/JetBrains/intellij-community/blob/idea/107.743/platform/util/src/com/intellij/openapi/util/io/FileUtil.java#L847">FileUtil</a>
- * from IntelliJ OpenAPI.
- * </p>
- *
- */
-public class WildcardPattern {
-
- private static final Map<String, WildcardPattern> CACHE = new HashMap<String, WildcardPattern>();
- 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.
- * <p>
- * This is used to match Java-classes, i.e. <code>org.foo.Bar</code> against <code>org/**</code>.
- * <b>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.</b>
- * </p>
- * <p>
- * Also note that no matter whether forward or backward slashes were used in the <code>antPattern</code>
- * the returned pattern will use <code>directorySeparator</code>.
- * Thus to match Windows-style path "dir\file.ext" against pattern "dir/file.ext" normalization should be performed.
- * </p>
- */
- 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;
- }
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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<String> fileSuffixes() {
- return Arrays.asList(fileSuffixes);
- }
-
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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<G extends Serializable> {
-
- Class<G> type();
-
- String key();
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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
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;
}
}
+ public void registerValueCoder(Class<?> clazz, ValueCoder coder) {
+ CoderManager cm = persistit.getCoderManager();
+ cm.registerValueCoder(clazz, coder);
+ }
+
public <V extends Serializable> Cache<V> createCache(String cacheName) {
Preconditions.checkState(volume != null && volume.isOpened(), "Caches are not initialized");
Preconditions.checkState(!cacheNames.contains(cacheName), "Cache is already created: " + cacheName);
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;
private final Cache<Measure> 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");
}
--- /dev/null
+/*
+ * 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;
+ }
+}
*/
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;
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;
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;
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 {
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
@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);
*/
@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);
*/
@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);
@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);
@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);
@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");
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();
+
+ }
}
<mapper namespace="org.sonar.core.source.db.SnapshotSourceMapper">
- <select id="selectSnapshotSource" parameterType="int" resultType="string">
+ <select id="selectSnapshotSource" parameterType="long" resultType="string">
SELECT data
FROM snapshot_sources
WHERE snapshot_id = #{sid}
return setValue(v, DEFAULT_PRECISION);
}
+ /**
+ * For internal use
+ */
+ public Measure setRawValue(@Nullable Double v) {
+ this.value = v;
+ return this;
+ }
+
/**
* Sets the measure value as an int
*