compile 'commons-io:commons-io'
compile 'commons-lang:commons-lang'
compile 'com.google.code.gson:gson'
- compile 'com.google.guava:guava'
compile 'org.apache.commons:commons-csv'
// shaded, but not relocated
compileOnly 'junit:junit'
compileOnly 'org.slf4j:slf4j-api'
+ testCompile 'com.google.guava:guava'
testCompile 'com.tngtech.java:junit-dataprovider'
testCompile 'org.assertj:assertj-core'
testCompile 'org.mockito:mockito-core'
- testCompile project(':sonar-testing-harness')
}
sourceSets {
*/
package org.sonar.api.batch.fs.internal;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.SetMultimap;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.StreamSupport;
*/
private static class MapCache extends Cache {
private final Map<String, InputFile> fileMap = new HashMap<>();
- private final SetMultimap<String, InputFile> filesByNameCache = LinkedHashMultimap.create();
- private final SetMultimap<String, InputFile> filesByExtensionCache = LinkedHashMultimap.create();
+ private final Map<String, Set<InputFile>> filesByNameCache = new HashMap<>();
+ private final Map<String, Set<InputFile>> filesByExtensionCache = new HashMap<>();
private SortedSet<String> languages = new TreeSet<>();
@Override
languages.add(inputFile.language());
}
fileMap.put(inputFile.relativePath(), inputFile);
- filesByNameCache.put(inputFile.filename(), inputFile);
- filesByExtensionCache.put(FileExtensionPredicate.getExtension(inputFile), inputFile);
+ filesByNameCache.computeIfAbsent(inputFile.filename(), x -> new HashSet<>()).add(inputFile);
+ filesByExtensionCache.computeIfAbsent(FileExtensionPredicate.getExtension(inputFile), x -> new HashSet<>()).add(inputFile);
}
@Override
*/
package org.sonar.api.batch.fs.internal;
-import com.google.common.base.Preconditions;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import org.sonar.api.batch.fs.TextPointer;
import org.sonar.api.batch.fs.TextRange;
-import static com.google.common.base.Preconditions.checkState;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
/**
* @since 4.2
public InputStream inputStream() throws IOException {
return contents != null ? new ByteArrayInputStream(contents.getBytes(charset()))
: new BOMInputStream(Files.newInputStream(path()),
- ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
+ ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
}
@Override
public TextPointer newPointer(int globalOffset) {
checkMetadata();
- Preconditions.checkArgument(globalOffset >= 0, "%s is not a valid offset for a file", globalOffset);
- Preconditions.checkArgument(globalOffset <= lastValidOffset(), "%s is not a valid offset for file %s. Max offset is %s", globalOffset, this, lastValidOffset());
+ checkArgument(globalOffset >= 0, "%s is not a valid offset for a file", globalOffset);
+ checkArgument(globalOffset <= lastValidOffset(), "%s is not a valid offset for file %s. Max offset is %s", globalOffset, this, lastValidOffset());
int line = findLine(globalOffset);
int startLineOffset = originalLineStartOffsets()[line - 1];
// In case the global offset is between \r and \n, move the pointer to a valid location
}
private void checkValid(TextPointer pointer, String owner) {
- Preconditions.checkArgument(pointer.line() >= 1, "%s is not a valid line for a file", pointer.line());
- Preconditions.checkArgument(pointer.line() <= this.metadata.lines(), "%s is not a valid line for %s. File %s has %s line(s)", pointer.line(), owner, this, metadata.lines());
- Preconditions.checkArgument(pointer.lineOffset() >= 0, "%s is not a valid line offset for a file", pointer.lineOffset());
+ checkArgument(pointer.line() >= 1, "%s is not a valid line for a file", pointer.line());
+ checkArgument(pointer.line() <= this.metadata.lines(), "%s is not a valid line for %s. File %s has %s line(s)", pointer.line(), owner, this, metadata.lines());
+ checkArgument(pointer.lineOffset() >= 0, "%s is not a valid line offset for a file", pointer.lineOffset());
int lineLength = lineLength(pointer.line());
- Preconditions.checkArgument(pointer.lineOffset() <= lineLength,
+ checkArgument(pointer.lineOffset() <= lineLength,
"%s is not a valid line offset for %s. File %s has %s character(s) at line %s", pointer.lineOffset(), owner, this, lineLength, pointer.line());
}
}
private static TextRange newRangeValidPointers(TextPointer start, TextPointer end, boolean acceptEmptyRange) {
- Preconditions.checkArgument(acceptEmptyRange ? (start.compareTo(end) <= 0) : (start.compareTo(end) < 0),
+ checkArgument(acceptEmptyRange ? (start.compareTo(end) <= 0) : (start.compareTo(end) < 0),
"Start pointer %s should be before end pointer %s", start, end);
return new DefaultTextRange(start, end);
}
*/
package org.sonar.api.batch.rule.internal;
-import com.google.common.collect.ImmutableListMultimap;
-import org.sonar.api.batch.rule.ActiveRule;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.rule.RuleKey;
-
-import javax.annotation.concurrent.Immutable;
-
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.rule.ActiveRule;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.rule.RuleKey;
@Immutable
public class DefaultActiveRules implements ActiveRules {
- private final ImmutableListMultimap<String, ActiveRule> activeRulesByRepository;
+ private final Map<String, List<ActiveRule>> activeRulesByRepository = new HashMap<>();
private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndKey = new HashMap<>();
private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndInternalKey = new HashMap<>();
- private final ImmutableListMultimap<String, ActiveRule> activeRulesByLanguage;
+ private final Map<String, List<ActiveRule>> activeRulesByLanguage = new HashMap<>();
public DefaultActiveRules(Collection<NewActiveRule> newActiveRules) {
- ImmutableListMultimap.Builder<String, ActiveRule> repoBuilder = ImmutableListMultimap.builder();
- ImmutableListMultimap.Builder<String, ActiveRule> langBuilder = ImmutableListMultimap.builder();
for (NewActiveRule newAR : newActiveRules) {
DefaultActiveRule ar = new DefaultActiveRule(newAR);
String repo = ar.ruleKey().repository();
- repoBuilder.put(repo, ar);
+ activeRulesByRepository.computeIfAbsent(repo, x -> new ArrayList<>()).add(ar);
if (ar.language() != null) {
- langBuilder.put(ar.language(), ar);
+ activeRulesByLanguage.computeIfAbsent(ar.language(), x -> new ArrayList<>()).add(ar);
}
activeRulesByRepositoryAndKey.computeIfAbsent(repo, r -> new HashMap<>()).put(ar.ruleKey().rule(), ar);
activeRulesByRepositoryAndInternalKey.computeIfAbsent(repo, r -> new HashMap<>()).put(internalKey, ar);
}
}
- activeRulesByRepository = repoBuilder.build();
- activeRulesByLanguage = langBuilder.build();
}
@Override
@Override
public Collection<ActiveRule> findAll() {
- return activeRulesByRepository.values();
+ return activeRulesByRepository.entrySet().stream().flatMap(x -> x.getValue().stream()).collect(Collectors.toList());
}
@Override
public Collection<ActiveRule> findByRepository(String repository) {
- return activeRulesByRepository.get(repository);
+ return activeRulesByRepository.getOrDefault(repository, Collections.emptyList());
}
@Override
public Collection<ActiveRule> findByLanguage(String language) {
- return activeRulesByLanguage.get(language);
+ return activeRulesByLanguage.getOrDefault(language, Collections.emptyList());
}
@Override
*/
package org.sonar.api.batch.rule.internal;
-import com.google.common.collect.ImmutableTable;
-
-import com.google.common.collect.HashBasedTable;
-import org.sonar.api.batch.rule.Rule;
-import com.google.common.collect.Table;
-import com.google.common.collect.ImmutableListMultimap;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.rule.RuleKey;
-
-import javax.annotation.concurrent.Immutable;
-
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.rule.Rule;
+import org.sonar.api.batch.rule.Rules;
+import org.sonar.api.rule.RuleKey;
@Immutable
class DefaultRules implements Rules {
- private final ImmutableListMultimap<String, Rule> rulesByRepository;
- private final ImmutableTable<String, String, List<Rule>> rulesByRepositoryAndInternalKey;
+ private final Map<String, List<Rule>> rulesByRepository;
+ private final Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKey;
private final Map<RuleKey, Rule> rulesByRuleKey;
DefaultRules(Collection<NewRule> newRules) {
+ Map<String, List<Rule>> rulesByRepositoryBuilder = new HashMap<>();
+ Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKeyBuilder = new HashMap<>();
Map<RuleKey, Rule> rulesByRuleKeyBuilder = new HashMap<>();
- ImmutableListMultimap.Builder<String, Rule> builder = ImmutableListMultimap.builder();
- Table<String, String, List<Rule>> tableBuilder = HashBasedTable.create();
for (NewRule newRule : newRules) {
DefaultRule r = new DefaultRule(newRule);
rulesByRuleKeyBuilder.put(r.key(), r);
- builder.put(r.key().repository(), r);
- addToTable(tableBuilder, r);
+ rulesByRepositoryBuilder.computeIfAbsent(r.key().repository(), x -> new ArrayList<>()).add(r);
+ addToTable(rulesByRepositoryAndInternalKeyBuilder, r);
}
rulesByRuleKey = Collections.unmodifiableMap(rulesByRuleKeyBuilder);
- rulesByRepository = builder.build();
- rulesByRepositoryAndInternalKey = ImmutableTable.copyOf(tableBuilder);
+ rulesByRepository = Collections.unmodifiableMap(rulesByRepositoryBuilder);
+ rulesByRepositoryAndInternalKey = Collections.unmodifiableMap(rulesByRepositoryAndInternalKeyBuilder);
}
- private static void addToTable(Table<String, String, List<Rule>> table, DefaultRule r) {
+ private static void addToTable(Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKeyBuilder, DefaultRule r) {
if (r.internalKey() == null) {
return;
}
- List<Rule> ruleList = table.get(r.key().repository(), r.internalKey());
-
- if (ruleList == null) {
- ruleList = new LinkedList<>();
- }
-
- ruleList.add(r);
- table.put(r.key().repository(), r.internalKey(), ruleList);
+ rulesByRepositoryAndInternalKeyBuilder
+ .computeIfAbsent(r.key().repository(), x -> new HashMap<>())
+ .computeIfAbsent(r.internalKey(), x -> new ArrayList<>())
+ .add(r);
}
@Override
@Override
public Collection<Rule> findAll() {
- return rulesByRepository.values();
+ return rulesByRepository.values().stream().flatMap(List::stream).collect(Collectors.toList());
}
@Override
public Collection<Rule> findByRepository(String repository) {
- return rulesByRepository.get(repository);
+ return rulesByRepository.getOrDefault(repository, Collections.emptyList());
}
@Override
public Collection<Rule> findByInternalKey(String repository, String internalKey) {
- List<Rule> rules = rulesByRepositoryAndInternalKey.get(repository, internalKey);
-
- return rules != null ? rules : Collections.<Rule>emptyList();
+ return rulesByRepositoryAndInternalKey
+ .getOrDefault(repository, Collections.emptyMap())
+ .getOrDefault(internalKey, Collections.emptyList());
}
}
*/
package org.sonar.api.batch.sensor.code.internal;
-import com.google.common.base.Preconditions;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.annotation.Nullable;
import org.sonar.api.batch.sensor.code.NewSignificantCode;
import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.utils.Preconditions;
public class DefaultSignificantCode extends DefaultStorable implements NewSignificantCode {
private SortedMap<Integer, TextRange> significantCodePerLine = new TreeMap<>();
import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
-import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultCoverage extends DefaultStorable implements NewCoverage {
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import static com.google.common.base.Preconditions.checkState;
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
private static final Logger LOG = Loggers.get(DefaultCpdTokens.class);
*/
package org.sonar.api.batch.sensor.error.internal;
-import com.google.common.base.Preconditions;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextPointer;
import org.sonar.api.batch.sensor.error.AnalysisError;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultAnalysisError extends DefaultStorable implements NewAnalysisError, AnalysisError {
private InputFile inputFile;
@Override
public NewAnalysisError onFile(InputFile inputFile) {
- Preconditions.checkArgument(inputFile != null, "Cannot use a inputFile that is null");
- Preconditions.checkState(this.inputFile == null, "onFile() already called");
+ checkArgument(inputFile != null, "Cannot use a inputFile that is null");
+ checkState(this.inputFile == null, "onFile() already called");
this.inputFile = inputFile;
return this;
}
@Override
public NewAnalysisError at(TextPointer location) {
- Preconditions.checkState(this.location == null, "at() already called");
+ checkState(this.location == null, "at() already called");
this.location = location;
return this;
}
*/
package org.sonar.api.batch.sensor.highlighting.internal;
-import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultHighlighting extends DefaultStorable implements NewHighlighting {
}
private void checkInputFileNotNull() {
- Preconditions.checkState(inputFile != null, "Call onFile() first");
+ checkState(inputFile != null, "Call onFile() first");
}
}
*/
package org.sonar.api.batch.sensor.internal;
-import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
public abstract class DefaultStorable {
public final void save() {
requireNonNull(this.storage, "No persister on this object");
- Preconditions.checkState(!saved, "This object was already saved");
+ checkState(!saved, "This object was already saved");
doSave();
this.saved = true;
}
*/
package org.sonar.api.batch.sensor.internal;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Table;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
-import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkArgument;
class InMemorySensorStorage implements SensorStorage {
- Table<String, String, Measure> measuresByComponentAndMetric = HashBasedTable.create();
+ Map<String, Map<String, Measure>> measuresByComponentAndMetric = new HashMap<>();
Collection<Issue> allIssues = new ArrayList<>();
Collection<ExternalIssue> allExternalIssues = new ArrayList<>();
Map<String, DefaultHighlighting> highlightingByComponent = new HashMap<>();
Map<String, DefaultCpdTokens> cpdTokensByComponent = new HashMap<>();
- Multimap<String, DefaultCoverage> coverageByComponent = ArrayListMultimap.create();
+ Map<String, List<DefaultCoverage>> coverageByComponent = new HashMap<>();
Map<String, DefaultSymbolTable> symbolsPerComponent = new HashMap<>();
Map<String, String> contextProperties = new HashMap<>();
Map<String, DefaultSignificantCode> significantCodePerComponent = new HashMap<>();
// Emulate duplicate measure check
String componentKey = measure.inputComponent().key();
String metricKey = measure.metric().key();
- if (measuresByComponentAndMetric.contains(componentKey, metricKey)) {
+ if (measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).containsKey(metricKey)) {
throw new IllegalStateException("Can not add the same measure twice");
}
- measuresByComponentAndMetric.row(componentKey).put(metricKey, measure);
+ measuresByComponentAndMetric.computeIfAbsent(componentKey, x -> new HashMap<>()).put(metricKey, measure);
}
@Override
@Override
public void store(DefaultCoverage defaultCoverage) {
String fileKey = defaultCoverage.inputFile().key();
- coverageByComponent.put(fileKey, defaultCoverage);
+ coverageByComponent.computeIfAbsent(fileKey, x -> new ArrayList<>()).add(defaultCoverage);
}
@Override
public void store(DefaultExternalIssue issue) {
allExternalIssues.add(issue);
}
-
+
@Override
public void store(DefaultSignificantCode significantCode) {
String fileKey = significantCode.inputFile().key();
}
public Collection<Measure> measures(String componentKey) {
- return sensorStorage.measuresByComponentAndMetric.row(componentKey).values();
+ return sensorStorage.measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).values();
}
public <G extends Serializable> Measure<G> measure(String componentKey, Metric<G> metric) {
}
public <G extends Serializable> Measure<G> measure(String componentKey, String metricKey) {
- return sensorStorage.measuresByComponentAndMetric.row(componentKey).get(metricKey);
+ return sensorStorage.measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).get(metricKey);
}
@Override
@CheckForNull
public Integer lineHits(String fileKey, int line) {
- return sensorStorage.coverageByComponent.get(fileKey).stream()
+ return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
.map(c -> c.hitsByLine().get(line))
.flatMap(Stream::of)
.filter(Objects::nonNull)
@CheckForNull
public Integer conditions(String fileKey, int line) {
- return sensorStorage.coverageByComponent.get(fileKey).stream()
+ return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
.map(c -> c.conditionsByLine().get(line))
.flatMap(Stream::of)
.filter(Objects::nonNull)
@CheckForNull
public Integer coveredConditions(String fileKey, int line) {
- return sensorStorage.coverageByComponent.get(fileKey).stream()
+ return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
.map(c -> c.coveredConditionsByLine().get(line))
.flatMap(Stream::of)
.filter(Objects::nonNull)
*/
package org.sonar.api.batch.sensor.issue.internal;
-import com.google.common.base.Preconditions;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import org.sonar.api.batch.sensor.issue.NewIssueLocation;
import org.sonar.api.utils.PathUtils;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> extends DefaultStorable {
protected IssueLocation primaryLocation;
}
public T at(NewIssueLocation primaryLocation) {
- Preconditions.checkArgument(primaryLocation != null, "Cannot use a location that is null");
+ checkArgument(primaryLocation != null, "Cannot use a location that is null");
checkState(this.primaryLocation == null, "at() already called");
this.primaryLocation = rewriteLocation((DefaultIssueLocation) primaryLocation);
- Preconditions.checkArgument(this.primaryLocation.inputComponent() != null, "Cannot use a location with no input component");
+ checkArgument(this.primaryLocation.inputComponent() != null, "Cannot use a location with no input component");
return (T) this;
}
DefaultIssueLocation fixedLocation = new DefaultIssueLocation();
fixedLocation.on(project);
StringBuilder fullMessage = new StringBuilder();
- if (!isNullOrEmpty(path)) {
+ if (path != null && !path.isEmpty()) {
fullMessage.append("[").append(path).append("] ");
}
fullMessage.append(location.message());
*/
package org.sonar.api.batch.sensor.issue.internal;
-import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
-import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIssue> implements ExternalIssue, NewExternalIssue {
private Long effort;
@Override
public DefaultExternalIssue remediationEffortMinutes(@Nullable Long effort) {
- Preconditions.checkArgument(effort == null || effort >= 0, format("effort must be greater than or equal 0 (got %s)", effort));
+ checkArgument(effort == null || effort >= 0, format("effort must be greater than or equal 0 (got %s)", effort));
this.effort = effort;
return this;
}
*/
package org.sonar.api.batch.sensor.issue.internal;
-import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.issue.NewIssue;
import org.sonar.api.rule.RuleKey;
-import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements Issue, NewIssue {
private RuleKey ruleKey;
@Override
public DefaultIssue gap(@Nullable Double gap) {
- Preconditions.checkArgument(gap == null || gap >= 0, format("Gap must be greater than or equal 0 (got %s)", gap));
+ checkArgument(gap == null || gap >= 0, format("Gap must be greater than or equal 0 (got %s)", gap));
this.gap = gap;
return this;
}
*/
package org.sonar.api.batch.sensor.issue.internal;
-import com.google.common.base.Preconditions;
+import javax.annotation.Nullable;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.TextRange;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.issue.IssueLocation;
import org.sonar.api.batch.sensor.issue.NewIssueLocation;
-import javax.annotation.Nullable;
-
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.abbreviate;
import static org.apache.commons.lang.StringUtils.trim;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultIssueLocation implements NewIssueLocation, IssueLocation {
@Override
public DefaultIssueLocation on(InputComponent component) {
checkArgument(component != null, "Component can't be null");
- Preconditions.checkState(this.component == null, "on() already called");
+ checkState(this.component == null, "on() already called");
this.component = component;
return this;
}
@Override
public DefaultIssueLocation at(TextRange location) {
- Preconditions.checkState(this.component != null, "at() should be called after on()");
- Preconditions.checkState(this.component.isFile(), "at() should be called only for an InputFile.");
+ checkState(this.component != null, "at() should be called after on()");
+ checkState(this.component.isFile(), "at() should be called only for an InputFile.");
DefaultInputFile file = (DefaultInputFile) this.component;
file.validate(location);
this.textRange = location;
*/
package org.sonar.api.batch.sensor.measure.internal;
-import com.google.common.base.Preconditions;
import java.io.Serializable;
import javax.annotation.Nullable;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.sonar.api.batch.sensor.measure.NewMeasure;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
@Override
public DefaultMeasure<G> on(InputComponent component) {
- Preconditions.checkArgument(component != null, "Component can't be null");
- Preconditions.checkState(this.component == null, "on() already called");
+ checkArgument(component != null, "Component can't be null");
+ checkState(this.component == null, "on() already called");
this.component = component;
return this;
}
@Override
public DefaultMeasure<G> forMetric(Metric<G> metric) {
- Preconditions.checkState(this.metric == null, "Metric already defined");
+ checkState(this.metric == null, "Metric already defined");
requireNonNull(metric, "metric should be non null");
this.metric = metric;
return this;
@Override
public DefaultMeasure<G> withValue(G value) {
- Preconditions.checkState(this.value == null, "Measure value already defined");
+ checkState(this.value == null, "Measure value already defined");
requireNonNull(value, "Measure value can't be null");
this.value = value;
return this;
public void doSave() {
requireNonNull(this.value, "Measure value can't be null");
requireNonNull(this.metric, "Measure metric can't be null");
- Preconditions.checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type %s", this.metric.valueType());
+ checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type %s", this.metric.valueType());
storage.store(this);
}
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
import org.sonar.api.rules.RuleType;
-import static com.google.common.base.Preconditions.checkState;
import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultAdHocRule extends DefaultStorable implements AdHocRule, NewAdHocRule {
private Severity severity;
*/
package org.sonar.api.batch.sensor.symbol.internal;
-import com.google.common.base.Preconditions;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
public class DefaultSymbolTable extends DefaultStorable implements NewSymbolTable {
@Override
public NewSymbol newReference(TextRange range) {
requireNonNull(range, "Provided range is null");
- Preconditions.checkArgument(!declaration.overlap(range), "Overlapping symbol declaration and reference for symbol at %s", declaration);
+ checkArgument(!declaration.overlap(range), "Overlapping symbol declaration and reference for symbol at %s", declaration);
references.add(range);
return this;
}
}
private void checkInputFileNotNull() {
- Preconditions.checkState(inputFile != null, "Call onFile() first");
+ checkState(inputFile != null, "Call onFile() first");
}
}
*/
package org.sonar.api.ce.measure;
-import com.google.common.collect.Multiset;
-import com.google.common.collect.TreeMultiset;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
*/
public class RangeDistributionBuilder {
- private Multiset<Number> distributionSet;
+ private Map<Number, Integer> distributionSet;
private boolean isEmpty = true;
private Number[] bottomLimits;
private boolean isValid = true;
System.arraycopy(bottomLimits, 0, this.bottomLimits, 0, this.bottomLimits.length);
Arrays.sort(this.bottomLimits);
changeDoublesToInts();
- distributionSet = TreeMultiset.create(NumberComparator.INSTANCE);
+ distributionSet = new TreeMap<>(NumberComparator.INSTANCE);
+ for (Number n : this.bottomLimits) {
+ distributionSet.put(n, 0);
+ }
}
private void changeDoublesToInts() {
private void addValue(Number value, int count) {
for (int i = bottomLimits.length - 1; i >= 0; i--) {
if (greaterOrEqualsThan(value, bottomLimits[i])) {
- this.distributionSet.add(bottomLimits[i], count);
+ this.distributionSet.compute(bottomLimits[i], (k, v) -> v + count);
return;
}
}
if (bottomLimits == null || bottomLimits.length == 0) {
return Collections.emptyMap();
}
- Map<Number, Integer> map = new TreeMap<>();
- for (Number value : bottomLimits) {
- map.put(value, distributionSet.count(value));
- }
- return map;
+ return distributionSet;
}
private static boolean greaterOrEqualsThan(Number n1, Number n2) {
import javax.annotation.concurrent.Immutable;
import org.sonar.api.ce.measure.Component;
-import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
@Immutable
public class TestComponent implements Component {
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
@Immutable
public class TestIssue implements Issue {
import javax.annotation.concurrent.Immutable;
import org.sonar.api.ce.measure.Measure;
-import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
@Immutable
public class TestMeasure implements Measure {
*/
package org.sonar.api.ce.measure.test;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Multimap;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import org.sonar.api.ce.measure.Measure;
import org.sonar.api.ce.measure.Settings;
-import static com.google.common.base.Preconditions.checkArgument;
import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerContext;
import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinition;
+import static org.sonar.api.utils.Preconditions.checkArgument;
public class TestMeasureComputerContext implements MeasureComputerContext {
private final Settings settings;
private Map<String, Measure> componentMeasureByMetricKey = new HashMap<>();
- private Multimap<String, Measure> childrenComponentMeasureByMetricKey = ArrayListMultimap.create();
+ private Map<String, List<Measure>> childrenComponentMeasureByMetricKey = new HashMap<>();
private List<Issue> issues = new ArrayList<>();
public TestMeasureComputerContext(Component component, Settings settings, MeasureComputerDefinition definition) {
@Override
public Iterable<Measure> getChildrenMeasures(String metric) {
validateInputMetric(metric);
- return childrenComponentMeasureByMetricKey.get(metric);
+ return childrenComponentMeasureByMetricKey.getOrDefault(metric, Collections.emptyList());
}
@Override
public void addChildrenMeasures(String metricKey, Integer... values) {
for (Integer value : values) {
- childrenComponentMeasureByMetricKey.put(metricKey, TestMeasure.createMeasure(value));
+ childrenComponentMeasureByMetricKey.computeIfAbsent(metricKey, x -> new ArrayList<>()).add(TestMeasure.createMeasure(value));
}
}
public void addChildrenMeasures(String metricKey, Double... values) {
for (Double value : values) {
- childrenComponentMeasureByMetricKey.put(metricKey, TestMeasure.createMeasure(value));
+ childrenComponentMeasureByMetricKey.computeIfAbsent(metricKey, x -> new ArrayList<>()).add(TestMeasure.createMeasure(value));
}
}
public void addChildrenMeasures(String metricKey, Long... values) {
for (Long value : values) {
- childrenComponentMeasureByMetricKey.put(metricKey, TestMeasure.createMeasure(value));
+ childrenComponentMeasureByMetricKey.computeIfAbsent(metricKey, x -> new ArrayList<>()).add(TestMeasure.createMeasure(value));
}
}
componentMeasureByMetricKey.put(metricKey, TestMeasure.createMeasure(value));
}
-
public void addInputMeasure(String metricKey, boolean value) {
componentMeasureByMetricKey.put(metricKey, TestMeasure.createMeasure(value));
}
public void addChildrenMeasures(String metricKey, String... values) {
for (String value : values) {
- childrenComponentMeasureByMetricKey.put(metricKey, TestMeasure.createMeasure(value));
+ childrenComponentMeasureByMetricKey.computeIfAbsent(metricKey, x -> new ArrayList<>()).add(TestMeasure.createMeasure(value));
}
}
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
public class TestMeasureComputerDefinition implements MeasureComputer.MeasureComputerDefinition {
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* This class can be used to test {@link PostProjectAnalysisTask} implementations, see example below:
* import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newConditionBuilder;
* import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newProjectBuilder;
* import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newQualityGateBuilder;
- *
* public class CaptorPostProjectAnalysisTaskTest {
* private class CaptorPostProjectAnalysisTask implements PostProjectAnalysisTask {
* private ProjectAnalysis projectAnalysis;
- *
* {@literal @}Override
* public void finished(ProjectAnalysis analysis) {
* this.projectAnalysis = analysis;
* }
* }
- *
* {@literal @}Test
* public void execute_is_passed_a_non_null_ProjectAnalysis_object() {
* CaptorPostProjectAnalysisTask postProjectAnalysisTask = new CaptorPostProjectAnalysisTask();
- *
* PostProjectAnalysisTaskTester.of(postProjectAnalysisTask)
* .withCeTask(
* newCeTaskBuilder()
* .build(QualityGate.EvaluationStatus.OK, "value"))
* .build())
* .execute();
- *
* assertThat(postProjectAnalysisTask.projectAnalysis).isNotNull();
* }
* }
import org.sonar.api.ExtensionPoint;
import org.sonar.api.Property;
import org.sonar.api.PropertyType;
-import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.server.ServerSide;
import org.sonarsource.api.sonarlint.SonarLintSide;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.Collections.unmodifiableSet;
import static org.sonar.api.PropertyType.PROPERTY_SET;
import static org.sonar.api.PropertyType.REGULAR_EXPRESSION;
import static org.sonar.api.PropertyType.SINGLE_SELECT_LIST;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* Declare a plugin property. Values are available at runtime through the component {@link Configuration}.
* only in General Settings.
*
* @throws IllegalArgumentException only qualifiers {@link Qualifiers#PROJECT PROJECT}, {@link Qualifiers#MODULE MODULE}, {@link Qualifiers#APP APP},
- * {@link Qualifiers#VIEW VIEW} and {@link Qualifiers#SUBVIEW SVW} are allowed.
+ * {@link Qualifiers#VIEW VIEW} and {@link Qualifiers#SUBVIEW SVW} are allowed.
* @throws IllegalArgumentException only qualifiers {@link Qualifiers#PROJECT PROJECT}, {@link Qualifiers#MODULE MODULE},
* {@link Qualifiers#VIEW VIEW} and {@link Qualifiers#SUBVIEW SVW} are allowed.
*/
*/
package org.sonar.api.config;
-import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import org.sonar.api.PropertyType;
import static java.util.Arrays.asList;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 3.3
}
public PropertyFieldDefinition build() {
- Preconditions.checkArgument(!StringUtils.isEmpty(key), "Key must be set");
- Preconditions.checkArgument(!StringUtils.isEmpty(name), "Name must be set");
+ checkArgument(!StringUtils.isEmpty(key), "Key must be set");
+ checkArgument(!StringUtils.isEmpty(name), "Name must be set");
return new PropertyFieldDefinition(this);
}
}
*/
package org.sonar.api.config;
-import com.google.common.base.Splitter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.DateUtils;
import org.sonarsource.api.sonarlint.SonarLintSide;
/**
* Effective value as boolean. It is {@code false} if {@link #getString(String)}
* does not return {@code "true"}, even if it's not a boolean representation.
+ *
* @return {@code true} if the effective value is {@code "true"}, else {@code false}.
*/
public boolean getBoolean(String key) {
/**
* Effective value as {@code int}.
+ *
* @return the value as {@code int}. If the property does not have value nor default value, then {@code 0} is returned.
* @throws NumberFormatException if value is not empty and is not a parsable integer
*/
/**
* Effective value as {@code long}.
+ *
* @return the value as {@code long}. If the property does not have value nor default value, then {@code 0L} is returned.
* @throws NumberFormatException if value is not empty and is not a parsable {@code long}
*/
/**
* Effective value as {@code Float}.
+ *
* @return the value as {@code Float}. If the property does not have value nor default value, then {@code null} is returned.
* @throws NumberFormatException if value is not empty and is not a parsable number
*/
/**
* Effective value as {@code Double}.
+ *
* @return the value as {@code Double}. If the property does not have value nor default value, then {@code null} is returned.
* @throws NumberFormatException if value is not empty and is not a parsable number
*/
return ArrayUtils.EMPTY_STRING_ARRAY;
}
- List<String> values = new ArrayList<>();
- for (String v : Splitter.on(",").trimResults().split(value)) {
- values.add(v.replace("%2C", ","));
- }
- return values.toArray(new String[values.size()]);
+ return Arrays.stream(value.split(",", -1)).map(String::trim)
+ .map(s -> s.replace("%2C", ","))
+ .toArray(String[]::new);
}
return getStringArrayBySeparator(key, ",");
* Change a property value in a restricted scope only, depending on execution context. New value
* is <b>never</b> persisted. New value is ephemeral and kept in memory only:
* <ul>
- * <li>during current analysis in the case of scanner stack</li>
- * <li>during processing of current HTTP request in the case of web server stack</li>
- * <li>during execution of current task in the case of Compute Engine stack</li>
+ * <li>during current analysis in the case of scanner stack</li>
+ * <li>during processing of current HTTP request in the case of web server stack</li>
+ * <li>during execution of current task in the case of Compute Engine stack</li>
* </ul>
- *
* Property is temporarily removed if the parameter {@code value} is {@code null}
*/
public Settings setProperty(String key, @Nullable String value) {
*/
package org.sonar.api.config.internal;
-import com.google.common.annotations.VisibleForTesting;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
* <li>{@code "a,\" \",b" => "ab"]}</li>
* </ul>
*/
- @VisibleForTesting
static String trimFieldsAndRemoveEmptyFields(String str) {
char[] chars = str.toCharArray();
char[] res = new char[chars.length];
*/
package org.sonar.api.internal;
-import com.google.common.io.Resources;
import java.io.IOException;
+import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import org.sonar.api.SonarEdition;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.Version;
public static Version loadVersion(System2 system) {
try {
URL url = system.getResource(VERSION_FILE_PATH);
- String versionInFile = Resources.toString(url, StandardCharsets.UTF_8);
+ String versionInFile = new String(Files.readAllBytes(Paths.get(url.toURI())), StandardCharsets.UTF_8);
return Version.parse(versionInFile);
- } catch (IOException e) {
+ } catch (IOException | URISyntaxException e) {
throw new IllegalStateException("Can not load " + VERSION_FILE_PATH + " from classpath", e);
}
}
if (url == null) {
return SonarEdition.COMMUNITY;
}
- String editionInFile = Resources.toString(url, StandardCharsets.UTF_8);
+ String editionInFile = new String(Files.readAllBytes(Paths.get(url.toURI())), StandardCharsets.UTF_8);
return parseEdition(editionInFile);
- } catch (IOException e) {
+ } catch (IOException | URISyntaxException e) {
throw new IllegalStateException("Can not load " + EDITION_FILE_PATH + " from classpath", e);
}
}
import org.sonar.api.SonarRuntime;
import org.sonar.api.utils.Version;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 6.0
import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.server.ServerSide;
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* Used to define a metric in a plugin. Should be used with {@link Metrics} extension point.
* @param userManaged whether the metric is user managed
*/
private Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, @Nullable String domain,
- boolean userManaged) {
+ boolean userManaged) {
this.key = key;
this.description = description;
this.type = type;
if (ValueType.PERCENT == this.type) {
this.bestValue = (direction == DIRECTION_BETTER) ? 100.0 : 0.0;
this.worstValue = (direction == DIRECTION_BETTER) ? 0.0 : 100.0;
- this.decimalScale = firstNonNull(decimalScale, DEFAULT_DECIMAL_SCALE);
+ this.decimalScale = coalesce(decimalScale, DEFAULT_DECIMAL_SCALE);
} else if (ValueType.FLOAT == this.type) {
- this.decimalScale = firstNonNull(decimalScale, DEFAULT_DECIMAL_SCALE);
+ this.decimalScale = coalesce(decimalScale, DEFAULT_DECIMAL_SCALE);
}
return new Metric<>(this);
}
}
+ @CheckForNull
+ private static <T> T coalesce(@Nullable T a, @Nullable T b) {
+ return a == null ? b : a;
+ }
+
@Override
public String key() {
return getKey();
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.api.measures;
-
-import com.google.common.collect.Multiset;
-import org.sonar.api.utils.KeyValueFormat;
-
-/**
- * Format internal {@link com.google.common.collect.Multiset} of {@link CountDistributionBuilder}
- * and {@link RangeDistributionBuilder}
- */
-class MultisetDistributionFormat {
-
- private MultisetDistributionFormat() {
- // only statics
- }
-
- static String format(Multiset countBag) {
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- for (Object obj : countBag.elementSet()) {
- if (!first) {
- sb.append(KeyValueFormat.PAIR_SEPARATOR);
- }
- sb.append(obj.toString());
- sb.append(KeyValueFormat.FIELD_SEPARATOR);
- // -1 allows to include zero values
- sb.append(countBag.count(obj) - 1);
- first = false;
- }
- return sb.toString();
- }
-}
*/
package org.sonar.api.resources;
-import com.google.common.base.Preconditions;
-
import java.util.Locale;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+
/**
* Inherit this class to define a new language like PLSQL, PHP or C#
*
/**
* Better to use AbstractLanguage(key, name). In this case, key and name will be the same
- *
+ *
* @param key The key of the language. Must not be more than 20 chars.
*/
public AbstractLanguage(String key) {
/**
* Should be the constructor used to build an AbstractLanguage.
*
- * @param key the key that will be used to retrieve the language. Must not be more than 20 chars. This key is important as it will be used to teint rules repositories...
+ * @param key the key that will be used to retrieve the language. Must not be more than 20 chars. This key is important as it will be used to teint rules repositories...
* @param name the display name of the language in the interface
*/
public AbstractLanguage(String key, String name) {
- Preconditions.checkArgument(key.length() <= 20, "The following language key exceeds 20 characters: '" + key + "'");
+ checkArgument(key.length() <= 20, "The following language key exceeds 20 characters: '" + key + "'");
this.key = key.toLowerCase(Locale.ENGLISH);
this.name = name;
}
*/
package org.sonar.api.resources;
-import com.google.common.base.Preconditions;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.isEmpty;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* <p>Experimental extension to declare types of resources.
* the resource being displayed.
* <br>
* Currently, the following properties can be defined:
- *
* <ul>
* <li>"deletable": if set to "true", then this resource can be deleted/purged.</li>
* <li>"supportsMeasureFilters": if set to "true", then this resource can be displayed in measure filters</li>
*/
public static Builder builder(String qualifier) {
requireNonNull(qualifier);
- Preconditions.checkArgument(qualifier.length() <= 10, "Qualifier is limited to 10 characters");
+ checkArgument(qualifier.length() <= 10, "Qualifier is limited to 10 characters");
return new Builder(qualifier);
}
*/
package org.sonar.api.resources;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ListMultimap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
-import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.server.ServerSide;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 2.14
public class ResourceTypeTree {
private final List<ResourceType> types;
- private final ListMultimap<String, String> relations;
+ private final Map<String, List<String>> relations;
private final ResourceType root;
private ResourceTypeTree(Builder builder) {
this.types = unmodifiableList(new ArrayList<>(builder.types));
- this.relations = ImmutableListMultimap.copyOf(builder.relations);
+ this.relations = Collections.unmodifiableMap(builder.relations);
this.root = builder.root;
}
}
public List<String> getChildren(String qualifier) {
- return relations.get(qualifier);
+ return relations.getOrDefault(qualifier, Collections.emptyList());
}
public ResourceType getRootType() {
}
public List<String> getLeaves() {
- return unmodifiableList(relations.values()
+ return relations.values()
.stream()
- .filter(qualifier -> relations.get(qualifier).isEmpty())
- .collect(Collectors.toList()));
+ .flatMap(Collection::stream)
+ .filter(qualifier -> !relations.containsKey(qualifier))
+ .collect(Collectors.toList());
}
@Override
public static final class Builder {
private List<ResourceType> types = new ArrayList<>();
- private ListMultimap<String, String> relations = ArrayListMultimap.create();
+ private Map<String, List<String>> relations = new HashMap<>();
+ private List<String> children = new ArrayList<>();
private ResourceType root;
private Builder() {
requireNonNull(parentQualifier);
requireNonNull(childrenQualifiers);
checkArgument(childrenQualifiers.length > 0, "childrenQualifiers can't be empty");
- relations.putAll(parentQualifier, Arrays.asList(childrenQualifiers));
+ relations.computeIfAbsent(parentQualifier, x -> new ArrayList<>()).addAll(Arrays.asList(childrenQualifiers));
+ children.addAll(Arrays.asList(childrenQualifiers));
return this;
}
public ResourceTypeTree build() {
- Collection<String> children = relations.values();
for (ResourceType type : types) {
if (!children.contains(type.getQualifier())) {
root = type;
*/
package org.sonar.api.resources;
-import com.google.common.annotations.Beta;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
/**
* @since 2.14
*/
-@Beta
@ServerSide
@ComputeEngineSide
public class ResourceTypes {
*/
package org.sonar.api.rule;
-import com.google.common.base.Preconditions;
import java.io.Serializable;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.apache.commons.lang.StringUtils.isEmpty;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* Key of a rule. Unique among all the rule repositories.
* Create a key. Parameters are NOT null.
*/
public static RuleKey of(String repository, String rule) {
- Preconditions.checkArgument(!isEmpty(repository), "Repository must be set");
- Preconditions.checkArgument(!isEmpty(rule), "Rule must be set");
+ checkArgument(!isEmpty(repository), "Repository must be set");
+ checkArgument(!isEmpty(rule), "Rule must be set");
return new RuleKey(repository, rule);
}
*/
public static RuleKey parse(String s) {
int semiColonPos = s.indexOf(':');
- Preconditions.checkArgument(semiColonPos > 0, "Invalid rule key: " + s);
+ checkArgument(semiColonPos > 0, "Invalid rule key: " + s);
String key = s.substring(0, semiColonPos);
String repo = s.substring(semiColonPos + 1);
return RuleKey.of(key, repo);
return rule;
}
-
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
*/
package org.sonar.api.rules;
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
-import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.PropertyType;
import org.sonar.api.ce.ComputeEngineSide;
}
}
- private static final Function<Class<?>, PropertyType> TYPE_FOR_CLASS = Functions.forMap(
- ImmutableMap.<Class<?>, PropertyType>builder()
- .put(Integer.class, PropertyType.INTEGER)
- .put(int.class, PropertyType.INTEGER)
- .put(Float.class, PropertyType.FLOAT)
- .put(float.class, PropertyType.FLOAT)
- .put(Boolean.class, PropertyType.BOOLEAN)
- .put(boolean.class, PropertyType.BOOLEAN)
- .build(),
- PropertyType.STRING);
+ private static final Map<Class<?>, PropertyType> TYPE_FOR_CLASS_MAP = new HashMap<>();
+
+ static {
+ TYPE_FOR_CLASS_MAP.put(Integer.class, PropertyType.INTEGER);
+ TYPE_FOR_CLASS_MAP.put(int.class, PropertyType.INTEGER);
+ TYPE_FOR_CLASS_MAP.put(Float.class, PropertyType.FLOAT);
+ TYPE_FOR_CLASS_MAP.put(float.class, PropertyType.FLOAT);
+ TYPE_FOR_CLASS_MAP.put(Boolean.class, PropertyType.BOOLEAN);
+ TYPE_FOR_CLASS_MAP.put(boolean.class, PropertyType.BOOLEAN);
+
+ }
+
+ private static final Function<Class<?>, PropertyType> TYPE_FOR_CLASS = type -> TYPE_FOR_CLASS_MAP.getOrDefault(type, PropertyType.STRING);
static PropertyType guessType(Class<?> type) {
return TYPE_FOR_CLASS.apply(type);
*/
package org.sonar.api.rules;
-import com.google.common.base.Joiner;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
*/
public Rule setStatus(String status) {
if (!STATUS_LIST.contains(status)) {
- throw new SonarException("The status of a rule can only contain : " + Joiner.on(", ").join(STATUS_LIST));
+ throw new SonarException("The status of a rule can only contain : " + String.join(", ", STATUS_LIST));
}
this.status = status;
return this;
/**
* For internal use only.
*
- * @deprecated since 4.4, use {@link #getCharacteristicKey()}
* @since 4.3
+ * @deprecated since 4.4, use {@link #getCharacteristicKey()}
*/
@CheckForNull
@Deprecated
/**
* For internal use only.
*
- * @deprecated since 4.4, use {@link #setCharacteristicKey(String)}
* @since 4.3
+ * @deprecated since 4.4, use {@link #setCharacteristicKey(String)}
*/
@Deprecated
public Rule setCharacteristicId(@Nullable Integer characteristicId) {
/**
* For internal use only.
*
- * @deprecated since 4.4, use {@link #getDefaultCharacteristicKey()}
* @since 4.3
+ * @deprecated since 4.4, use {@link #getDefaultCharacteristicKey()}
*/
@CheckForNull
@Deprecated
/**
* For internal use only.
*
- * @deprecated since 4.4, use {@link #setDefaultCharacteristicKey(String)}
* @since 4.3
+ * @deprecated since 4.4, use {@link #setDefaultCharacteristicKey(String)}
*/
@Deprecated
public Rule setDefaultCharacteristicId(@Nullable Integer defaultCharacteristicId) {
*/
package org.sonar.api.rules;
-import com.google.common.base.Strings;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
tags.add(StringUtils.trim(cursor.collectDescendantText(false)));
}
}
- if (Strings.isNullOrEmpty(rule.getKey())) {
+ if (rule.getKey() == null || rule.getKey().isEmpty()) {
throw new SonarException("Node <key> is missing in <rule>");
}
rule.setTags(tags.toArray(new String[tags.size()]));
import javax.annotation.CheckForNull;
import javax.annotation.concurrent.Immutable;
-import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* Display information provided by the Identity Provider to be displayed into the login form.
* URL path to the provider icon, as deployed at runtime, for example "/static/authgithub/github.svg" (in this
* case "authgithub" is the plugin key. Source file is "src/main/resources/static/github.svg").
* It can also be an external URL, for example "http://www.mydomain/myincon.png".
- *
* Must not be blank.
* <br>
* The recommended format is SVG with a size of 24x24 pixels.
import javax.annotation.concurrent.Immutable;
import org.sonar.api.user.UserGroupValidation;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* User information provided by the Identity Provider to be register into the platform.
*/
package org.sonar.api.server.debt.internal;
-import com.google.common.base.MoreObjects;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.utils.Duration;
-import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkArgument;
public class DefaultDebtRemediationFunction implements DebtRemediationFunction {
return gapMultiplier();
}
-
@Override
@CheckForNull
public String gapMultiplier() {
return baseEffort;
}
-
private void validate() {
checkArgument(type != null, "Remediation function type cannot be null");
switch (type) {
return result;
}
-
@Override
public String toString() {
- return MoreObjects.toStringHelper(DebtRemediationFunction.class)
- .add("type", type)
- .add("gap multiplier", gapMultiplier)
- .add("base effort", baseEffort)
- .toString();
+ return "DebtRemediationFunction{" +
+ "type=" + type + ", " +
+ "gap multiplier=" + gapMultiplier + ", " +
+ "base effort=" + baseEffort
+ + "}";
}
}
*/
package org.sonar.api.server.profile;
-import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.sonar.api.rule.Severity;
import org.sonar.api.server.ServerSide;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* Define built-in quality profiles which are automatically registered during SonarQube startup.
* We no more provide any facility to load profiles from XML file or annotated classes, but it should
- * be straightforward to implement (adapt code of deprecated {@link org.sonar.api.profiles.AnnotationProfileParser}
+ * be straightforward to implement (adapt code of deprecated {@link org.sonar.api.profiles.AnnotationProfileParser}
* or {@link org.sonar.api.profiles.XMLProfileParser} for example).
*
* @since 6.6
private void registerProfile(NewBuiltInQualityProfileImpl newProfile) {
String language = newProfile.language();
String name = newProfile.name();
- Preconditions.checkArgument(!profilesByLanguageAndName.computeIfAbsent(language, l -> new LinkedHashMap<>()).containsKey(name),
+ checkArgument(!profilesByLanguageAndName.computeIfAbsent(language, l -> new LinkedHashMap<>()).containsKey(name),
"There is already a quality profile with name '%s' for language '%s'", name, language);
profilesByLanguageAndName.get(language).put(name, new BuiltInQualityProfileImpl(newProfile));
}
/**
* Override default rule severity in this quality profile. By default the active rule will have the default rule severity.
+ *
* @param severity See {@link Severity} constants.
*/
public NewBuiltInActiveRule overrideSeverity(String severity) {
*/
package org.sonar.api.server.rule;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Sets;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import org.sonar.api.utils.log.Loggers;
import org.sonarsource.api.sonarlint.SonarLintSide;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.emptyList;
import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.trimToNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
/**
* Defines some coding rules of the same repository. For example the Java Findbugs plugin provides an implementation of
* <h3>How to use</h3>
* <pre>
* public class MyJsRulesDefinition implements RulesDefinition {
- *
* {@literal @}Override
* public void define(Context context) {
* NewRepository repository = context.createRepository("my_js", "js").setName("My Javascript Analyzer");
- *
* // define a rule programmatically. Note that rules
* // could be loaded from files (JSON, XML, ...)
* NewRule x1Rule = repository.createRule("x1")
* .setName("No empty line")
* .setHtmlDescription("Generate an issue on empty lines")
- *
* // optional tags
* .setTags("style", "stupid")
- *
* // optional status. Default value is READY.
* .setStatus(RuleStatus.BETA)
- *
* // default severity when the rule is activated on a Quality profile. Default value is MAJOR.
* .setSeverity(Severity.MINOR);
- *
* // optional type for SonarQube Quality Model. Default is RulesDefinition.Type.CODE_SMELL.
* .setType(RulesDefinition.Type.BUG)
- *
* x1Rule
* .setDebtRemediationFunction(x1Rule.debtRemediationFunctions().linearWithOffset("1h", "30min"));
- *
* x1Rule.createParam("acceptWhitespace")
* .setDefaultValue("false")
* .setType(RuleParamType.BOOLEAN)
* .setDescription("Accept whitespaces on the line");
- *
* // don't forget to call done() to finalize the definition
* repository.done();
* }
* <br>
* <pre>
* public class MyJsRulesDefinition implements RulesDefinition {
- *
* private final RulesDefinitionXmlLoader xmlLoader;
- *
* public MyJsRulesDefinition(RulesDefinitionXmlLoader xmlLoader) {
* this.xmlLoader = xmlLoader;
* }
- *
* {@literal @}Override
* public void define(Context context) {
* NewRepository repository = context.createRepository("my_js", "js").setName("My Javascript Analyzer");
* <br>
* <pre>
* public class MyJsRulesDefinition implements RulesDefinition {
- *
* private final RulesDefinitionXmlLoader xmlLoader;
* private final RulesDefinitionI18nLoader i18nLoader;
- *
* public MyJsRulesDefinition(RulesDefinitionXmlLoader xmlLoader, RulesDefinitionI18nLoader i18nLoader) {
* this.xmlLoader = xmlLoader;
* this.i18nLoader = i18nLoader;
* }
- *
* {@literal @}Override
* public void define(Context context) {
* NewRepository repository = context.createRepository("my_js", "js").setName("My Javascript Analyzer");
/**
* Creates a repository of rules from external rule engines.
* The repository key will be "external_[engineId]".
- *
+ *
* @since 7.2
*/
public NewRepository createExternalRepository(String engineId, String language) {
* <p>
* Deprecated keys should be added with this method in order, oldest first, for documentation purpose.
*
- * @since 7.1
* @throws IllegalArgumentException if {@code repository} or {@code key} is {@code null} or empty.
* @see Rule#deprecatedRuleKeys
+ * @since 7.1
*/
public NewRule addDeprecatedRuleKey(String repository, String key) {
deprecatedRuleKeys.add(RuleKey.of(repository, key));
this.gapDescription = newRule.gapDescription;
this.scope = newRule.scope == null ? RuleScope.MAIN : newRule.scope;
this.type = newRule.type == null ? RuleTagsToTypeConverter.convert(newRule.tags) : newRule.type;
- this.tags = ImmutableSortedSet.copyOf(Sets.difference(newRule.tags, RuleTagsToTypeConverter.RESERVED_TAGS));
- this.securityStandards = ImmutableSortedSet.copyOf(newRule.securityStandards);
+ Set<String> tagsBuilder = new TreeSet<>(newRule.tags);
+ tagsBuilder.removeAll(RuleTagsToTypeConverter.RESERVED_TAGS);
+ this.tags = Collections.unmodifiableSet(tagsBuilder);
+ this.securityStandards = Collections.unmodifiableSet(new TreeSet<>(newRule.securityStandards));
Map<String, Param> paramsBuilder = new HashMap<>();
for (NewParam newParam : newRule.paramsByKey.values()) {
paramsBuilder.put(newParam.key, new Param(newParam));
}
this.params = Collections.unmodifiableMap(paramsBuilder);
this.activatedByDefault = newRule.activatedByDefault;
- this.deprecatedRuleKeys = ImmutableSortedSet.copyOf(newRule.deprecatedRuleKeys);
+ this.deprecatedRuleKeys = Collections.unmodifiableSet(new TreeSet<>(newRule.deprecatedRuleKeys));
}
public Repository repository() {
* <br>
* Consider the following use case scenario:
* <ul>
- * <li>Rule {@code Foo:A} is defined in version 1 of the plugin
+ * <li>Rule {@code Foo:A} is defined in version 1 of the plugin
* <pre>
* NewRepository newRepository = context.createRepository("Foo", "my_language");
* NewRule r = newRepository.createRule("A");
* </pre>
- * </li>
- * <li>Rule's key is renamed to B in version 2 of the plugin
+ * </li>
+ * <li>Rule's key is renamed to B in version 2 of the plugin
* <pre>
* NewRepository newRepository = context.createRepository("Foo", "my_language");
* NewRule r = newRepository.createRule("B")
* .addDeprecatedRuleKey("Foo", "A");
* </pre>
- * </li>
- * <li>All rules, including {@code Foo:B}, are moved to a new repository Bar in version 3 of the plugin
+ * </li>
+ * <li>All rules, including {@code Foo:B}, are moved to a new repository Bar in version 3 of the plugin
* <pre>
* NewRepository newRepository = context.createRepository("Bar", "my_language");
* NewRule r = newRepository.createRule("B")
* .addDeprecatedRuleKey("Foo", "A")
* .addDeprecatedRuleKey("Bar", "B");
* </pre>
- * </li>
+ * </li>
* </ul>
- *
* With all deprecated keys defined in version 3 of the plugin, SonarQube will be able to support "issue re-keying"
* for this rule in all cases:
* <ul>
- * <li>plugin upgrade from v1 to v2,</li>
- * <li>plugin upgrade from v2 to v3</li>
- * <li>AND plugin upgrade from v1 to v3</li>
+ * <li>plugin upgrade from v1 to v2,</li>
+ * <li>plugin upgrade from v2 to v3</li>
+ * <li>AND plugin upgrade from v1 to v3</li>
* </ul>
* <p>
* Finally, repository/key pairs must be unique across all rules and their deprecated keys.
* {@link NewRule#addDeprecatedRuleKey(String, String) addDeprecatedRuleKey}. This allows to describe the history
* of a rule's repositories and keys over time. Oldest repository and key must be specified first.
*
- * @since 7.1
* @see NewRule#addDeprecatedRuleKey(String, String)
+ * @since 7.1
*/
public Set<RuleKey> deprecatedRuleKeys() {
return deprecatedRuleKeys;
*/
package org.sonar.api.server.ws;
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableMap;
import java.io.BufferedReader;
import java.io.InputStream;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.utils.DateUtils;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.utils.DateUtils.parseDateQuietly;
import static org.sonar.api.utils.DateUtils.parseDateTimeQuietly;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 4.2
if (value == null) {
return null;
}
- Iterable<String> values = Splitter.on(',').omitEmptyStrings().trimResults().split(value);
- List<E> result = new ArrayList<>();
- for (String s : values) {
- result.add(Enum.valueOf(enumClass, s));
- }
-
- return result;
+ return Arrays.stream(value.split(","))
+ .map(String::trim)
+ .filter(s -> !s.isEmpty())
+ .map(x -> Enum.valueOf(enumClass, x))
+ .collect(Collectors.toList());
}
@CheckForNull
public abstract Optional<String> header(String name);
public Map<String, String> getHeaders() {
- return ImmutableMap.of();
+ return Collections.emptyMap();
}
/**
* Allows a web service to call another web service.
+ *
* @see LocalConnector
* @since 5.5
*/
/**
* Return path of the request
+ *
* @since 6.0
*/
public abstract String getPath();
/**
* @return the value of the parameter
- *
* @throws IllegalStateException if param is not present.
*/
@CheckForNull
/**
* @return the value of the parameter
- *
* @throws IllegalStateException if param is not present.
*/
@Override
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
/**
* Defines a web service.
* public void define(Context context) {
* NewController controller = context.createController("api/hello");
* controller.setDescription("Web service example");
- *
* // create the URL /api/hello/show
* controller.createAction("show")
* .setDescription("Entry point")
* }
* })
* .createParam("key").setDescription("Example key").setRequired(true);
- *
* // important to apply changes
* controller.done();
* }
/**
* Add predefined parameters related to pagination of results with a maximum page size.
+ *
* @since 7.1
*/
public NewAction addPagingParamsSince(int defaultPageSize, int maxPageSize, String version) {
this.changelog = newAction.changelog;
checkState(this.handler != null, "RequestHandler is not set on action %s", path);
- logWarningIf(isNullOrEmpty(this.description), "Description is not set on action " + path);
- logWarningIf(isNullOrEmpty(this.since), "Since is not set on action " + path);
+ logWarningIf(this.description == null || this.description.isEmpty(), "Description is not set on action " + path);
+ logWarningIf(this.since == null || this.since.isEmpty(), "Since is not set on action " + path);
logWarningIf(!this.post && this.responseExample == null, "The response example is not set on action " + path);
Map<String, Param> paramsBuilder = new HashMap<>();
}
/**
- * @since 5.3
* @see Param#since()
+ * @since 5.3
*/
public NewParam setSince(@Nullable String since) {
this.since = since;
/**
* @param deprecatedSince Version when the old key was replaced/deprecated. Ex: 5.6
- * @since 6.4
* @see Param#deprecatedKey()
+ * @since 6.4
*/
public NewParam setDeprecatedKey(@Nullable String key, @Nullable String deprecatedSince) {
this.deprecatedKey = key;
}
/**
- * @since 5.6
* @see Param#description()
+ * @since 5.6
*/
public NewParam setDescription(@Nullable String description, Object... descriptionArgument) {
this.description = description == null ? null : String.format(description, descriptionArgument);
/**
* Is the parameter required or optional ? Default value is false (optional).
*
- * @since 4.4
* @see Param#isRequired()
+ * @since 4.4
*/
public NewParam setRequired(boolean b) {
this.required = b;
* displayed only when the check-box "Show Internal API" is selected. By default
* a parameter is not internal.
*
- * @since 6.2
* @see Param#isInternal()
+ * @since 6.2
*/
public NewParam setInternal(boolean b) {
this.internal = b;
}
/**
- * @since 4.4
* @see Param#exampleValue()
+ * @since 4.4
*/
public NewParam setExampleValue(@Nullable Object s) {
this.exampleValue = (s != null) ? s.toString() : null;
* Exhaustive list of possible values when it makes sense, for example
* list of severities.
*
- * @since 4.4
* @see Param#possibleValues()
+ * @since 4.4
*/
public <T> NewParam setPossibleValues(@Nullable T... values) {
return setPossibleValues(values == null ? Collections.emptyList() : asList(values));
/**
* Shortcut for {@code setPossibleValues("true", "false", "yes", "no")}
+ *
* @since 4.4
*/
public NewParam setBooleanPossibleValues() {
* Exhaustive list of possible values when it makes sense, for example
* list of severities.
*
- * @since 4.4
* @see Param#possibleValues()
+ * @since 4.4
*/
public <T> NewParam setPossibleValues(@Nullable Collection<T> values) {
if (values == null || values.isEmpty()) {
}
/**
- * @since 4.4
* @see Param#defaultValue()
+ * @since 4.4
*/
public NewParam setDefaultValue(@Nullable Object o) {
this.defaultValue = (o != null) ? o.toString() : null;
}
/**
- * @since 6.4
* @see Param#maxValuesAllowed()
+ * @since 6.4
*/
public NewParam setMaxValuesAllowed(@Nullable Integer maxValuesAllowed) {
this.maxValuesAllowed = maxValuesAllowed;
}
/**
- * @since 7.0
* @see Param#maximumLength()
+ * @since 7.0
*/
public NewParam setMaximumLength(@Nullable Integer maximumLength) {
this.maximumLength = maximumLength;
}
/**
- * @since 7.0
* @see Param#minimumLength()
+ * @since 7.0
*/
public NewParam setMinimumLength(@Nullable Integer minimumLength) {
this.minimumLength = minimumLength;
}
/**
- * @since 7.0
* @see Param#maximumValue()
+ * @since 7.0
*/
public NewParam setMaximumValue(@Nullable Integer maximumValue) {
this.maximumValue = maximumValue;
*/
package org.sonar.api.server.ws.internal;
-import com.google.common.base.Splitter;
import java.io.InputStream;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
if (value == null) {
return null;
}
- return Splitter.on(',').omitEmptyStrings().trimResults().splitToList(value);
+
+ return Arrays.stream(value.split(",")).map(String::trim).filter(x -> !x.isEmpty()).collect(Collectors.toList());
}
@Override
*/
package org.sonar.api.server.ws.internal;
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Splitter;
import java.io.InputStream;
+import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.defaultString;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 4.2
*/
public abstract class ValidatingRequest extends Request {
- private static final Splitter COMMA_SPLITTER = Splitter.on(',').omitEmptyStrings().trimResults();
+ private static final String COMMA_SPLITTER = ",";
private WebService.Action action;
private LocalConnector localConnector;
@CheckForNull
public String param(String key) {
WebService.Param definition = action.param(key);
-
String rawValue = readParam(key, definition);
String rawValueOrDefault = defaultString(rawValue, definition.defaultValue());
- String value = rawValueOrDefault == null ? null : CharMatcher.WHITESPACE.trimFrom(rawValueOrDefault);
+ String value = rawValueOrDefault == null ? null : trim(rawValueOrDefault);
validateRequiredValue(key, definition, rawValue);
if (value == null) {
return null;
return validateValues(values, definition);
}
+ private static String trim(String s) {
+ int begin;
+ for (begin = 0; begin < s.length(); begin++) {
+ if (!Character.isWhitespace(s.charAt(begin))) {
+ break;
+ }
+ }
+
+ int end;
+ for (end = s.length(); end > begin; end--) {
+ if (!Character.isWhitespace(s.charAt(end - 1))) {
+ break;
+ }
+ }
+ return s.substring(begin, end);
+ }
+
@Override
@CheckForNull
public InputStream paramAsInputStream(String key) {
if (value == null) {
return null;
}
- List<String> values = COMMA_SPLITTER.splitToList(value);
+ List<String> values = Arrays.stream(value.split(COMMA_SPLITTER))
+ .map(String::trim)
+ .filter(s -> !s.isEmpty())
+ .collect(Collectors.toList());
return validateValues(values, definition);
}
return null;
}
return values.stream()
+ .filter(s -> !s.isEmpty())
.map(value -> Enum.valueOf(enumClass, value))
.collect(Collectors.toList());
}
*/
package org.sonar.api.task;
-import com.google.common.base.Preconditions;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.ExtensionPoint;
import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.batch.ScannerSide;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+
/**
* Register and describe a {@link TaskExtension}.
*
}
public TaskDefinition build() {
- Preconditions.checkArgument(!StringUtils.isEmpty(key), "Task key must be set");
- Preconditions.checkArgument(Pattern.matches(KEY_PATTERN, key), "Task key '" + key + "' must match " + KEY_PATTERN);
- Preconditions.checkArgument(!StringUtils.isEmpty(description), "Description must be set for task '" + key + "'");
- Preconditions.checkArgument(taskClass != null, "Class must be set for task '" + key + "'");
+ checkArgument(!StringUtils.isEmpty(key), "Task key must be set");
+ checkArgument(Pattern.matches(KEY_PATTERN, key), "Task key '" + key + "' must match " + KEY_PATTERN);
+ checkArgument(!StringUtils.isEmpty(description), "Description must be set for task '" + key + "'");
+ checkArgument(taskClass != null, "Class must be set for task '" + key + "'");
return new TaskDefinition(this);
}
}
import org.apache.commons.lang.StringUtils;
import org.sonar.api.security.DefaultGroups;
-import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkArgument;
public class UserGroupValidation {
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* Parses and formats <a href="https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html#rfc822timezone">RFC 822</a> dates.
*/
package org.sonar.api.utils;
-import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 3.6
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.utils;
+
+public class Preconditions {
+ public static void checkArgument(boolean condition, String message) {
+ if (!condition) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ public static void checkArgument(boolean condition) {
+ if (!condition) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static void checkArgument(boolean condition, String format, Object... args) {
+ if (!condition) {
+ throw new IllegalArgumentException(String.format(format, args));
+ }
+ }
+
+ public static void checkState(boolean condition, String message) {
+ if (!condition) {
+ throw new IllegalStateException(message);
+ }
+ }
+
+ public static void checkState(boolean condition, String format, Object... args) {
+ if (!condition) {
+ throw new IllegalStateException(String.format(format, args));
+ }
+ }
+}
*/
package org.sonar.api.utils;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
-import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Stream;
-import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.server.ServerSide;
/**
@Override
public String[] getSupportedSchemes() {
- return new String[]{"file"};
+ return new String[] {"file"};
}
@Override
protected byte[] readBytes(URI uri) {
try {
- return Files.toByteArray(new File(uri));
+ return Files.readAllBytes(Paths.get(uri));
} catch (IOException e) {
- throw Throwables.propagate(e);
+ throw new RuntimeException(e);
}
}
@Override
protected String readString(URI uri, Charset charset) {
try {
- return Files.toString(new File(uri), charset);
+ return new String(Files.readAllBytes(Paths.get(uri)), charset);
} catch (IOException e) {
- throw Throwables.propagate(e);
+ throw new RuntimeException(e);
}
}
*/
package org.sonar.api.utils;
-import com.google.common.base.Splitter;
-import java.util.List;
+import java.util.regex.Pattern;
import javax.annotation.concurrent.Immutable;
import static java.lang.Integer.parseInt;
private static final int DEFAULT_PATCH = 0;
private static final String DEFAULT_QUALIFIER = "";
private static final String QUALIFIER_SEPARATOR = "-";
- private static final char SEQUENCE_SEPARATOR = '.';
- private static final Splitter SEQUENCE_SPLITTER = Splitter.on(SEQUENCE_SEPARATOR);
+ private static final String SEQUENCE_SEPARATOR = ".";
private final int major;
private final int minor;
/**
* Build number if the fourth field, for example {@code 12345} for "6.3.0.12345".
* If absent, then value is zero.
+ *
* @since 6.3
*/
public long buildNumber() {
/**
* Convert a {@link String} to a Version. Supported formats:
* <ul>
- * <li>1</li>
- * <li>1.2</li>
- * <li>1.2.3</li>
- * <li>1-beta-1</li>
- * <li>1.2-beta-1</li>
- * <li>1.2.3-beta-1</li>
- * <li>1.2.3.4567</li>
- * <li>1.2.3.4567-beta-1</li>
+ * <li>1</li>
+ * <li>1.2</li>
+ * <li>1.2.3</li>
+ * <li>1-beta-1</li>
+ * <li>1.2-beta-1</li>
+ * <li>1.2.3-beta-1</li>
+ * <li>1.2.3.4567</li>
+ * <li>1.2.3.4567-beta-1</li>
* </ul>
* Note that the optional qualifier is the part after the first "-".
*
* @throws IllegalArgumentException if parameter is badly formatted, for example
- * if it defines 5 integer-sequences.
+ * if it defines 5 integer-sequences.
*/
public static Version parse(String text) {
String s = trimToEmpty(text);
if (!qualifier.isEmpty()) {
s = substringBefore(s, QUALIFIER_SEPARATOR);
}
- List<String> fields = SEQUENCE_SPLITTER.splitToList(s);
+ String[] fields = s.split(Pattern.quote(SEQUENCE_SEPARATOR));
int major = 0;
int minor = 0;
int patch = DEFAULT_PATCH;
long buildNumber = DEFAULT_BUILD_NUMBER;
- int size = fields.size();
+ int size = fields.length;
if (size > 0) {
- major = parseFieldAsInt(fields.get(0));
+ major = parseFieldAsInt(fields[0]);
if (size > 1) {
- minor = parseFieldAsInt(fields.get(1));
+ minor = parseFieldAsInt(fields[1]);
if (size > 2) {
- patch = parseFieldAsInt(fields.get(2));
+ patch = parseFieldAsInt(fields[2]);
if (size > 3) {
- buildNumber = parseFieldAsLong(fields.get(3));
+ buildNumber = parseFieldAsLong(fields[3]);
if (size > 4) {
throw new IllegalArgumentException("Maximum 4 fields are accepted: " + text);
}
*/
package org.sonar.api.utils.command;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 2.7
private final System2 system;
Command(String executable, System2 system) {
- Preconditions.checkArgument(!StringUtils.isBlank(executable), "Command executable can not be blank");
+ checkArgument(!StringUtils.isBlank(executable), "Command executable can not be blank");
this.executable = executable;
this.env = new HashMap<>(system.envVariables());
this.system = system;
/**
* Set to <code>true</code> if a new shell should be used to execute the command.
* This is useful when the executed command is a script with no execution rights (+x on unix).
- *
* On windows, the command will be executed with <code>cmd /C executable</code>.
* On other platforms, the command will be executed with <code>sh executable</code>.
*
}
public String toCommandLine() {
- return Joiner.on(" ").join(toStrings(false));
+ return String.join(" ", toStrings(false));
}
@Override
public String toString() {
- return Joiner.on(" ").join(toStrings(true));
+ return String.join(" ", toStrings(true));
}
}
import java.util.function.Supplier;
import org.sonar.api.utils.System2;
-import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* A subclass of {@link System2} which implementation of {@link System2#now()} always return a bigger value than the
*/
package org.sonar.api.utils.log;
-import com.google.common.base.Preconditions;
+import static org.sonar.api.utils.Preconditions.checkArgument;
class LogInterceptors {
}
static void set(LogInterceptor li) {
- Preconditions.checkArgument(li != null);
+ checkArgument(li != null);
instance = li;
}
}
*/
package org.sonar.api.web;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ListMultimap;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/**
* Definition of a dashboard.
private String description;
private DashboardLayout layout = DashboardLayout.TWO_COLUMNS;
- private ListMultimap<Integer, Widget> widgetsByColumn = ArrayListMultimap.create();
+ private Map<Integer, List<Widget>> widgetsByColumn = new HashMap<>();
private boolean activated = true;
private boolean global = false;
/**
* Add a widget with the given parameters, and return the newly created {@link Widget} object if one wants to add parameters to it.
- *
* <p>The widget ids are listed by the web service /api/widgets
*
* @param widgetId id of an existing widget
}
Widget widget = new Widget(widgetId);
- widgetsByColumn.put(columnId, widget);
+ widgetsByColumn.computeIfAbsent(columnId, x -> new ArrayList<>()).add(widget);
return widget;
}
public Collection<Widget> getWidgets() {
- return widgetsByColumn.values();
+ return widgetsByColumn.values().stream().flatMap(List::stream).collect(Collectors.toList());
}
public List<Widget> getWidgetsOfColumn(int columnId) {
import org.sonar.api.ExtensionPoint;
import org.sonar.api.server.ServerSide;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
import static org.apache.commons.lang.StringUtils.substringBeforeLast;
+import static org.sonar.api.utils.Preconditions.checkArgument;
/**
* @since 3.1
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.mockito.Mockito;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.assertj.core.data.MapEntry.entry;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class SensorContextTesterTest {
import java.util.Collections;
import org.junit.Test;
import org.sonar.api.rules.RuleType;
-import org.sonar.test.TestUtils;
+import org.sonar.api.utils.TestUtils;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import org.sonar.api.server.debt.DebtRemediationFunction;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.test.ExceptionCauseMatcher.hasType;
+import static org.sonar.api.utils.ExceptionCauseMatcher.hasType;
public class RulesDefinitionXmlLoaderTest {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.utils;
+
+import java.util.Objects;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * Matchers designed to be used as an argument of {@link org.junit.rules.ExpectedException#expectCause(Matcher)} such as:
+ *
+ * <pre>
+ * expectedException.expect(VisitException.class);
+ * expectedException.expectCause(hasType(IllegalArgumentException.class).andMessage("file and otherFile Components can not be the same"));
+ * </pre>
+ *
+ * Class strongly inspired from {@code CauseMatcher} class from {@code http://blog.codeleak.pl/2014/03/junit-expectedexception-rule-beyond.html}
+ */
+@Immutable
+public class ExceptionCauseMatcher extends TypeSafeMatcher<Throwable> {
+ private static final String EXPECT_NO_MESSAGE_CONSTANT = "RQXG8QTUCXOT7HZ3APPKBKUE5";
+
+ private final Class<? extends Throwable> type;
+ @CheckForNull
+ private final String expectedMessage;
+
+ private ExceptionCauseMatcher(Class<? extends Throwable> type, @Nullable String expectedMessage) {
+ this.type = type;
+ this.expectedMessage = expectedMessage;
+ }
+
+ public static ExceptionCauseMatcher hasType(Class<? extends Throwable> type) {
+ return new ExceptionCauseMatcher(type, null);
+ }
+
+ public ExceptionCauseMatcher andMessage(String expectedMessage) {
+ return new ExceptionCauseMatcher(type, Objects.requireNonNull(expectedMessage));
+ }
+
+ public ExceptionCauseMatcher andNoMessage() {
+ return new ExceptionCauseMatcher(type, EXPECT_NO_MESSAGE_CONSTANT);
+ }
+
+ @Override
+ protected boolean matchesSafely(Throwable item) {
+ if (!type.isAssignableFrom(item.getClass())) {
+ return false;
+ }
+ if (expectedMessage == null) {
+ return true;
+ }
+ if (EXPECT_NO_MESSAGE_CONSTANT.equals(expectedMessage)) {
+ return item.getMessage() == null;
+ }
+ return item.getMessage().contains(expectedMessage);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("of type ")
+ .appendValue(type);
+ if (EXPECT_NO_MESSAGE_CONSTANT.equals(expectedMessage)) {
+ description.appendText(" and no message");
+ } else if (expectedMessage != null) {
+ description.appendText(" and message ")
+ .appendValue(expectedMessage);
+ }
+ description.appendText(" but");
+ }
+}
import java.util.TreeMap;
import org.junit.Test;
import org.sonar.api.rules.RulePriority;
-import org.sonar.test.TestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
public class KeyValueFormatTest {
@Test
- public void test_parser() throws Exception {
+ public void test_parser() {
KeyValueFormat.FieldParser reader = new KeyValueFormat.FieldParser("abc=def;ghi=jkl");
assertThat(reader.nextKey()).isEqualTo("abc");
assertThat(reader.nextVal()).isEqualTo("def");
*/
package org.sonar.api.utils;
+import java.io.File;
+import java.io.IOException;
import org.apache.commons.io.FilenameUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import java.io.File;
-import java.io.IOException;
-import org.sonar.test.TestUtils;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.utils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+
+/**
+ * Utilities for unit tests
+ *
+ * @since 2.2
+ */
+public final class TestUtils {
+
+ private TestUtils() {
+ }
+
+ /**
+ * Asserts that all constructors are private, usually for helper classes with
+ * only static methods. If a constructor does not have any parameters, then
+ * it's instantiated.
+ */
+ public static boolean hasOnlyPrivateConstructors(Class clazz) {
+ boolean ok = true;
+ for (Constructor constructor : clazz.getDeclaredConstructors()) {
+ ok &= Modifier.isPrivate(constructor.getModifiers());
+ if (constructor.getParameterTypes().length == 0) {
+ constructor.setAccessible(true);
+ try {
+ constructor.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format("Fail to instantiate %s", clazz), e);
+ }
+ }
+ }
+ return ok;
+ }
+}
public void should_consume_StdOut_and_StdErr() throws Exception {
// too many false-positives on MS windows
if (!SystemUtils.IS_OS_WINDOWS) {
- final StringBuilder stdOutBuilder = new StringBuilder();
- StreamConsumer stdOutConsumer = new StreamConsumer() {
- public void consumeLine(String line) {
- stdOutBuilder.append(line).append(SystemUtils.LINE_SEPARATOR);
- }
- };
- final StringBuilder stdErrBuilder = new StringBuilder();
- StreamConsumer stdErrConsumer = new StreamConsumer() {
- public void consumeLine(String line) {
- stdErrBuilder.append(line).append(SystemUtils.LINE_SEPARATOR);
- }
- };
+ StringBuilder stdOutBuilder = new StringBuilder();
+ StreamConsumer stdOutConsumer = line -> stdOutBuilder.append(line).append(SystemUtils.LINE_SEPARATOR);
+ StringBuilder stdErrBuilder = new StringBuilder();
+ StreamConsumer stdErrConsumer = line -> stdErrBuilder.append(line).append(SystemUtils.LINE_SEPARATOR);
Command command = Command.create(getScript("output")).setDirectory(workDir);
int exitCode = CommandExecutor.create().execute(command, stdOutConsumer, stdErrConsumer, 1000L);
assertThat(exitCode).isEqualTo(0);
CommandExecutor.create().execute(command, NOP_CONSUMER, BAD_CONSUMER, 1500L);
}
- private static final StreamConsumer NOP_CONSUMER = new StreamConsumer() {
- public void consumeLine(String line) {
- // nop
- }
+ private static final StreamConsumer NOP_CONSUMER = line -> {
};
- private static final StreamConsumer BAD_CONSUMER = new StreamConsumer() {
- public void consumeLine(String line) {
- throw new RuntimeException();
- }
+ private static final StreamConsumer BAD_CONSUMER = line -> {
+ throw new RuntimeException();
};
@Test
public void should_stop_after_timeout() throws IOException {
try {
String executable = getScript("forever");
- CommandExecutor.create().execute(Command.create(executable).setDirectory(workDir), 1000L);
+ CommandExecutor.create().execute(Command.create(executable).setDirectory(workDir), 100);
fail();
} catch (TimeoutException e) {
// ok
public void should_stop_after_timeout_and_new_shell() throws IOException {
try {
String executable = getScript("forever");
- CommandExecutor.create().execute(Command.create(executable).setNewShell(true).setDirectory(workDir), 1000L);
+ CommandExecutor.create().execute(Command.create(executable).setNewShell(true).setDirectory(workDir), 100);
fail();
} catch (TimeoutException e) {
// ok
package org.sonar.api.utils.log;
import org.junit.Test;
-import org.sonar.test.TestUtils;
+import org.sonar.api.utils.TestUtils;
import static org.assertj.core.api.Assertions.assertThat;
package org.sonar.api.utils.log;
import org.junit.Test;
-import org.sonar.test.TestUtils;
+import org.sonar.api.utils.TestUtils;
import static org.assertj.core.api.Assertions.assertThat;