diff options
author | Fabrice Bellingard <bellingard@gmail.com> | 2011-04-18 16:04:44 +0200 |
---|---|---|
committer | Fabrice Bellingard <bellingard@gmail.com> | 2011-04-20 08:57:57 +0200 |
commit | d84014d6f9043632961940d292989d58e2a6e73f (patch) | |
tree | f2d4e4de25fadc0b481abf9830b23d3303969a56 /sonar-batch/src | |
parent | 906ab01373ae378f70156243259bac77cc1ab072 (diff) | |
download | sonarqube-d84014d6f9043632961940d292989d58e2a6e73f.tar.gz sonarqube-d84014d6f9043632961940d292989d58e2a6e73f.zip |
[SONAR-1957] Add ViolationQuery on SonarIndex and DecoratorContext
APIs
Diffstat (limited to 'sonar-batch/src')
3 files changed, 962 insertions, 885 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java index fde3c9099d4..4ca401c310a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java @@ -1,164 +1,175 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.batch; - -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Set; - -import com.google.common.collect.Lists; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.Event; -import org.sonar.api.batch.SonarIndex; -import org.sonar.api.design.Dependency; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasuresFilter; -import org.sonar.api.measures.MeasuresFilters; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.rules.Violation; - -public class DefaultDecoratorContext implements DecoratorContext { - - private SonarIndex index; - private Resource resource; - private boolean readOnly = false; - - private List<DecoratorContext> childrenContexts; - - public DefaultDecoratorContext(Resource resource, - SonarIndex index, - List<DecoratorContext> childrenContexts) { - this.index = index; - this.resource = resource; - this.childrenContexts = childrenContexts; - } - - public DefaultDecoratorContext setReadOnly(boolean b) { - readOnly = b; - childrenContexts = null; - return this; - } - - public Project getProject() { - return index.getProject(); - } - - public List<DecoratorContext> getChildren() { - checkReadOnly("getModules"); - return childrenContexts; - } - - private void checkReadOnly(String methodName) { - if (readOnly) { - throw new IllegalStateException("Method DecoratorContext." + methodName + "() can not be executed on children."); - } - } - - public <M> M getMeasures(MeasuresFilter<M> filter) { - return index.getMeasures(resource, filter); - } - - public Measure getMeasure(Metric metric) { - return index.getMeasure(resource, metric); - } - - public Collection<Measure> getChildrenMeasures(MeasuresFilter filter) { - List<Measure> result = Lists.newArrayList(); - for (DecoratorContext childContext : childrenContexts) { - Object childResult = childContext.getMeasures(filter); - if (childResult != null) { - if (childResult instanceof Collection) { - result.addAll((Collection) childResult); - } else { - result.add((Measure) childResult); - } - } - } - return result; - } - - public Collection<Measure> getChildrenMeasures(Metric metric) { - return getChildrenMeasures(MeasuresFilters.metric(metric)); - } - - public Resource getResource() { - return resource; - } - - public DecoratorContext saveMeasure(Measure measure) { - checkReadOnly("saveMeasure"); - index.addMeasure(resource, measure); - return this; - } - - public DecoratorContext saveMeasure(Metric metric, Double value) { - checkReadOnly("saveMeasure"); - index.addMeasure(resource, new Measure(metric, value)); - return this; - } - - public List<Violation> getViolations() { - return index.getViolations(resource); - } - - public Dependency saveDependency(Dependency dependency) { - checkReadOnly("addDependency"); - return index.addDependency(dependency); - } - - public Set<Dependency> getDependencies() { - return index.getDependencies(); - } - - public Collection<Dependency> getIncomingDependencies() { - return index.getIncomingEdges(resource); - } - - public Collection<Dependency> getOutgoingDependencies() { - return index.getOutgoingEdges(resource); - } - - public List<Event> getEvents() { - return index.getEvents(resource); - } - - public Event createEvent(String name, String description, String category, Date date) { - return index.addEvent(resource, name, description, category, date); - } - - public void deleteEvent(Event event) { - index.deleteEvent(event); - } - - public DefaultDecoratorContext saveViolation(Violation violation, boolean force) { - if (violation.getResource() == null) { - violation.setResource(resource); - } - index.addViolation(violation, force); - return this; - } - - public DefaultDecoratorContext saveViolation(Violation violation) { - return saveViolation(violation, false); - } -} +/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.Lists;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.batch.Event;
+import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilter;
+import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.violations.ViolationQuery;
+
+public class DefaultDecoratorContext implements DecoratorContext {
+
+ private SonarIndex index;
+ private Resource resource;
+ private boolean readOnly = false;
+
+ private List<DecoratorContext> childrenContexts;
+
+ public DefaultDecoratorContext(Resource resource,
+ SonarIndex index,
+ List<DecoratorContext> childrenContexts) {
+ this.index = index;
+ this.resource = resource;
+ this.childrenContexts = childrenContexts;
+ }
+
+ public DefaultDecoratorContext setReadOnly(boolean b) {
+ readOnly = b;
+ childrenContexts = null;
+ return this;
+ }
+
+ public Project getProject() {
+ return index.getProject();
+ }
+
+ public List<DecoratorContext> getChildren() {
+ checkReadOnly("getModules");
+ return childrenContexts;
+ }
+
+ private void checkReadOnly(String methodName) {
+ if (readOnly) {
+ throw new IllegalStateException("Method DecoratorContext." + methodName + "() can not be executed on children.");
+ }
+ }
+
+ public <M> M getMeasures(MeasuresFilter<M> filter) {
+ return index.getMeasures(resource, filter);
+ }
+
+ public Measure getMeasure(Metric metric) {
+ return index.getMeasure(resource, metric);
+ }
+
+ public Collection<Measure> getChildrenMeasures(MeasuresFilter filter) {
+ List<Measure> result = Lists.newArrayList();
+ for (DecoratorContext childContext : childrenContexts) {
+ Object childResult = childContext.getMeasures(filter);
+ if (childResult != null) {
+ if (childResult instanceof Collection) {
+ result.addAll((Collection) childResult);
+ } else {
+ result.add((Measure) childResult);
+ }
+ }
+ }
+ return result;
+ }
+
+ public Collection<Measure> getChildrenMeasures(Metric metric) {
+ return getChildrenMeasures(MeasuresFilters.metric(metric));
+ }
+
+ public Resource getResource() {
+ return resource;
+ }
+
+ public DecoratorContext saveMeasure(Measure measure) {
+ checkReadOnly("saveMeasure");
+ index.addMeasure(resource, measure);
+ return this;
+ }
+
+ public DecoratorContext saveMeasure(Metric metric, Double value) {
+ checkReadOnly("saveMeasure");
+ index.addMeasure(resource, new Measure(metric, value));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Violation> getViolations(ViolationQuery violationQuery) {
+ return index.getViolations(violationQuery);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Violation> getViolations() {
+ return index.getViolations(resource);
+ }
+
+ public Dependency saveDependency(Dependency dependency) {
+ checkReadOnly("addDependency");
+ return index.addDependency(dependency);
+ }
+
+ public Set<Dependency> getDependencies() {
+ return index.getDependencies();
+ }
+
+ public Collection<Dependency> getIncomingDependencies() {
+ return index.getIncomingEdges(resource);
+ }
+
+ public Collection<Dependency> getOutgoingDependencies() {
+ return index.getOutgoingEdges(resource);
+ }
+
+ public List<Event> getEvents() {
+ return index.getEvents(resource);
+ }
+
+ public Event createEvent(String name, String description, String category, Date date) {
+ return index.addEvent(resource, name, description, category, date);
+ }
+
+ public void deleteEvent(Event event) {
+ index.deleteEvent(event);
+ }
+
+ public DefaultDecoratorContext saveViolation(Violation violation, boolean force) {
+ if (violation.getResource() == null) {
+ violation.setResource(resource);
+ }
+ index.addViolation(violation, force);
+ return this;
+ }
+
+ public DefaultDecoratorContext saveViolation(Violation violation) {
+ return saveViolation(violation, false);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java index 484ab7ce54f..b8f42c96040 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java @@ -1,533 +1,549 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.batch.index; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.Event; -import org.sonar.api.batch.SonarIndex; -import org.sonar.api.database.model.ResourceModel; -import org.sonar.api.design.Dependency; -import org.sonar.api.measures.*; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.resources.*; -import org.sonar.api.rules.ActiveRule; -import org.sonar.api.rules.Violation; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.DefaultResourceCreationLock; -import org.sonar.batch.ProjectTree; -import org.sonar.batch.ResourceFilters; -import org.sonar.batch.ViolationFilters; - -import java.util.*; - -public class DefaultIndex extends SonarIndex { - - private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class); - - private RulesProfile profile; - private PersistenceManager persistence; - private DefaultResourceCreationLock lock; - private MetricFinder metricFinder; - - // filters - private ViolationFilters violationFilters; - private ResourceFilters resourceFilters; - - // caches - private Project currentProject; - private Map<Resource, Bucket> buckets = Maps.newHashMap(); - private Set<Dependency> dependencies = Sets.newHashSet(); - private Map<Resource, Map<Resource, Dependency>> outgoingDependenciesByResource = Maps.newHashMap(); - private Map<Resource, Map<Resource, Dependency>> incomingDependenciesByResource = Maps.newHashMap(); - private ProjectTree projectTree; - - public DefaultIndex(PersistenceManager persistence, DefaultResourceCreationLock lock, ProjectTree projectTree, MetricFinder metricFinder) { - this.persistence = persistence; - this.lock = lock; - this.projectTree = projectTree; - this.metricFinder = metricFinder; - } - - public void start() { - Project rootProject = projectTree.getRootProject(); - doStart(rootProject); - } - - void doStart(Project rootProject) { - Bucket bucket = new Bucket(rootProject); - buckets.put(rootProject, bucket); - persistence.saveProject(rootProject, null); - currentProject = rootProject; - - for (Project project : rootProject.getModules()) { - addProject(project); - } - } - - private void addProject(Project project) { - addResource(project); - for (Project module : project.getModules()) { - addProject(module); - } - } - - public Project getProject() { - return currentProject; - } - - public void setCurrentProject(Project project, ResourceFilters resourceFilters, ViolationFilters violationFilters, RulesProfile profile) { - this.currentProject = project; - - // the following components depend on the current project, so they need to be reloaded. - this.resourceFilters = resourceFilters; - this.violationFilters = violationFilters; - this.profile = profile; - } - - /** - * Keep only project stuff - */ - public void clear() { - Iterator<Map.Entry<Resource, Bucket>> it = buckets.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<Resource, Bucket> entry = it.next(); - Resource resource = entry.getKey(); - if (!ResourceUtils.isSet(resource)) { - entry.getValue().clear(); - it.remove(); - } - } - - Set<Dependency> projectDependencies = getDependenciesBetweenProjects(); - dependencies.clear(); - incomingDependenciesByResource.clear(); - outgoingDependenciesByResource.clear(); - for (Dependency projectDependency : projectDependencies) { - projectDependency.setId(null); - registerDependency(projectDependency); - } - - lock.unlock(); - } - - public Measure getMeasure(Resource resource, Metric metric) { - Bucket bucket = buckets.get(resource); - if (bucket != null) { - Measure measure = bucket.getMeasures(MeasuresFilters.metric(metric)); - if (measure != null) { - return persistence.reloadMeasure(measure); - } - } - return null; - } - - public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) { - Bucket bucket = buckets.get(resource); - if (bucket != null) { - // TODO the data measures which are not kept in memory are not reloaded yet. Use getMeasure(). - return bucket.getMeasures(filter); - } - return null; - } - - /** - * the measure is updated if it's already registered. - */ - public Measure addMeasure(Resource resource, Measure measure) { - Bucket bucket = checkIndexed(resource); - if (bucket != null && !bucket.isExcluded()) { - Metric metric = metricFinder.findByKey(measure.getMetricKey()); - if (metric == null) { - throw new SonarException("Unknown metric: " + measure.getMetricKey()); - } - measure.setMetric(metric); - bucket.addMeasure(measure); - - if (measure.getPersistenceMode().useDatabase()) { - persistence.saveMeasure(resource, measure); - } - } - return measure; - } - - // - // - // - // DEPENDENCIES - // - // - // - - public Dependency addDependency(Dependency dependency) { - Dependency existingDep = getEdge(dependency.getFrom(), dependency.getTo()); - if (existingDep != null) { - return existingDep; - } - - Dependency parentDependency = dependency.getParent(); - if (parentDependency != null) { - addDependency(parentDependency); - } - - if (registerDependency(dependency)) { - persistence.saveDependency(currentProject, dependency, parentDependency); - } - return dependency; - } - - boolean registerDependency(Dependency dependency) { - Bucket fromBucket = doIndex(dependency.getFrom()); - Bucket toBucket = doIndex(dependency.getTo()); - - if (fromBucket != null && !fromBucket.isExcluded() && toBucket != null && !toBucket.isExcluded()) { - dependencies.add(dependency); - registerOutgoingDependency(dependency); - registerIncomingDependency(dependency); - return true; - } - return false; - } - - private void registerOutgoingDependency(Dependency dependency) { - Map<Resource, Dependency> outgoingDeps = outgoingDependenciesByResource.get(dependency.getFrom()); - if (outgoingDeps == null) { - outgoingDeps = new HashMap<Resource, Dependency>(); - outgoingDependenciesByResource.put(dependency.getFrom(), outgoingDeps); - } - outgoingDeps.put(dependency.getTo(), dependency); - } - - private void registerIncomingDependency(Dependency dependency) { - Map<Resource, Dependency> incomingDeps = incomingDependenciesByResource.get(dependency.getTo()); - if (incomingDeps == null) { - incomingDeps = new HashMap<Resource, Dependency>(); - incomingDependenciesByResource.put(dependency.getTo(), incomingDeps); - } - incomingDeps.put(dependency.getFrom(), dependency); - } - - public Set<Dependency> getDependencies() { - return dependencies; - } - - public Dependency getEdge(Resource from, Resource to) { - Map<Resource, Dependency> map = outgoingDependenciesByResource.get(from); - if (map != null) { - return map.get(to); - } - return null; - } - - public boolean hasEdge(Resource from, Resource to) { - return getEdge(from, to) != null; - } - - public Set<Resource> getVertices() { - return buckets.keySet(); - } - - public Collection<Dependency> getOutgoingEdges(Resource from) { - Map<Resource, Dependency> deps = outgoingDependenciesByResource.get(from); - if (deps != null) { - return deps.values(); - } - return Collections.emptyList(); - } - - public Collection<Dependency> getIncomingEdges(Resource to) { - Map<Resource, Dependency> deps = incomingDependenciesByResource.get(to); - if (deps != null) { - return deps.values(); - } - return Collections.emptyList(); - } - - Set<Dependency> getDependenciesBetweenProjects() { - Set<Dependency> result = Sets.newLinkedHashSet(); - for (Dependency dependency : dependencies) { - if (ResourceUtils.isSet(dependency.getFrom()) || ResourceUtils.isSet(dependency.getTo())) { - result.add(dependency); - } - } - return result; - } - - // - // - // - // VIOLATIONS - // - // - // - - public List<Violation> getViolations(Resource resource) { - Bucket bucket = buckets.get(resource); - if (bucket == null) { - return Collections.emptyList(); - } - return bucket.getViolations(); - } - - public void addViolation(Violation violation, boolean force) { - Resource resource = violation.getResource(); - if (resource == null) { - violation.setResource(currentProject); - } else if (!Scopes.isHigherThanOrEquals(resource, Scopes.FILE)) { - throw new IllegalArgumentException("Violations are only supported on files, directories and project"); - } - - if (violation.getRule() == null) { - LOG.warn("Rule is null, ignoring violation {}", violation); - return; - } - - Bucket bucket = checkIndexed(resource); - if (bucket != null && !bucket.isExcluded()) { - boolean isIgnored = !force && violationFilters != null && violationFilters.isIgnored(violation); - if (!isIgnored) { - ActiveRule activeRule = profile.getActiveRule(violation.getRule()); - if (activeRule == null) { - if (currentProject.getReuseExistingRulesConfig()) { - violation.setSeverity(violation.getRule().getSeverity()); - doAddViolation(violation, bucket); - - } else { - LoggerFactory.getLogger(getClass()).debug("Rule is not activated, ignoring violation {}", violation); - } - - } else { - violation.setSeverity(activeRule.getSeverity()); - doAddViolation(violation, bucket); - } - } - } - } - - private void doAddViolation(Violation violation, Bucket bucket) { - bucket.addViolation(violation); - } - - // - // - // - // LINKS - // - // - // - - public void addLink(ProjectLink link) { - persistence.saveLink(currentProject, link); - } - - public void deleteLink(String key) { - persistence.deleteLink(currentProject, key); - } - - // - // - // - // EVENTS - // - // - // - - public List<Event> getEvents(Resource resource) { - // currently events are not cached in memory - return persistence.getEvents(resource); - } - - public void deleteEvent(Event event) { - persistence.deleteEvent(event); - } - - public Event addEvent(Resource resource, String name, String description, String category, Date date) { - Event event = new Event(name, description, category); - event.setDate(date); - persistence.saveEvent(resource, event); - return null; - } - - public void setSource(Resource reference, String source) { - Bucket bucket = checkIndexed(reference); - if (bucket != null && !bucket.isExcluded()) { - persistence.setSource(reference, source); - } - } - - /** - * Does nothing if the resource is already registered. - */ - public Resource addResource(Resource resource) { - Bucket bucket = doIndex(resource); - return bucket != null ? bucket.getResource() : null; - } - - public <R extends Resource> R getResource(R reference) { - Bucket bucket = buckets.get(reference); - if (bucket != null) { - return (R) bucket.getResource(); - } - return null; - } - - static String createUID(Project project, Resource resource) { - String uid = resource.getKey(); - if (!StringUtils.equals(Scopes.PROJECT, resource.getScope())) { - // not a project nor a library - uid = new StringBuilder(ResourceModel.KEY_SIZE) - .append(project.getKey()) - .append(':') - .append(resource.getKey()) - .toString(); - } - return uid; - } - - private boolean checkExclusion(Resource resource, Bucket parent) { - boolean excluded = (parent != null && parent.isExcluded()) || (resourceFilters != null && resourceFilters.isExcluded(resource)); - resource.setExcluded(excluded); - return excluded; - } - - public List<Resource> getChildren(Resource resource) { - return getChildren(resource, false); - } - - public List<Resource> getChildren(Resource resource, boolean acceptExcluded) { - List<Resource> children = Lists.newLinkedList(); - Bucket bucket = getBucket(resource, acceptExcluded); - if (bucket != null) { - for (Bucket childBucket : bucket.getChildren()) { - if (acceptExcluded || !childBucket.isExcluded()) { - children.add(childBucket.getResource()); - } - } - } - return children; - } - - public Resource getParent(Resource resource) { - Bucket bucket = getBucket(resource, false); - if (bucket != null && bucket.getParent() != null) { - return bucket.getParent().getResource(); - } - return null; - } - - public boolean index(Resource resource) { - Bucket bucket = doIndex(resource); - return bucket != null && !bucket.isExcluded(); - } - - private Bucket doIndex(Resource resource) { - if (resource.getParent() != null) { - doIndex(resource.getParent()); - } - return doIndex(resource, resource.getParent()); - } - - public boolean index(Resource resource, Resource parentReference) { - Bucket bucket = doIndex(resource, parentReference); - return bucket != null && !bucket.isExcluded(); - } - - private Bucket doIndex(Resource resource, Resource parentReference) { - Bucket bucket = buckets.get(resource); - if (bucket != null) { - return bucket; - } - - checkLock(resource); - - Resource parent = null; - if (!ResourceUtils.isLibrary(resource)) { - // a library has no parent - parent = (Resource) ObjectUtils.defaultIfNull(parentReference, currentProject); - } - - Bucket parentBucket = getBucket(parent, true); - if (parentBucket == null && parent != null) { - LOG.warn("Resource ignored, parent is not indexed: " + resource); - return null; - } - - resource.setEffectiveKey(createUID(currentProject, resource)); - bucket = new Bucket(resource).setParent(parentBucket); - buckets.put(resource, bucket); - - boolean excluded = checkExclusion(resource, parentBucket); - if (!excluded) { - persistence.saveResource(currentProject, resource, (parentBucket != null ? parentBucket.getResource() : null)); - } - return bucket; - } - - private void checkLock(Resource resource) { - if (lock.isLocked() && !ResourceUtils.isLibrary(resource)) { - if (lock.isFailWhenLocked()) { - throw new SonarException("Index is locked, resource can not be indexed: " + resource); - } - } - } - - private Bucket checkIndexed(Resource resource) { - Bucket bucket = getBucket(resource, true); - if (bucket == null) { - if (lock.isLocked()) { - if (lock.isFailWhenLocked()) { - throw new ResourceNotIndexedException(resource); - } - LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + resource); - } - if (Scopes.isDirectory(resource) || Scopes.isFile(resource)) { - bucket = doIndex(resource); - } else if (!lock.isLocked()) { - LOG.warn("Resource will be ignored in next Sonar versions, it must be indexed before adding data: " + resource); - } - } - return bucket; - } - - public boolean isExcluded(Resource reference) { - Bucket bucket = getBucket(reference, true); - return bucket != null && bucket.isExcluded(); - } - - public boolean isIndexed(Resource reference, boolean acceptExcluded) { - return getBucket(reference, acceptExcluded) != null; - } - - private Bucket getBucket(Resource resource, boolean acceptExcluded) { - Bucket bucket = null; - if (resource != null) { - bucket = buckets.get(resource); - if (!acceptExcluded && bucket != null && bucket.isExcluded()) { - bucket = null; - } - } - return bucket; - } -} +/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.index;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.Event;
+import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.database.model.ResourceModel;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.*;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.resources.*;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.SonarException;
+import org.sonar.api.violations.ViolationQuery;
+import org.sonar.batch.DefaultResourceCreationLock;
+import org.sonar.batch.ProjectTree;
+import org.sonar.batch.ResourceFilters;
+import org.sonar.batch.ViolationFilters;
+
+import java.util.*;
+
+public class DefaultIndex extends SonarIndex {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class);
+
+ private RulesProfile profile;
+ private PersistenceManager persistence;
+ private DefaultResourceCreationLock lock;
+ private MetricFinder metricFinder;
+
+ // filters
+ private ViolationFilters violationFilters;
+ private ResourceFilters resourceFilters;
+
+ // caches
+ private Project currentProject;
+ private Map<Resource, Bucket> buckets = Maps.newHashMap();
+ private Set<Dependency> dependencies = Sets.newHashSet();
+ private Map<Resource, Map<Resource, Dependency>> outgoingDependenciesByResource = Maps.newHashMap();
+ private Map<Resource, Map<Resource, Dependency>> incomingDependenciesByResource = Maps.newHashMap();
+ private ProjectTree projectTree;
+
+ public DefaultIndex(PersistenceManager persistence, DefaultResourceCreationLock lock, ProjectTree projectTree, MetricFinder metricFinder) {
+ this.persistence = persistence;
+ this.lock = lock;
+ this.projectTree = projectTree;
+ this.metricFinder = metricFinder;
+ }
+
+ public void start() {
+ Project rootProject = projectTree.getRootProject();
+ doStart(rootProject);
+ }
+
+ void doStart(Project rootProject) {
+ Bucket bucket = new Bucket(rootProject);
+ buckets.put(rootProject, bucket);
+ persistence.saveProject(rootProject, null);
+ currentProject = rootProject;
+
+ for (Project project : rootProject.getModules()) {
+ addProject(project);
+ }
+ }
+
+ private void addProject(Project project) {
+ addResource(project);
+ for (Project module : project.getModules()) {
+ addProject(module);
+ }
+ }
+
+ public Project getProject() {
+ return currentProject;
+ }
+
+ public void setCurrentProject(Project project, ResourceFilters resourceFilters, ViolationFilters violationFilters, RulesProfile profile) {
+ this.currentProject = project;
+
+ // the following components depend on the current project, so they need to be reloaded.
+ this.resourceFilters = resourceFilters;
+ this.violationFilters = violationFilters;
+ this.profile = profile;
+ }
+
+ /**
+ * Keep only project stuff
+ */
+ public void clear() {
+ Iterator<Map.Entry<Resource, Bucket>> it = buckets.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<Resource, Bucket> entry = it.next();
+ Resource resource = entry.getKey();
+ if (!ResourceUtils.isSet(resource)) {
+ entry.getValue().clear();
+ it.remove();
+ }
+ }
+
+ Set<Dependency> projectDependencies = getDependenciesBetweenProjects();
+ dependencies.clear();
+ incomingDependenciesByResource.clear();
+ outgoingDependenciesByResource.clear();
+ for (Dependency projectDependency : projectDependencies) {
+ projectDependency.setId(null);
+ registerDependency(projectDependency);
+ }
+
+ lock.unlock();
+ }
+
+ public Measure getMeasure(Resource resource, Metric metric) {
+ Bucket bucket = buckets.get(resource);
+ if (bucket != null) {
+ Measure measure = bucket.getMeasures(MeasuresFilters.metric(metric));
+ if (measure != null) {
+ return persistence.reloadMeasure(measure);
+ }
+ }
+ return null;
+ }
+
+ public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
+ Bucket bucket = buckets.get(resource);
+ if (bucket != null) {
+ // TODO the data measures which are not kept in memory are not reloaded yet. Use getMeasure().
+ return bucket.getMeasures(filter);
+ }
+ return null;
+ }
+
+ /**
+ * the measure is updated if it's already registered.
+ */
+ public Measure addMeasure(Resource resource, Measure measure) {
+ Bucket bucket = checkIndexed(resource);
+ if (bucket != null && !bucket.isExcluded()) {
+ Metric metric = metricFinder.findByKey(measure.getMetricKey());
+ if (metric == null) {
+ throw new SonarException("Unknown metric: " + measure.getMetricKey());
+ }
+ measure.setMetric(metric);
+ bucket.addMeasure(measure);
+
+ if (measure.getPersistenceMode().useDatabase()) {
+ persistence.saveMeasure(resource, measure);
+ }
+ }
+ return measure;
+ }
+
+ //
+ //
+ //
+ // DEPENDENCIES
+ //
+ //
+ //
+
+ public Dependency addDependency(Dependency dependency) {
+ Dependency existingDep = getEdge(dependency.getFrom(), dependency.getTo());
+ if (existingDep != null) {
+ return existingDep;
+ }
+
+ Dependency parentDependency = dependency.getParent();
+ if (parentDependency != null) {
+ addDependency(parentDependency);
+ }
+
+ if (registerDependency(dependency)) {
+ persistence.saveDependency(currentProject, dependency, parentDependency);
+ }
+ return dependency;
+ }
+
+ boolean registerDependency(Dependency dependency) {
+ Bucket fromBucket = doIndex(dependency.getFrom());
+ Bucket toBucket = doIndex(dependency.getTo());
+
+ if (fromBucket != null && !fromBucket.isExcluded() && toBucket != null && !toBucket.isExcluded()) {
+ dependencies.add(dependency);
+ registerOutgoingDependency(dependency);
+ registerIncomingDependency(dependency);
+ return true;
+ }
+ return false;
+ }
+
+ private void registerOutgoingDependency(Dependency dependency) {
+ Map<Resource, Dependency> outgoingDeps = outgoingDependenciesByResource.get(dependency.getFrom());
+ if (outgoingDeps == null) {
+ outgoingDeps = new HashMap<Resource, Dependency>();
+ outgoingDependenciesByResource.put(dependency.getFrom(), outgoingDeps);
+ }
+ outgoingDeps.put(dependency.getTo(), dependency);
+ }
+
+ private void registerIncomingDependency(Dependency dependency) {
+ Map<Resource, Dependency> incomingDeps = incomingDependenciesByResource.get(dependency.getTo());
+ if (incomingDeps == null) {
+ incomingDeps = new HashMap<Resource, Dependency>();
+ incomingDependenciesByResource.put(dependency.getTo(), incomingDeps);
+ }
+ incomingDeps.put(dependency.getFrom(), dependency);
+ }
+
+ public Set<Dependency> getDependencies() {
+ return dependencies;
+ }
+
+ public Dependency getEdge(Resource from, Resource to) {
+ Map<Resource, Dependency> map = outgoingDependenciesByResource.get(from);
+ if (map != null) {
+ return map.get(to);
+ }
+ return null;
+ }
+
+ public boolean hasEdge(Resource from, Resource to) {
+ return getEdge(from, to) != null;
+ }
+
+ public Set<Resource> getVertices() {
+ return buckets.keySet();
+ }
+
+ public Collection<Dependency> getOutgoingEdges(Resource from) {
+ Map<Resource, Dependency> deps = outgoingDependenciesByResource.get(from);
+ if (deps != null) {
+ return deps.values();
+ }
+ return Collections.emptyList();
+ }
+
+ public Collection<Dependency> getIncomingEdges(Resource to) {
+ Map<Resource, Dependency> deps = incomingDependenciesByResource.get(to);
+ if (deps != null) {
+ return deps.values();
+ }
+ return Collections.emptyList();
+ }
+
+ Set<Dependency> getDependenciesBetweenProjects() {
+ Set<Dependency> result = Sets.newLinkedHashSet();
+ for (Dependency dependency : dependencies) {
+ if (ResourceUtils.isSet(dependency.getFrom()) || ResourceUtils.isSet(dependency.getTo())) {
+ result.add(dependency);
+ }
+ }
+ return result;
+ }
+
+ //
+ //
+ //
+ // VIOLATIONS
+ //
+ //
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Violation> getViolations(ViolationQuery violationQuery) {
+ Resource resource = violationQuery.getResource();
+ if (resource == null) {
+ throw new IllegalArgumentException("A resource must be set on the ViolationQuery in order to search for violations.");
+ }
+ Bucket bucket = buckets.get(resource);
+ if (bucket == null) {
+ return Collections.emptyList();
+ }
+ List<Violation> filteredViolations = Lists.newArrayList();
+ boolean ignoreSwitchedOff = violationQuery.ignoreSwitchedOff();
+ for (Violation violation : bucket.getViolations()) {
+ if ( ignoreSwitchedOff && violation.isSwitchedOff()) {
+ continue;
+ }
+ filteredViolations.add(violation);
+ }
+ return filteredViolations;
+ }
+
+ public void addViolation(Violation violation, boolean force) {
+ Resource resource = violation.getResource();
+ if (resource == null) {
+ violation.setResource(currentProject);
+ } else if (!Scopes.isHigherThanOrEquals(resource, Scopes.FILE)) {
+ throw new IllegalArgumentException("Violations are only supported on files, directories and project");
+ }
+
+ if (violation.getRule() == null) {
+ LOG.warn("Rule is null, ignoring violation {}", violation);
+ return;
+ }
+
+ Bucket bucket = checkIndexed(resource);
+ if (bucket != null && !bucket.isExcluded()) {
+ boolean isIgnored = !force && violationFilters != null && violationFilters.isIgnored(violation);
+ if (!isIgnored) {
+ ActiveRule activeRule = profile.getActiveRule(violation.getRule());
+ if (activeRule == null) {
+ if (currentProject.getReuseExistingRulesConfig()) {
+ violation.setSeverity(violation.getRule().getSeverity());
+ doAddViolation(violation, bucket);
+
+ } else {
+ LoggerFactory.getLogger(getClass()).debug("Rule is not activated, ignoring violation {}", violation);
+ }
+
+ } else {
+ violation.setSeverity(activeRule.getSeverity());
+ doAddViolation(violation, bucket);
+ }
+ }
+ }
+ }
+
+ private void doAddViolation(Violation violation, Bucket bucket) {
+ bucket.addViolation(violation);
+ }
+
+ //
+ //
+ //
+ // LINKS
+ //
+ //
+ //
+
+ public void addLink(ProjectLink link) {
+ persistence.saveLink(currentProject, link);
+ }
+
+ public void deleteLink(String key) {
+ persistence.deleteLink(currentProject, key);
+ }
+
+ //
+ //
+ //
+ // EVENTS
+ //
+ //
+ //
+
+ public List<Event> getEvents(Resource resource) {
+ // currently events are not cached in memory
+ return persistence.getEvents(resource);
+ }
+
+ public void deleteEvent(Event event) {
+ persistence.deleteEvent(event);
+ }
+
+ public Event addEvent(Resource resource, String name, String description, String category, Date date) {
+ Event event = new Event(name, description, category);
+ event.setDate(date);
+ persistence.saveEvent(resource, event);
+ return null;
+ }
+
+ public void setSource(Resource reference, String source) {
+ Bucket bucket = checkIndexed(reference);
+ if (bucket != null && !bucket.isExcluded()) {
+ persistence.setSource(reference, source);
+ }
+ }
+
+ /**
+ * Does nothing if the resource is already registered.
+ */
+ public Resource addResource(Resource resource) {
+ Bucket bucket = doIndex(resource);
+ return bucket != null ? bucket.getResource() : null;
+ }
+
+ public <R extends Resource> R getResource(R reference) {
+ Bucket bucket = buckets.get(reference);
+ if (bucket != null) {
+ return (R) bucket.getResource();
+ }
+ return null;
+ }
+
+ static String createUID(Project project, Resource resource) {
+ String uid = resource.getKey();
+ if (!StringUtils.equals(Scopes.PROJECT, resource.getScope())) {
+ // not a project nor a library
+ uid = new StringBuilder(ResourceModel.KEY_SIZE)
+ .append(project.getKey())
+ .append(':')
+ .append(resource.getKey())
+ .toString();
+ }
+ return uid;
+ }
+
+ private boolean checkExclusion(Resource resource, Bucket parent) {
+ boolean excluded = (parent != null && parent.isExcluded()) || (resourceFilters != null && resourceFilters.isExcluded(resource));
+ resource.setExcluded(excluded);
+ return excluded;
+ }
+
+ public List<Resource> getChildren(Resource resource) {
+ return getChildren(resource, false);
+ }
+
+ public List<Resource> getChildren(Resource resource, boolean acceptExcluded) {
+ List<Resource> children = Lists.newLinkedList();
+ Bucket bucket = getBucket(resource, acceptExcluded);
+ if (bucket != null) {
+ for (Bucket childBucket : bucket.getChildren()) {
+ if (acceptExcluded || !childBucket.isExcluded()) {
+ children.add(childBucket.getResource());
+ }
+ }
+ }
+ return children;
+ }
+
+ public Resource getParent(Resource resource) {
+ Bucket bucket = getBucket(resource, false);
+ if (bucket != null && bucket.getParent() != null) {
+ return bucket.getParent().getResource();
+ }
+ return null;
+ }
+
+ public boolean index(Resource resource) {
+ Bucket bucket = doIndex(resource);
+ return bucket != null && !bucket.isExcluded();
+ }
+
+ private Bucket doIndex(Resource resource) {
+ if (resource.getParent() != null) {
+ doIndex(resource.getParent());
+ }
+ return doIndex(resource, resource.getParent());
+ }
+
+ public boolean index(Resource resource, Resource parentReference) {
+ Bucket bucket = doIndex(resource, parentReference);
+ return bucket != null && !bucket.isExcluded();
+ }
+
+ private Bucket doIndex(Resource resource, Resource parentReference) {
+ Bucket bucket = buckets.get(resource);
+ if (bucket != null) {
+ return bucket;
+ }
+
+ checkLock(resource);
+
+ Resource parent = null;
+ if (!ResourceUtils.isLibrary(resource)) {
+ // a library has no parent
+ parent = (Resource) ObjectUtils.defaultIfNull(parentReference, currentProject);
+ }
+
+ Bucket parentBucket = getBucket(parent, true);
+ if (parentBucket == null && parent != null) {
+ LOG.warn("Resource ignored, parent is not indexed: " + resource);
+ return null;
+ }
+
+ resource.setEffectiveKey(createUID(currentProject, resource));
+ bucket = new Bucket(resource).setParent(parentBucket);
+ buckets.put(resource, bucket);
+
+ boolean excluded = checkExclusion(resource, parentBucket);
+ if (!excluded) {
+ persistence.saveResource(currentProject, resource, (parentBucket != null ? parentBucket.getResource() : null));
+ }
+ return bucket;
+ }
+
+ private void checkLock(Resource resource) {
+ if (lock.isLocked() && !ResourceUtils.isLibrary(resource)) {
+ if (lock.isFailWhenLocked()) {
+ throw new SonarException("Index is locked, resource can not be indexed: " + resource);
+ }
+ }
+ }
+
+ private Bucket checkIndexed(Resource resource) {
+ Bucket bucket = getBucket(resource, true);
+ if (bucket == null) {
+ if (lock.isLocked()) {
+ if (lock.isFailWhenLocked()) {
+ throw new ResourceNotIndexedException(resource);
+ }
+ LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + resource);
+ }
+ if (Scopes.isDirectory(resource) || Scopes.isFile(resource)) {
+ bucket = doIndex(resource);
+ } else if (!lock.isLocked()) {
+ LOG.warn("Resource will be ignored in next Sonar versions, it must be indexed before adding data: " + resource);
+ }
+ }
+ return bucket;
+ }
+
+ public boolean isExcluded(Resource reference) {
+ Bucket bucket = getBucket(reference, true);
+ return bucket != null && bucket.isExcluded();
+ }
+
+ public boolean isIndexed(Resource reference, boolean acceptExcluded) {
+ return getBucket(reference, acceptExcluded) != null;
+ }
+
+ private Bucket getBucket(Resource resource, boolean acceptExcluded) {
+ Bucket bucket = null;
+ if (resource != null) {
+ bucket = buckets.get(resource);
+ if (!acceptExcluded && bucket != null && bucket.isExcluded()) {
+ bucket = null;
+ }
+ }
+ return bucket;
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java index 39080fe6a5b..6457cf2cc43 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java @@ -1,188 +1,238 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.batch.index; - -import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.apache.commons.lang.StringUtils; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.ResourceFilter; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasuresFilters; -import org.sonar.api.measures.MetricFinder; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.resources.*; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.Violation; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.DefaultResourceCreationLock; -import org.sonar.batch.ProjectTree; -import org.sonar.batch.ResourceFilters; -import org.sonar.batch.ViolationFilters; - -public class DefaultIndexTest { - - private DefaultIndex index = null; - private DefaultResourceCreationLock lock; - - @Before - public void createIndex() { - lock = new DefaultResourceCreationLock(); - MetricFinder metricFinder = mock(MetricFinder.class); - when(metricFinder.findByKey("ncloc")).thenReturn(CoreMetrics.NCLOC); - - index = new DefaultIndex(mock(PersistenceManager.class), lock, mock(ProjectTree.class), metricFinder); - Project project = new Project("project"); - - ResourceFilter filter = new ResourceFilter() { - public boolean isIgnored(Resource resource) { - return StringUtils.containsIgnoreCase(resource.getKey(), "excluded"); - } - }; - index.setCurrentProject(project, new ResourceFilters(new ResourceFilter[] { filter }), new ViolationFilters(), RulesProfile.create()); - index.doStart(project); - } - - @Test - public void shouldCreateUID() { - Project project = new Project("my_project"); - assertThat(DefaultIndex.createUID(project, project), is("my_project")); - - JavaPackage javaPackage = new JavaPackage("org.foo"); - assertThat(DefaultIndex.createUID(project, javaPackage), is("my_project:org.foo")); - - Library library = new Library("junit:junit", "4.7"); - assertThat(DefaultIndex.createUID(project, library), is("junit:junit")); - } - - @Test - public void shouldIndexParentOfDeprecatedFiles() { - File file = new File("org/foo/Bar.java"); - assertThat(index.index(file), is(true)); - - Directory reference = new Directory("org/foo"); - assertThat(index.getResource(reference).getName(), is("org/foo")); - assertThat(index.isIndexed(reference, true), is(true)); - assertThat(index.isExcluded(reference), is(false)); - assertThat(index.getChildren(reference).size(), is(1)); - assertThat(index.getParent(reference), is(Project.class)); - } - - @Test - public void shouldIndexTreeOfResources() { - Directory directory = new Directory("org/foo"); - File file = new File("org/foo/Bar.java"); - file.setLanguage(Java.INSTANCE); - - assertThat(index.index(directory), is(true)); - assertThat(index.index(file, directory), is(true)); - - File fileRef = new File("org/foo/Bar.java"); - assertThat(index.getResource(fileRef).getKey(), is("org/foo/Bar.java")); - assertThat(index.getResource(fileRef).getLanguage(), is((Language) Java.INSTANCE)); - assertThat(index.isIndexed(fileRef, true), is(true)); - assertThat(index.isExcluded(fileRef), is(false)); - assertThat(index.getChildren(fileRef).size(), is(0)); - assertThat(index.getParent(fileRef), is(Directory.class)); - } - - @Test - public void shouldIndexLibraryOutsideProjectTree() { - Library lib = new Library("junit", "4.8"); - assertThat(index.index(lib), is(true)); - - Library reference = new Library("junit", "4.8"); - assertThat(index.getResource(reference).getQualifier(), is(Qualifiers.LIBRARY)); - assertThat(index.isIndexed(reference, true), is(true)); - assertThat(index.isExcluded(reference), is(false)); - } - - @Test - public void shouldNotIndexResourceIfParentNotIndexed() { - Directory directory = new Directory("org/other"); - File file = new File("org/foo/Bar.java"); - - assertThat(index.index(file, directory), is(false)); - - File fileRef = new File("org/foo/Bar.java"); - assertThat(index.isIndexed(directory, true), is(false)); - assertThat(index.isIndexed(fileRef, true), is(false)); - assertThat(index.isExcluded(fileRef), is(false)); - assertThat(index.getChildren(fileRef).size(), is(0)); - assertThat(index.getParent(fileRef), nullValue()); - } - - /** - * Only a warning is logged when index is locked. - */ - @Test - public void shouldIndexEvenIfLocked() { - lock.lock(); - - Directory dir = new Directory("org/foo"); - assertThat(index.index(dir), is(true)); - assertThat(index.isIndexed(dir, true), is(true)); - } - - @Test(expected = SonarException.class) - public void shouldFailIfIndexingAndLocked() { - lock.setFailWhenLocked(true); - lock.lock(); - - Directory dir = new Directory("org/foo"); - index.index(dir); - } - - @Test - public void shouldBeExcluded() { - File file = new File("org/foo/ExcludedBar.java"); - assertThat(index.index(file), is(false)); - assertThat(index.isIndexed(file, true), is(true)); - assertThat(index.isIndexed(file, false), is(false)); - assertThat(index.isExcluded(file), is(true)); - } - - @Test - public void shouldIndexResourceWhenAddingMeasure() { - Resource dir = new Directory("org/foo"); - index.addMeasure(dir, new Measure("ncloc").setValue(50.0)); - - assertThat(index.isIndexed(dir, true), is(true)); - assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc")).getIntValue(), is(50)); - } - - /** - * See http://jira.codehaus.org/browse/SONAR-2107 - */ - @Test - public void shouldNotFailWhenSavingViolationOnNullRule() { - File file = new File("org/foo/Bar.java"); - Violation violation = Violation.create((Rule) null, file); - index.addViolation(violation); - - assertThat(index.getViolations(file).size(), is(0)); - } -} +/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.index;
+
+import static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.ResourceFilter;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.resources.Directory;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.JavaPackage;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Library;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.SonarException;
+import org.sonar.api.violations.ViolationQuery;
+import org.sonar.batch.DefaultResourceCreationLock;
+import org.sonar.batch.ProjectTree;
+import org.sonar.batch.ResourceFilters;
+import org.sonar.batch.ViolationFilters;
+
+public class DefaultIndexTest {
+
+ private DefaultIndex index = null;
+ private DefaultResourceCreationLock lock;
+ private Rule rule;
+
+ @Before
+ public void createIndex() {
+ lock = new DefaultResourceCreationLock();
+ MetricFinder metricFinder = mock(MetricFinder.class);
+ when(metricFinder.findByKey("ncloc")).thenReturn(CoreMetrics.NCLOC);
+
+ index = new DefaultIndex(mock(PersistenceManager.class), lock, mock(ProjectTree.class), metricFinder);
+ Project project = new Project("project");
+
+ ResourceFilter filter = new ResourceFilter() {
+
+ public boolean isIgnored(Resource resource) {
+ return StringUtils.containsIgnoreCase(resource.getKey(), "excluded");
+ }
+ };
+ RulesProfile rulesProfile = RulesProfile.create();
+ rule = Rule.create("repoKey", "ruleKey", "Rule");
+ rulesProfile.activateRule(rule, null);
+ index.setCurrentProject(project, new ResourceFilters(new ResourceFilter[] { filter }), new ViolationFilters(), rulesProfile);
+ index.doStart(project);
+ }
+
+ @Test
+ public void shouldCreateUID() {
+ Project project = new Project("my_project");
+ assertThat(DefaultIndex.createUID(project, project), is("my_project"));
+
+ JavaPackage javaPackage = new JavaPackage("org.foo");
+ assertThat(DefaultIndex.createUID(project, javaPackage), is("my_project:org.foo"));
+
+ Library library = new Library("junit:junit", "4.7");
+ assertThat(DefaultIndex.createUID(project, library), is("junit:junit"));
+ }
+
+ @Test
+ public void shouldIndexParentOfDeprecatedFiles() {
+ File file = new File("org/foo/Bar.java");
+ assertThat(index.index(file), is(true));
+
+ Directory reference = new Directory("org/foo");
+ assertThat(index.getResource(reference).getName(), is("org/foo"));
+ assertThat(index.isIndexed(reference, true), is(true));
+ assertThat(index.isExcluded(reference), is(false));
+ assertThat(index.getChildren(reference).size(), is(1));
+ assertThat(index.getParent(reference), is(Project.class));
+ }
+
+ @Test
+ public void shouldIndexTreeOfResources() {
+ Directory directory = new Directory("org/foo");
+ File file = new File("org/foo/Bar.java");
+ file.setLanguage(Java.INSTANCE);
+
+ assertThat(index.index(directory), is(true));
+ assertThat(index.index(file, directory), is(true));
+
+ File fileRef = new File("org/foo/Bar.java");
+ assertThat(index.getResource(fileRef).getKey(), is("org/foo/Bar.java"));
+ assertThat(index.getResource(fileRef).getLanguage(), is((Language) Java.INSTANCE));
+ assertThat(index.isIndexed(fileRef, true), is(true));
+ assertThat(index.isExcluded(fileRef), is(false));
+ assertThat(index.getChildren(fileRef).size(), is(0));
+ assertThat(index.getParent(fileRef), is(Directory.class));
+ }
+
+ @Test
+ public void shouldIndexLibraryOutsideProjectTree() {
+ Library lib = new Library("junit", "4.8");
+ assertThat(index.index(lib), is(true));
+
+ Library reference = new Library("junit", "4.8");
+ assertThat(index.getResource(reference).getQualifier(), is(Qualifiers.LIBRARY));
+ assertThat(index.isIndexed(reference, true), is(true));
+ assertThat(index.isExcluded(reference), is(false));
+ }
+
+ @Test
+ public void shouldNotIndexResourceIfParentNotIndexed() {
+ Directory directory = new Directory("org/other");
+ File file = new File("org/foo/Bar.java");
+
+ assertThat(index.index(file, directory), is(false));
+
+ File fileRef = new File("org/foo/Bar.java");
+ assertThat(index.isIndexed(directory, true), is(false));
+ assertThat(index.isIndexed(fileRef, true), is(false));
+ assertThat(index.isExcluded(fileRef), is(false));
+ assertThat(index.getChildren(fileRef).size(), is(0));
+ assertThat(index.getParent(fileRef), nullValue());
+ }
+
+ /**
+ * Only a warning is logged when index is locked.
+ */
+ @Test
+ public void shouldIndexEvenIfLocked() {
+ lock.lock();
+
+ Directory dir = new Directory("org/foo");
+ assertThat(index.index(dir), is(true));
+ assertThat(index.isIndexed(dir, true), is(true));
+ }
+
+ @Test(expected = SonarException.class)
+ public void shouldFailIfIndexingAndLocked() {
+ lock.setFailWhenLocked(true);
+ lock.lock();
+
+ Directory dir = new Directory("org/foo");
+ index.index(dir);
+ }
+
+ @Test
+ public void shouldBeExcluded() {
+ File file = new File("org/foo/ExcludedBar.java");
+ assertThat(index.index(file), is(false));
+ assertThat(index.isIndexed(file, true), is(true));
+ assertThat(index.isIndexed(file, false), is(false));
+ assertThat(index.isExcluded(file), is(true));
+ }
+
+ @Test
+ public void shouldIndexResourceWhenAddingMeasure() {
+ Resource dir = new Directory("org/foo");
+ index.addMeasure(dir, new Measure("ncloc").setValue(50.0));
+
+ assertThat(index.isIndexed(dir, true), is(true));
+ assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc")).getIntValue(), is(50));
+ }
+
+ /**
+ * See http://jira.codehaus.org/browse/SONAR-2107
+ */
+ @Test
+ public void shouldNotFailWhenSavingViolationOnNullRule() {
+ File file = new File("org/foo/Bar.java");
+ Violation violation = Violation.create((Rule) null, file);
+ index.addViolation(violation);
+
+ assertThat(index.getViolations(file).size(), is(0));
+ }
+
+ @Test
+ public void testGetViolations() {
+ File file = new File("org/foo/Bar.java");
+ Violation violation1 = Violation.create(rule, file);
+ index.addViolation(violation1);
+ Violation violation2 = Violation.create(rule, file);
+ violation2.setSwitchedOff(true);
+ index.addViolation(violation2);
+ Violation violation3 = Violation.create(rule, file);
+ violation3.setSwitchedOff(true);
+ index.addViolation(violation3);
+
+ assertThat(index.getViolations(file).size(), is(1));
+ }
+
+ @Test
+ public void testGetViolationsWithQuery() {
+ File file = new File("org/foo/Bar.java");
+ Violation violation1 = Violation.create(rule, file);
+ index.addViolation(violation1);
+ Violation violation2 = Violation.create(rule, file);
+ violation2.setSwitchedOff(true);
+ index.addViolation(violation2);
+ Violation violation3 = Violation.create(rule, file);
+ violation3.setSwitchedOff(true);
+ index.addViolation(violation3);
+
+ assertThat(index.getViolations(ViolationQuery.create().forResource(file).ignoreSwitchedOff(false)).size(), is(3));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetViolationsWithQueryWithNoResource() {
+ index.getViolations(ViolationQuery.create());
+ }
+
+}
|