diff options
34 files changed, 3594 insertions, 3594 deletions
@@ -1,4 +1,4 @@ - GNU LESSER GENERAL PUBLIC LICENSE + GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> diff --git a/deploy-docs.sh b/deploy-docs.sh index 6413b469e6a..6bcd4c42542 100644 --- a/deploy-docs.sh +++ b/deploy-docs.sh @@ -6,4 +6,4 @@ tar -cf docs.tar -C target/site/ . scp -i ~/.ssh/id_rsa-sonar-keypair -C -r docs.tar root@ec2-75-101-133-159.compute-1.amazonaws.com:/tmp -ssh -i ~/.ssh/id_rsa-sonar-keypair root@ec2-75-101-133-159.compute-1.amazonaws.com 'tar -xf /tmp/docs.tar -C /vol/www/sonar.codehaus.org/docs'
\ No newline at end of file +ssh -i ~/.ssh/id_rsa-sonar-keypair root@ec2-75-101-133-159.compute-1.amazonaws.com 'tar -xf /tmp/docs.tar -C /vol/www/sonar.codehaus.org/docs' diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewsDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewsDecorator.java index 1faef7c4f66..c0b5b7ef94c 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewsDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewsDecorator.java @@ -1,71 +1,71 @@ -/*
- * 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.plugins.core.sensors;
-
-import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
-import javax.persistence.Query;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.Decorator;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.batch.DependedUpon;
-import org.sonar.api.batch.DependsUpon;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.batch.index.ResourcePersister;
-
-/**
- * Decorator that currently only closes a review when its corresponding violation has been fixed.
- */
-@DependsUpon("ViolationPersisterDecorator")
-public class ReviewsDecorator implements Decorator {
-
- private static final Logger LOG = LoggerFactory.getLogger(ReviewsDecorator.class);
-
- private ResourcePersister resourcePersister;
- private DatabaseSession databaseSession;
-
- public ReviewsDecorator(ResourcePersister resourcePersister, DatabaseSession databaseSession) {
- this.resourcePersister = resourcePersister;
- this.databaseSession = databaseSession;
- }
-
- public boolean shouldExecuteOnProject(Project project) {
- return true;
- }
-
- public void decorate(Resource resource, DecoratorContext context) {
- Snapshot currentSnapshot = resourcePersister.getSnapshot(resource);
- if (currentSnapshot != null) {
- int resourceId = currentSnapshot.getResourceId();
- int snapshotId = currentSnapshot.getId();
- Query query = databaseSession.createNativeQuery("UPDATE reviews SET status='closed' " + "WHERE resource_id = " + resourceId
- + " AND rule_failure_permanent_id NOT IN " + "(SELECT permanent_id FROM rule_failures WHERE snapshot_id = " + snapshotId + ")");
- int rowUpdated = query.executeUpdate();
- LOG.debug("- {} reviews set to 'closed' on resource #{}", rowUpdated, resourceId);
- databaseSession.commit();
- }
- }
-
-}
+/* + * 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.plugins.core.sensors; + +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; +import javax.persistence.Query; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.database.DatabaseSession; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.batch.index.ResourcePersister; + +/** + * Decorator that currently only closes a review when its corresponding violation has been fixed. + */ +@DependsUpon("ViolationPersisterDecorator") +public class ReviewsDecorator implements Decorator { + + private static final Logger LOG = LoggerFactory.getLogger(ReviewsDecorator.class); + + private ResourcePersister resourcePersister; + private DatabaseSession databaseSession; + + public ReviewsDecorator(ResourcePersister resourcePersister, DatabaseSession databaseSession) { + this.resourcePersister = resourcePersister; + this.databaseSession = databaseSession; + } + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + public void decorate(Resource resource, DecoratorContext context) { + Snapshot currentSnapshot = resourcePersister.getSnapshot(resource); + if (currentSnapshot != null) { + int resourceId = currentSnapshot.getResourceId(); + int snapshotId = currentSnapshot.getId(); + Query query = databaseSession.createNativeQuery("UPDATE reviews SET status='closed' " + "WHERE resource_id = " + resourceId + + " AND rule_failure_permanent_id NOT IN " + "(SELECT permanent_id FROM rule_failures WHERE snapshot_id = " + snapshotId + ")"); + int rowUpdated = query.executeUpdate(); + LOG.debug("- {} reviews set to 'closed' on resource #{}", rowUpdated, resourceId); + databaseSession.commit(); + } + } + +} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java index 455ec647f94..59ad0a168ca 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java @@ -1,196 +1,196 @@ -/*
- * 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.plugins.core.timemachine;
-
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.StringUtils;
-import org.codehaus.plexus.util.StringInputStream;
-import org.sonar.api.batch.*;
-import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.SnapshotSource;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.Violation;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.components.PastViolationsLoader;
-import org.sonar.batch.index.ViolationPersister;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-@DependsUpon(DecoratorBarriers.END_OF_VIOLATIONS_GENERATION)
-@DependedUpon("ViolationPersisterDecorator") /* temporary workaround - see NewViolationsDecorator */
-public class ViolationPersisterDecorator implements Decorator {
-
- /**
- * Those chars would be ignored during generation of checksums.
- */
- private static final String SPACE_CHARS = "\t\n\r ";
-
- private RuleFinder ruleFinder;
- private PastViolationsLoader pastViolationsLoader;
- private ViolationPersister violationPersister;
-
- List<String> checksums = Lists.newArrayList();
-
- public ViolationPersisterDecorator(RuleFinder ruleFinder, PastViolationsLoader pastViolationsLoader, ViolationPersister violationPersister) {
- this.ruleFinder = ruleFinder;
- this.pastViolationsLoader = pastViolationsLoader;
- this.violationPersister = violationPersister;
- }
-
- public boolean shouldExecuteOnProject(Project project) {
- return true;
- }
-
- public void decorate(Resource resource, DecoratorContext context) {
- if (context.getViolations().isEmpty()) {
- return;
- }
- // Load past violations
- List<RuleFailureModel> pastViolations = pastViolationsLoader.getPastViolations(resource);
- // Load current source and calculate checksums
- checksums = getChecksums(pastViolationsLoader.getSource(resource));
- // Save violations
- compareWithPastViolations(context, pastViolations);
- // Clear cache
- checksums.clear();
- }
-
- private void compareWithPastViolations(DecoratorContext context, List<RuleFailureModel> pastViolations) {
- Multimap<Rule, RuleFailureModel> pastViolationsByRule = LinkedHashMultimap.create();
- for (RuleFailureModel pastViolation : pastViolations) {
- Rule rule = ruleFinder.findById(pastViolation.getRuleId());
- pastViolationsByRule.put(rule, pastViolation);
- }
- // for each violation, search equivalent past violation
- for (Violation violation : context.getViolations()) {
- RuleFailureModel pastViolation = selectPastViolation(violation, pastViolationsByRule);
- if (pastViolation != null) {
- // remove violation, since would be updated and shouldn't affect other violations anymore
- pastViolationsByRule.remove(violation.getRule(), pastViolation);
- }
- String checksum = getChecksumForLine(checksums, violation.getLineId());
- violationPersister.saveViolation(context.getProject(), violation, pastViolation, checksum);
- }
- violationPersister.commit();
- }
-
- /**
- * @return checksums, never null
- */
- private List<String> getChecksums(SnapshotSource source) {
- return source == null || source.getData() == null ? Collections.<String>emptyList() : getChecksums(source.getData());
- }
-
- static List<String> getChecksums(String data) {
- List<String> result = Lists.newArrayList();
- StringInputStream stream = new StringInputStream(data);
- try {
- List<String> lines = IOUtils.readLines(stream);
- for (String line : lines) {
- result.add(getChecksum(line));
- }
- } catch (IOException e) {
- throw new SonarException("Unable to calculate checksums", e);
-
- } finally {
- IOUtils.closeQuietly(stream);
- }
- return result;
- }
-
- static String getChecksum(String line) {
- String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, "");
- return DigestUtils.md5Hex(reducedLine);
- }
-
- /**
- * @return checksum or null if checksum not exists for line
- */
- private String getChecksumForLine(List<String> checksums, Integer line) {
- if (line == null || line < 1 || line > checksums.size()) {
- return null;
- }
- return checksums.get(line - 1);
- }
-
- /**
- * Search for past violation.
- */
- RuleFailureModel selectPastViolation(Violation violation, Multimap<Rule, RuleFailureModel> pastViolationsByRule) {
- Collection<RuleFailureModel> pastViolations = pastViolationsByRule.get(violation.getRule());
- if (pastViolations==null || pastViolations.isEmpty()) {
- // skip violation, if there is no past violations with same rule
- return null;
- }
- String dbFormattedMessage = RuleFailureModel.abbreviateMessage(violation.getMessage());
- RuleFailureModel found = selectPastViolationUsingLine(violation, dbFormattedMessage, pastViolations);
- if (found == null) {
- found = selectPastViolationUsingChecksum(violation, dbFormattedMessage, pastViolations);
- }
- return found;
- }
-
- /**
- * Search for past violation with same message and line.
- */
- private RuleFailureModel selectPastViolationUsingLine(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) {
- for (RuleFailureModel pastViolation : pastViolations) {
- if (ObjectUtils.equals(violation.getLineId(), pastViolation.getLine()) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) {
- return pastViolation;
- }
- }
- return null;
- }
-
- /**
- * Search for past violation with same message and checksum.
- */
- private RuleFailureModel selectPastViolationUsingChecksum(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) {
- String checksum = getChecksumForLine(checksums, violation.getLineId());
- // skip violation, which not attached to line
- if (checksum == null) {
- return null;
- }
- for (RuleFailureModel pastViolation : pastViolations) {
- String pastChecksum = pastViolation.getChecksum();
- if (StringUtils.equals(checksum, pastChecksum) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) {
- return pastViolation;
- }
- }
- return null;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName();
- }
-
+/* + * 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.plugins.core.timemachine; + +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; +import org.codehaus.plexus.util.StringInputStream; +import org.sonar.api.batch.*; +import org.sonar.api.database.model.RuleFailureModel; +import org.sonar.api.database.model.SnapshotSource; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.rules.Violation; +import org.sonar.api.utils.SonarException; +import org.sonar.batch.components.PastViolationsLoader; +import org.sonar.batch.index.ViolationPersister; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +@DependsUpon(DecoratorBarriers.END_OF_VIOLATIONS_GENERATION) +@DependedUpon("ViolationPersisterDecorator") /* temporary workaround - see NewViolationsDecorator */ +public class ViolationPersisterDecorator implements Decorator { + + /** + * Those chars would be ignored during generation of checksums. + */ + private static final String SPACE_CHARS = "\t\n\r "; + + private RuleFinder ruleFinder; + private PastViolationsLoader pastViolationsLoader; + private ViolationPersister violationPersister; + + List<String> checksums = Lists.newArrayList(); + + public ViolationPersisterDecorator(RuleFinder ruleFinder, PastViolationsLoader pastViolationsLoader, ViolationPersister violationPersister) { + this.ruleFinder = ruleFinder; + this.pastViolationsLoader = pastViolationsLoader; + this.violationPersister = violationPersister; + } + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + public void decorate(Resource resource, DecoratorContext context) { + if (context.getViolations().isEmpty()) { + return; + } + // Load past violations + List<RuleFailureModel> pastViolations = pastViolationsLoader.getPastViolations(resource); + // Load current source and calculate checksums + checksums = getChecksums(pastViolationsLoader.getSource(resource)); + // Save violations + compareWithPastViolations(context, pastViolations); + // Clear cache + checksums.clear(); + } + + private void compareWithPastViolations(DecoratorContext context, List<RuleFailureModel> pastViolations) { + Multimap<Rule, RuleFailureModel> pastViolationsByRule = LinkedHashMultimap.create(); + for (RuleFailureModel pastViolation : pastViolations) { + Rule rule = ruleFinder.findById(pastViolation.getRuleId()); + pastViolationsByRule.put(rule, pastViolation); + } + // for each violation, search equivalent past violation + for (Violation violation : context.getViolations()) { + RuleFailureModel pastViolation = selectPastViolation(violation, pastViolationsByRule); + if (pastViolation != null) { + // remove violation, since would be updated and shouldn't affect other violations anymore + pastViolationsByRule.remove(violation.getRule(), pastViolation); + } + String checksum = getChecksumForLine(checksums, violation.getLineId()); + violationPersister.saveViolation(context.getProject(), violation, pastViolation, checksum); + } + violationPersister.commit(); + } + + /** + * @return checksums, never null + */ + private List<String> getChecksums(SnapshotSource source) { + return source == null || source.getData() == null ? Collections.<String>emptyList() : getChecksums(source.getData()); + } + + static List<String> getChecksums(String data) { + List<String> result = Lists.newArrayList(); + StringInputStream stream = new StringInputStream(data); + try { + List<String> lines = IOUtils.readLines(stream); + for (String line : lines) { + result.add(getChecksum(line)); + } + } catch (IOException e) { + throw new SonarException("Unable to calculate checksums", e); + + } finally { + IOUtils.closeQuietly(stream); + } + return result; + } + + static String getChecksum(String line) { + String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, ""); + return DigestUtils.md5Hex(reducedLine); + } + + /** + * @return checksum or null if checksum not exists for line + */ + private String getChecksumForLine(List<String> checksums, Integer line) { + if (line == null || line < 1 || line > checksums.size()) { + return null; + } + return checksums.get(line - 1); + } + + /** + * Search for past violation. + */ + RuleFailureModel selectPastViolation(Violation violation, Multimap<Rule, RuleFailureModel> pastViolationsByRule) { + Collection<RuleFailureModel> pastViolations = pastViolationsByRule.get(violation.getRule()); + if (pastViolations==null || pastViolations.isEmpty()) { + // skip violation, if there is no past violations with same rule + return null; + } + String dbFormattedMessage = RuleFailureModel.abbreviateMessage(violation.getMessage()); + RuleFailureModel found = selectPastViolationUsingLine(violation, dbFormattedMessage, pastViolations); + if (found == null) { + found = selectPastViolationUsingChecksum(violation, dbFormattedMessage, pastViolations); + } + return found; + } + + /** + * Search for past violation with same message and line. + */ + private RuleFailureModel selectPastViolationUsingLine(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) { + for (RuleFailureModel pastViolation : pastViolations) { + if (ObjectUtils.equals(violation.getLineId(), pastViolation.getLine()) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) { + return pastViolation; + } + } + return null; + } + + /** + * Search for past violation with same message and checksum. + */ + private RuleFailureModel selectPastViolationUsingChecksum(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) { + String checksum = getChecksumForLine(checksums, violation.getLineId()); + // skip violation, which not attached to line + if (checksum == null) { + return null; + } + for (RuleFailureModel pastViolation : pastViolations) { + String pastChecksum = pastViolation.getChecksum(); + if (StringUtils.equals(checksum, pastChecksum) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) { + return pastViolation; + } + } + return null; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ReviewsDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ReviewsDecoratorTest.java index 1fd4da1748a..256cca68c04 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ReviewsDecoratorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ReviewsDecoratorTest.java @@ -1,58 +1,58 @@ -/*
- * 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.plugins.core.sensors;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.batch.components.PastSnapshot;
-import org.sonar.batch.components.TimeMachineConfiguration;
-import org.sonar.batch.index.ResourcePersister;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-
-import java.text.ParseException;
-import java.util.Arrays;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ReviewsDecoratorTest extends AbstractDbUnitTestCase {
-
- @Test
- @Ignore("DBUnit needs Hibernate mapping...")
- public void shouldSaveConfigurationInSnapshotsTable() throws ParseException {
- setupData("fixture");
-
- File resource = new File("Foo");
- Snapshot snapshot = new Snapshot();
- snapshot.setId(666);
- snapshot.setResourceId(111);
- ResourcePersister persister = mock(ResourcePersister.class);
- when(persister.getSnapshot(resource)).thenReturn(snapshot);
-
- ReviewsDecorator reviewsDecorator = new ReviewsDecorator(persister, getSession());
- reviewsDecorator.decorate(resource, null);
-
- //checkTables("shouldSaveConfigurationInSnapshotsTable", "snapshots");
- }
-}
+/* + * 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.plugins.core.sensors; + +import org.junit.Ignore; +import org.junit.Test; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Resource; +import org.sonar.api.utils.DateUtils; +import org.sonar.batch.components.PastSnapshot; +import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.index.ResourcePersister; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import java.text.ParseException; +import java.util.Arrays; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ReviewsDecoratorTest extends AbstractDbUnitTestCase { + + @Test + @Ignore("DBUnit needs Hibernate mapping...") + public void shouldSaveConfigurationInSnapshotsTable() throws ParseException { + setupData("fixture"); + + File resource = new File("Foo"); + Snapshot snapshot = new Snapshot(); + snapshot.setId(666); + snapshot.setResourceId(111); + ResourcePersister persister = mock(ResourcePersister.class); + when(persister.getSnapshot(resource)).thenReturn(snapshot); + + ReviewsDecorator reviewsDecorator = new ReviewsDecorator(persister, getSession()); + reviewsDecorator.decorate(resource, null); + + //checkTables("shouldSaveConfigurationInSnapshotsTable", "snapshots"); + } +} diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ReviewsDecoratorTest/fixture.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ReviewsDecoratorTest/fixture.xml index 24cf1cfb55d..ea16316886c 100644 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ReviewsDecoratorTest/fixture.xml +++ b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ReviewsDecoratorTest/fixture.xml @@ -1,53 +1,53 @@ -<dataset>
-
- <snapshots
- id="11"
- project_id="555"/>
- <snapshots
- id="111"
- project_id="555"/>
- <snapshots
- id="22"
- project_id="666"/>
- <snapshots
- id="222"
- project_id="666"/>
-
- <rule_failures
- id="1"
- permament_id="1"
- snapshot_id="11"/>
- <rule_failures
- id="2"
- permament_id="2"
- snapshot_id="22"/>
- <rule_failures
- id="3"
- permament_id="3"
- snapshot_id="22"/>
- <rule_failures
- id="4"
- permament_id="1"
- snapshot_id="111"/>
- <rule_failures
- id="5"
- permament_id="3"
- snapshot_id="222"/>
-
- <reviews
- id="1"
- status="open"
- rule_failure_permanent_id="1"
- resource_id="555"/>
- <reviews
- id="2"
- status="open"
- rule_failure_permanent_id="2"
- resource_id="666"/>
- <reviews
- id="3"
- status="open"
- rule_failure_permanent_id="3"
- resource_id="666"/>
-
+<dataset> + + <snapshots + id="11" + project_id="555"/> + <snapshots + id="111" + project_id="555"/> + <snapshots + id="22" + project_id="666"/> + <snapshots + id="222" + project_id="666"/> + + <rule_failures + id="1" + permament_id="1" + snapshot_id="11"/> + <rule_failures + id="2" + permament_id="2" + snapshot_id="22"/> + <rule_failures + id="3" + permament_id="3" + snapshot_id="22"/> + <rule_failures + id="4" + permament_id="1" + snapshot_id="111"/> + <rule_failures + id="5" + permament_id="3" + snapshot_id="222"/> + + <reviews + id="1" + status="open" + rule_failure_permanent_id="1" + resource_id="555"/> + <reviews + id="2" + status="open" + rule_failure_permanent_id="2" + resource_id="666"/> + <reviews + id="3" + status="open" + rule_failure_permanent_id="3" + resource_id="666"/> + </dataset>
\ No newline at end of file diff --git a/quick-build.bat b/quick-build.bat index a72fc8a4a6a..d83b5db5031 100644 --- a/quick-build.bat +++ b/quick-build.bat @@ -1,2 +1,2 @@ set MAVEN_OPTS=-Xmx768m -XX:MaxPermSize=256m -mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
\ No newline at end of file +mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev diff --git a/quick-build.sh b/quick-build.sh index 75b97b0a504..f0755770766 100755 --- a/quick-build.sh +++ b/quick-build.sh @@ -9,4 +9,4 @@ echo '' echo '-------------------------------------------------' # it is recommended to use maven 3 for faster builds -mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
\ No newline at end of file +mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev 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 4ca401c310a..3e5caae2957 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java @@ -1,175 +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;
-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);
- }
-}
+/* + * 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 b8f42c96040..5b4dd14c5fd 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,549 +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.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;
- }
-}
+/* + * 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/main/java/org/sonar/batch/index/ViolationPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java index cc156125a5d..2334c0f8714 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java @@ -1,88 +1,88 @@ -/*
- * 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 org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.Project;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.Violation;
-
-public final class ViolationPersister {
-
- private DatabaseSession session;
- private ResourcePersister resourcePersister;
- private RuleFinder ruleFinder;
-
- public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) {
- this.session = session;
- this.resourcePersister = resourcePersister;
- this.ruleFinder = ruleFinder;
- }
-
- void saveViolation(Project project, Violation violation) {
- saveViolation(project, violation, null, null);
- }
-
- public void saveViolation(Project project, Violation violation, RuleFailureModel pastViolation, String checksum) {
- Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource());
-
- RuleFailureModel model = createModel(violation);
- if (pastViolation!=null) {
- model.setCreatedAt(pastViolation.getCreatedAt());
- model.setPermanentId(pastViolation.getPermanentId());
- model.setSwitchedOff(pastViolation.isSwitchedOff());
- } else {
- // avoid plugins setting date
- model.setCreatedAt(snapshot.getCreatedAt());
- }
- model.setSnapshotId(snapshot.getId());
- model.setChecksum(checksum);
- session.save(model);
-
- if (model.getPermanentId()==null) {
- model.setPermanentId(model.getId());
- session.save(model);
- }
-
- // the following fields can have been changed
- violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim)
- violation.setCreatedAt(model.getCreatedAt());
- violation.setSwitchedOff(model.isSwitchedOff());
- }
-
- public void commit() {
- session.commit();
- }
-
- private RuleFailureModel createModel(Violation violation) {
- RuleFailureModel model = new RuleFailureModel();
- Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey());
- model.setRuleId(rule.getId());
- model.setPriority(violation.getSeverity());
- model.setLine(violation.getLineId());
- model.setMessage(violation.getMessage());
- model.setCost(violation.getCost());
- return model;
- }
-
-}
+/* + * 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 org.sonar.api.database.DatabaseSession; +import org.sonar.api.database.model.RuleFailureModel; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.Project; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.rules.Violation; + +public final class ViolationPersister { + + private DatabaseSession session; + private ResourcePersister resourcePersister; + private RuleFinder ruleFinder; + + public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) { + this.session = session; + this.resourcePersister = resourcePersister; + this.ruleFinder = ruleFinder; + } + + void saveViolation(Project project, Violation violation) { + saveViolation(project, violation, null, null); + } + + public void saveViolation(Project project, Violation violation, RuleFailureModel pastViolation, String checksum) { + Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource()); + + RuleFailureModel model = createModel(violation); + if (pastViolation!=null) { + model.setCreatedAt(pastViolation.getCreatedAt()); + model.setPermanentId(pastViolation.getPermanentId()); + model.setSwitchedOff(pastViolation.isSwitchedOff()); + } else { + // avoid plugins setting date + model.setCreatedAt(snapshot.getCreatedAt()); + } + model.setSnapshotId(snapshot.getId()); + model.setChecksum(checksum); + session.save(model); + + if (model.getPermanentId()==null) { + model.setPermanentId(model.getId()); + session.save(model); + } + + // the following fields can have been changed + violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim) + violation.setCreatedAt(model.getCreatedAt()); + violation.setSwitchedOff(model.isSwitchedOff()); + } + + public void commit() { + session.commit(); + } + + private RuleFailureModel createModel(Violation violation) { + RuleFailureModel model = new RuleFailureModel(); + Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey()); + model.setRuleId(rule.getId()); + model.setPriority(violation.getSeverity()); + model.setLine(violation.getLineId()); + model.setMessage(violation.getMessage()); + model.setCost(violation.getCost()); + return model; + } + +} 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 6457cf2cc43..48946226df4 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,238 +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.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());
- }
-
-}
+/* + * 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()); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java index d1d3b775f5c..bb5bc1a34e9 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java @@ -1,96 +1,96 @@ -/*
- * 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 org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.JavaFile;
-import org.sonar.api.resources.Project;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.components.DefaultRuleFinder;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ViolationPersisterTest extends AbstractDbUnitTestCase {
-
- private ViolationPersister violationPersister;
- private Rule rule1 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck", "Check Header");
- private Rule rule2 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck", "Equals Avoid Null");
- private JavaFile javaFile = new JavaFile("org.foo.Bar");
- Project project = new Project("project");
-
- @Before
- public void before() {
- setupData("shared");
- Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000);
- ResourcePersister resourcePersister = mock(ResourcePersister.class);
- when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot);
- when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot);
- violationPersister = new ViolationPersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory()));
- }
-
- @Test
- public void shouldSaveViolations() {
- Violation violation1a = Violation.create(rule1, javaFile)
- .setSeverity(RulePriority.CRITICAL).setLineId(20).setCost(55.6)
- .setMessage("the message");
- Violation violation1b = Violation.create(rule1, javaFile)
- .setSeverity(RulePriority.CRITICAL).setLineId(50).setCost(80.0);
- Violation violation2 = Violation.create(rule2, javaFile)
- .setSeverity(RulePriority.MINOR);
-
- violationPersister.saveViolation(project, violation1a);
- violationPersister.saveViolation(project, violation1b);
- violationPersister.saveViolation(project, violation2);
-
- checkTables("shouldInsertViolations", "rule_failures");
- }
-
- @Test
- public void shouldCopyPermanentIdFromPastViolation() {
- RuleFailureModel pastViolation = getSession().getSingleResult(RuleFailureModel.class, "id", 1);
-
- Violation violation = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");
- violationPersister.saveViolation(project, violation, pastViolation, "line_checksum");
-
- checkTables("shouldCopyPermanentIdFromPastViolation", "rule_failures");
- }
-
- @Test
- public void shouldCopySwitchedOffFromPastViolation() {
- RuleFailureModel pastViolation1 = getSession().getSingleResult(RuleFailureModel.class, "id", 1);
- Violation violation1 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");
- violationPersister.saveViolation(project, violation1, pastViolation1, "line_checksum");
-
- RuleFailureModel pastViolation2 = getSession().getSingleResult(RuleFailureModel.class, "id", 2);
- Violation violation2 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");
- violationPersister.saveViolation(project, violation2, pastViolation2, "line_checksum");
-
- checkTables("shouldCopySwitchedOffFromPastViolation", "rule_failures");
- }
-}
+/* + * 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 org.junit.Before; +import org.junit.Test; +import org.sonar.api.database.model.RuleFailureModel; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.JavaFile; +import org.sonar.api.resources.Project; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.rules.Violation; +import org.sonar.core.components.DefaultRuleFinder; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ViolationPersisterTest extends AbstractDbUnitTestCase { + + private ViolationPersister violationPersister; + private Rule rule1 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck", "Check Header"); + private Rule rule2 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck", "Equals Avoid Null"); + private JavaFile javaFile = new JavaFile("org.foo.Bar"); + Project project = new Project("project"); + + @Before + public void before() { + setupData("shared"); + Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000); + ResourcePersister resourcePersister = mock(ResourcePersister.class); + when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot); + when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot); + violationPersister = new ViolationPersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory())); + } + + @Test + public void shouldSaveViolations() { + Violation violation1a = Violation.create(rule1, javaFile) + .setSeverity(RulePriority.CRITICAL).setLineId(20).setCost(55.6) + .setMessage("the message"); + Violation violation1b = Violation.create(rule1, javaFile) + .setSeverity(RulePriority.CRITICAL).setLineId(50).setCost(80.0); + Violation violation2 = Violation.create(rule2, javaFile) + .setSeverity(RulePriority.MINOR); + + violationPersister.saveViolation(project, violation1a); + violationPersister.saveViolation(project, violation1b); + violationPersister.saveViolation(project, violation2); + + checkTables("shouldInsertViolations", "rule_failures"); + } + + @Test + public void shouldCopyPermanentIdFromPastViolation() { + RuleFailureModel pastViolation = getSession().getSingleResult(RuleFailureModel.class, "id", 1); + + Violation violation = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message"); + violationPersister.saveViolation(project, violation, pastViolation, "line_checksum"); + + checkTables("shouldCopyPermanentIdFromPastViolation", "rule_failures"); + } + + @Test + public void shouldCopySwitchedOffFromPastViolation() { + RuleFailureModel pastViolation1 = getSession().getSingleResult(RuleFailureModel.class, "id", 1); + Violation violation1 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message"); + violationPersister.saveViolation(project, violation1, pastViolation1, "line_checksum"); + + RuleFailureModel pastViolation2 = getSession().getSingleResult(RuleFailureModel.class, "id", 2); + Violation violation2 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message"); + violationPersister.saveViolation(project, violation2, pastViolation2, "line_checksum"); + + checkTables("shouldCopySwitchedOffFromPastViolation", "rule_failures"); + } +} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml index cc50133e0bd..90a3f202297 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml @@ -1,24 +1,24 @@ -<dataset>
-
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
-</dataset>
+<dataset> + + <rules_categories id="1" name="Efficiency" description="[null]"/> + <rules_categories id="6" name="Usability" description="[null]"/> + + <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck" + plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck" + plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]" + name="Bar" long_name="org.foo.Bar" description="[null]" + enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]" + scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path="" + status="U" islast="false" depth="3" /> + + <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> +</dataset> diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml index 842a7e10765..881a88dc3bb 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml @@ -1,26 +1,26 @@ -<dataset>
-
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
-
- <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
-</dataset>
+<dataset> + + <rules_categories id="1" name="Efficiency" description="[null]"/> + <rules_categories id="6" name="Usability" description="[null]"/> + + <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck" + plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck" + plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]" + name="Bar" long_name="org.foo.Bar" description="[null]" + enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]" + scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path="" + status="U" islast="false" depth="3" /> + + <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + + <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/> +</dataset> diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml index f72c573676d..bc366b16a45 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml @@ -1,27 +1,27 @@ -<dataset>
-
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
-
- <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
- <rule_failures switched_off="true" permanent_id="2" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
-</dataset>
+<dataset> + + <rules_categories id="1" name="Efficiency" description="[null]"/> + <rules_categories id="6" name="Usability" description="[null]"/> + + <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck" + plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck" + plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]" + name="Bar" long_name="org.foo.Bar" description="[null]" + enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]" + scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path="" + status="U" islast="false" depth="3" /> + + <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + + <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/> + <rule_failures switched_off="true" permanent_id="2" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/> +</dataset> diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml index 765a84bae8c..3b3215ffe11 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml @@ -1,26 +1,26 @@ -<dataset>
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="false" permanent_id="3" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="false" permanent_id="4" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="false" permanent_id="5" ID="5" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+<dataset> + <rules_categories id="1" name="Efficiency" description="[null]"/> + <rules_categories id="6" name="Usability" description="[null]"/> + + <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck" + plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck" + plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true" + cardinality="SINGLE" parent_id="[null]"/> + + <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]" + name="Bar" long_name="org.foo.Bar" description="[null]" + enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]" + scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path="" + status="U" islast="false" depth="3" /> + + <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + <rule_failures switched_off="false" permanent_id="3" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + <rule_failures switched_off="false" permanent_id="4" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> + <rule_failures switched_off="false" permanent_id="5" ID="5" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/> </dataset>
\ No newline at end of file diff --git a/sonar-core/src/main/java/org/sonar/jpa/session/JpaDatabaseSession.java b/sonar-core/src/main/java/org/sonar/jpa/session/JpaDatabaseSession.java index 6533b5ae5cf..ab3ee2417d0 100644 --- a/sonar-core/src/main/java/org/sonar/jpa/session/JpaDatabaseSession.java +++ b/sonar-core/src/main/java/org/sonar/jpa/session/JpaDatabaseSession.java @@ -1,263 +1,263 @@ -/*
- * 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.jpa.session;
-
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.database.DatabaseSession;
-
-import java.util.*;
-
-import javax.persistence.EntityManager;
-import javax.persistence.NonUniqueResultException;
-import javax.persistence.PersistenceException;
-import javax.persistence.Query;
-
-public class JpaDatabaseSession extends DatabaseSession {
-
- private final DatabaseConnector connector;
- private EntityManager entityManager = null;
- private int index = 0;
- private boolean inTransaction = false;
-
- public JpaDatabaseSession(DatabaseConnector connector) {
- this.connector = connector;
- }
-
- /**
- * Note that usage of this method is discouraged, because it allows to construct and execute queries without additional exception handling,
- * which done in methods of this class.
- */
- public EntityManager getEntityManager() {
- return entityManager;
- }
-
- public void start() {
- entityManager = connector.createEntityManager();
- index = 0;
- }
-
- public void stop() {
- commit();
- if (entityManager != null && entityManager.isOpen()) {
- entityManager.close();
- entityManager = null;
- }
- }
-
- public void commit() {
- if (entityManager != null && inTransaction) {
- if (entityManager.isOpen()) {
- if (entityManager.getTransaction().getRollbackOnly()) {
- entityManager.getTransaction().rollback();
- } else {
- entityManager.getTransaction().commit();
- }
- entityManager.clear();
- index = 0;
- }
- inTransaction = false;
- }
- }
-
- public void rollback() {
- if (entityManager != null && inTransaction) {
- entityManager.getTransaction().rollback();
- inTransaction = false;
- }
- }
-
- public <T> T save(T model) {
- startTransaction();
- internalSave(model, true);
- return model;
- }
-
- public Object saveWithoutFlush(Object model) {
- startTransaction();
- internalSave(model, false);
- return model;
- }
-
- public boolean contains(Object model) {
- startTransaction();
- return entityManager.contains(model);
- }
-
- public void save(Object... models) {
- startTransaction();
- for (Object model : models) {
- save(model);
- }
- }
-
- private void internalSave(Object model, boolean flushIfNeeded) {
- try {
- entityManager.persist(model);
- } catch (PersistenceException e) {
- /*
- * See http://jira.codehaus.org/browse/SONAR-2234
- * In some cases Hibernate can throw exceptions without meaningful information about context, so we improve them here.
- */
- throw new PersistenceException("Unable to persist : " + model, e);
- }
- if (flushIfNeeded && (++index % BATCH_SIZE == 0)) {
- commit();
- }
- }
-
- public Object merge(Object model) {
- startTransaction();
- return entityManager.merge(model);
- }
-
- public void remove(Object model) {
- startTransaction();
- entityManager.remove(model);
- if (++index % BATCH_SIZE == 0) {
- commit();
- }
- }
-
- public void removeWithoutFlush(Object model) {
- startTransaction();
- entityManager.remove(model);
- }
-
- public <T> T reattach(Class<T> entityClass, Object primaryKey) {
- startTransaction();
- return entityManager.getReference(entityClass, primaryKey);
- }
-
- private void startTransaction() {
- if (!inTransaction) {
- entityManager.getTransaction().begin();
- inTransaction = true;
- }
- }
-
- /**
- * Note that not recommended to directly execute {@link Query#getSingleResult()}, because it will bypass exception handling,
- * which done in {@link #getSingleResult(Query, Object)}.
- */
- public Query createQuery(String hql) {
- startTransaction();
- return entityManager.createQuery(hql);
- }
-
- @Override
- public Query createNativeQuery(String sql) {
- startTransaction();
- return entityManager.createNativeQuery(sql);
- }
-
- /**
- * @return the result or <code>defaultValue</code>, if not found
- * @throws NonUniqueResultException if more than one result
- */
- public <T> T getSingleResult(Query query, T defaultValue) {
- /*
- * See http://jira.codehaus.org/browse/SONAR-2225
- * By default Hibernate throws NonUniqueResultException without meaningful information about context,
- * so we improve it here by adding all results in error message.
- * Note that in some rare situations we can receive too many results, which may lead to OOME,
- * but actually it will mean that database is corrupted as we don't expect more than one result
- * and in fact org.hibernate.ejb.QueryImpl#getSingleResult() anyway does loading of several results under the hood.
- */
- List<T> result = query.getResultList();
-
- if (result.size() == 1) {
- return result.get(0);
-
- } else if (result.isEmpty()) {
- return defaultValue;
-
- } else {
- Set<T> uniqueResult = new HashSet<T>(result);
- if (uniqueResult.size() > 1) {
- throw new NonUniqueResultException("Expected single result, but got : " + result.toString());
- } else {
- return uniqueResult.iterator().next();
- }
- }
- }
-
- public <T> T getEntity(Class<T> entityClass, Object id) {
- startTransaction();
- return getEntityManager().find(entityClass, id);
- }
-
- /**
- * @return the result or <code>null</code>, if not found
- * @throws NonUniqueResultException if more than one result
- */
- public <T> T getSingleResult(Class<T> entityClass, Object... criterias) {
- try {
- return getSingleResult(getQueryForCriterias(entityClass, true, criterias), (T) null);
-
- } catch (NonUniqueResultException ex) {
- NonUniqueResultException e = new NonUniqueResultException("Expected single result for entitiy " + entityClass.getSimpleName()
- + " with criterias : " + StringUtils.join(criterias, ","));
- e.initCause(ex);
- throw e;
- }
- }
-
- public <T> List<T> getResults(Class<T> entityClass, Object... criterias) {
- return getQueryForCriterias(entityClass, true, criterias).getResultList();
- }
-
- public <T> List<T> getResults(Class<T> entityClass) {
- return getQueryForCriterias(entityClass, false, null).getResultList();
- }
-
- private Query getQueryForCriterias(Class<?> entityClass, boolean raiseError, Object... criterias) {
- if (criterias == null && raiseError) {
- throw new IllegalStateException("criterias parameter must be provided");
- }
- startTransaction();
- StringBuilder hql = new StringBuilder("SELECT o FROM ").append(entityClass.getSimpleName()).append(" o");
- if (criterias != null) {
- hql.append(" WHERE ");
- Map<String, Object> mappedCriterias = new HashMap<String, Object>();
- for (int i = 0; i < criterias.length; i += 2) {
- mappedCriterias.put((String) criterias[i], criterias[i + 1]);
- }
- buildCriteriasHQL(hql, mappedCriterias);
- Query query = getEntityManager().createQuery(hql.toString());
-
- for (Map.Entry<String, Object> entry : mappedCriterias.entrySet()) {
- query.setParameter(entry.getKey(), entry.getValue());
- }
- return query;
- }
- return getEntityManager().createQuery(hql.toString());
- }
-
- private void buildCriteriasHQL(StringBuilder hql, Map<String, Object> mappedCriterias) {
- for (Iterator<String> i = mappedCriterias.keySet().iterator(); i.hasNext();) {
- String criteria = i.next();
- hql.append("o.").append(criteria).append("=:").append(criteria);
- if (i.hasNext()) {
- hql.append(" AND ");
- }
- }
- }
-
-}
+/* + * 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.jpa.session; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.database.DatabaseSession; + +import java.util.*; + +import javax.persistence.EntityManager; +import javax.persistence.NonUniqueResultException; +import javax.persistence.PersistenceException; +import javax.persistence.Query; + +public class JpaDatabaseSession extends DatabaseSession { + + private final DatabaseConnector connector; + private EntityManager entityManager = null; + private int index = 0; + private boolean inTransaction = false; + + public JpaDatabaseSession(DatabaseConnector connector) { + this.connector = connector; + } + + /** + * Note that usage of this method is discouraged, because it allows to construct and execute queries without additional exception handling, + * which done in methods of this class. + */ + public EntityManager getEntityManager() { + return entityManager; + } + + public void start() { + entityManager = connector.createEntityManager(); + index = 0; + } + + public void stop() { + commit(); + if (entityManager != null && entityManager.isOpen()) { + entityManager.close(); + entityManager = null; + } + } + + public void commit() { + if (entityManager != null && inTransaction) { + if (entityManager.isOpen()) { + if (entityManager.getTransaction().getRollbackOnly()) { + entityManager.getTransaction().rollback(); + } else { + entityManager.getTransaction().commit(); + } + entityManager.clear(); + index = 0; + } + inTransaction = false; + } + } + + public void rollback() { + if (entityManager != null && inTransaction) { + entityManager.getTransaction().rollback(); + inTransaction = false; + } + } + + public <T> T save(T model) { + startTransaction(); + internalSave(model, true); + return model; + } + + public Object saveWithoutFlush(Object model) { + startTransaction(); + internalSave(model, false); + return model; + } + + public boolean contains(Object model) { + startTransaction(); + return entityManager.contains(model); + } + + public void save(Object... models) { + startTransaction(); + for (Object model : models) { + save(model); + } + } + + private void internalSave(Object model, boolean flushIfNeeded) { + try { + entityManager.persist(model); + } catch (PersistenceException e) { + /* + * See http://jira.codehaus.org/browse/SONAR-2234 + * In some cases Hibernate can throw exceptions without meaningful information about context, so we improve them here. + */ + throw new PersistenceException("Unable to persist : " + model, e); + } + if (flushIfNeeded && (++index % BATCH_SIZE == 0)) { + commit(); + } + } + + public Object merge(Object model) { + startTransaction(); + return entityManager.merge(model); + } + + public void remove(Object model) { + startTransaction(); + entityManager.remove(model); + if (++index % BATCH_SIZE == 0) { + commit(); + } + } + + public void removeWithoutFlush(Object model) { + startTransaction(); + entityManager.remove(model); + } + + public <T> T reattach(Class<T> entityClass, Object primaryKey) { + startTransaction(); + return entityManager.getReference(entityClass, primaryKey); + } + + private void startTransaction() { + if (!inTransaction) { + entityManager.getTransaction().begin(); + inTransaction = true; + } + } + + /** + * Note that not recommended to directly execute {@link Query#getSingleResult()}, because it will bypass exception handling, + * which done in {@link #getSingleResult(Query, Object)}. + */ + public Query createQuery(String hql) { + startTransaction(); + return entityManager.createQuery(hql); + } + + @Override + public Query createNativeQuery(String sql) { + startTransaction(); + return entityManager.createNativeQuery(sql); + } + + /** + * @return the result or <code>defaultValue</code>, if not found + * @throws NonUniqueResultException if more than one result + */ + public <T> T getSingleResult(Query query, T defaultValue) { + /* + * See http://jira.codehaus.org/browse/SONAR-2225 + * By default Hibernate throws NonUniqueResultException without meaningful information about context, + * so we improve it here by adding all results in error message. + * Note that in some rare situations we can receive too many results, which may lead to OOME, + * but actually it will mean that database is corrupted as we don't expect more than one result + * and in fact org.hibernate.ejb.QueryImpl#getSingleResult() anyway does loading of several results under the hood. + */ + List<T> result = query.getResultList(); + + if (result.size() == 1) { + return result.get(0); + + } else if (result.isEmpty()) { + return defaultValue; + + } else { + Set<T> uniqueResult = new HashSet<T>(result); + if (uniqueResult.size() > 1) { + throw new NonUniqueResultException("Expected single result, but got : " + result.toString()); + } else { + return uniqueResult.iterator().next(); + } + } + } + + public <T> T getEntity(Class<T> entityClass, Object id) { + startTransaction(); + return getEntityManager().find(entityClass, id); + } + + /** + * @return the result or <code>null</code>, if not found + * @throws NonUniqueResultException if more than one result + */ + public <T> T getSingleResult(Class<T> entityClass, Object... criterias) { + try { + return getSingleResult(getQueryForCriterias(entityClass, true, criterias), (T) null); + + } catch (NonUniqueResultException ex) { + NonUniqueResultException e = new NonUniqueResultException("Expected single result for entitiy " + entityClass.getSimpleName() + + " with criterias : " + StringUtils.join(criterias, ",")); + e.initCause(ex); + throw e; + } + } + + public <T> List<T> getResults(Class<T> entityClass, Object... criterias) { + return getQueryForCriterias(entityClass, true, criterias).getResultList(); + } + + public <T> List<T> getResults(Class<T> entityClass) { + return getQueryForCriterias(entityClass, false, null).getResultList(); + } + + private Query getQueryForCriterias(Class<?> entityClass, boolean raiseError, Object... criterias) { + if (criterias == null && raiseError) { + throw new IllegalStateException("criterias parameter must be provided"); + } + startTransaction(); + StringBuilder hql = new StringBuilder("SELECT o FROM ").append(entityClass.getSimpleName()).append(" o"); + if (criterias != null) { + hql.append(" WHERE "); + Map<String, Object> mappedCriterias = new HashMap<String, Object>(); + for (int i = 0; i < criterias.length; i += 2) { + mappedCriterias.put((String) criterias[i], criterias[i + 1]); + } + buildCriteriasHQL(hql, mappedCriterias); + Query query = getEntityManager().createQuery(hql.toString()); + + for (Map.Entry<String, Object> entry : mappedCriterias.entrySet()) { + query.setParameter(entry.getKey(), entry.getValue()); + } + return query; + } + return getEntityManager().createQuery(hql.toString()); + } + + private void buildCriteriasHQL(StringBuilder hql, Map<String, Object> mappedCriterias) { + for (Iterator<String> i = mappedCriterias.keySet().iterator(); i.hasNext();) { + String criteria = i.next(); + hql.append("o.").append(criteria).append("=:").append(criteria); + if (i.hasNext()) { + hql.append(" AND "); + } + } + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java index af59b924da7..57103c691d0 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java @@ -1,159 +1,159 @@ -/*
- * 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.api.batch;
-
-import org.sonar.api.design.Dependency;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-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;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @since 1.10
- */
-public interface DecoratorContext {
-
- /**
- * @return the project in which the decorator is
- */
- Project getProject();
-
- /**
- * @return the resource that is currently decorated
- */
- Resource getResource();
-
- /**
- * Child contexts are read only
- */
- List<DecoratorContext> getChildren();
-
- // MEASURES
-
- /**
- * Find a measure for the resource
- */
- Measure getMeasure(Metric metric);
-
- /**
- * Never return null.
- */
- <M> M getMeasures(MeasuresFilter<M> filter);
-
- /**
- * Never return null.
- */
- Collection<Measure> getChildrenMeasures(MeasuresFilter filter);
-
- /**
- * @return the resource children measures for the given metric
- */
- Collection<Measure> getChildrenMeasures(Metric metric);
-
- /**
- * Add a measure on the current resource. It can not be executed from children contexts.
- *
- * @return the same context
- */
- DecoratorContext saveMeasure(Measure measure);
-
- /**
- * Add a measure on the current resource. It can not be executed from children contexts.
- *
- * @return the current object
- */
- DecoratorContext saveMeasure(Metric metric, Double value);
-
- // DEPENDENCIES
-
- Dependency saveDependency(Dependency dependency);
-
- Set<Dependency> getDependencies();
-
- Collection<Dependency> getIncomingDependencies();
-
- Collection<Dependency> getOutgoingDependencies();
-
- // RULES
-
- /**
- * Returns the violations that match the {@link ViolationQuery} parameters.
- *
- * @since 2.8
- * @param violationQuery
- * the request parameters specified as a {@link ViolationQuery}
- * @return the list of violations that match those parameters
- */
- public abstract List<Violation> getViolations(ViolationQuery violationQuery);
-
- /**
- * Returns all the active (= non switched-off) violations found on the current resource.
- *
- * @return the list of violations
- */
- List<Violation> getViolations();
-
- /**
- * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION.
- *
- * @since 2.5
- * @param force allows to force creation of violation even if it was suppressed by {@link org.sonar.api.rules.ViolationFilter}
- */
- DecoratorContext saveViolation(Violation violation, boolean force);
-
- /**
- * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION.
- */
- DecoratorContext saveViolation(Violation violation);
-
- // EVENTS
-
- /**
- * @return the list of events associated to the current resource
- */
- List<Event> getEvents();
-
- /**
- * Creates an event for a given date
- *
- * @param name the event name
- * @param description the event description
- * @param category the event category
- * @param date the event date
- * @return the created event
- */
- Event createEvent(String name, String description, String category, Date date);
-
- /**
- * Deletes an event
- *
- * @param event the event to delete
- */
- void deleteEvent(Event event);
-
-}
+/* + * 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.api.batch; + +import org.sonar.api.design.Dependency; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilter; +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; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + * @since 1.10 + */ +public interface DecoratorContext { + + /** + * @return the project in which the decorator is + */ + Project getProject(); + + /** + * @return the resource that is currently decorated + */ + Resource getResource(); + + /** + * Child contexts are read only + */ + List<DecoratorContext> getChildren(); + + // MEASURES + + /** + * Find a measure for the resource + */ + Measure getMeasure(Metric metric); + + /** + * Never return null. + */ + <M> M getMeasures(MeasuresFilter<M> filter); + + /** + * Never return null. + */ + Collection<Measure> getChildrenMeasures(MeasuresFilter filter); + + /** + * @return the resource children measures for the given metric + */ + Collection<Measure> getChildrenMeasures(Metric metric); + + /** + * Add a measure on the current resource. It can not be executed from children contexts. + * + * @return the same context + */ + DecoratorContext saveMeasure(Measure measure); + + /** + * Add a measure on the current resource. It can not be executed from children contexts. + * + * @return the current object + */ + DecoratorContext saveMeasure(Metric metric, Double value); + + // DEPENDENCIES + + Dependency saveDependency(Dependency dependency); + + Set<Dependency> getDependencies(); + + Collection<Dependency> getIncomingDependencies(); + + Collection<Dependency> getOutgoingDependencies(); + + // RULES + + /** + * Returns the violations that match the {@link ViolationQuery} parameters. + * + * @since 2.8 + * @param violationQuery + * the request parameters specified as a {@link ViolationQuery} + * @return the list of violations that match those parameters + */ + public abstract List<Violation> getViolations(ViolationQuery violationQuery); + + /** + * Returns all the active (= non switched-off) violations found on the current resource. + * + * @return the list of violations + */ + List<Violation> getViolations(); + + /** + * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION. + * + * @since 2.5 + * @param force allows to force creation of violation even if it was suppressed by {@link org.sonar.api.rules.ViolationFilter} + */ + DecoratorContext saveViolation(Violation violation, boolean force); + + /** + * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION. + */ + DecoratorContext saveViolation(Violation violation); + + // EVENTS + + /** + * @return the list of events associated to the current resource + */ + List<Event> getEvents(); + + /** + * Creates an event for a given date + * + * @param name the event name + * @param description the event description + * @param category the event category + * @param date the event date + * @return the created event + */ + Event createEvent(String name, String description, String category, Date date); + + /** + * Deletes an event + * + * @param event the event to delete + */ + void deleteEvent(Event event); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java index f2a09f9a6ce..89133b1c6b8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java @@ -1,182 +1,182 @@ -/*
- * 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.api.batch;
-
-import org.sonar.api.design.Dependency;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.DuplicatedSourceException;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectLink;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rules.Violation;
-import org.sonar.api.violations.ViolationQuery;
-import org.sonar.graph.DirectedGraphAccessor;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Dependency> {
-
- /**
- * Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed.
- * If the method resource.getParent() does not return null, then this parent will be indexed too.
- *
- * @return false if the resource is excluded
- * @since 2.6
- */
- public abstract boolean index(Resource resource);
-
-
- /**
- * Indexes a resource. This method does nothing if the resource is already indexed.
- *
- * @param resource the resource to index. Not nullable
- * @param parentReference a reference to the indexed parent. If null, the resource is indexed as a direct child of project.
- * @return false if the parent is not indexed or if the resource is excluded
- * @since 2.6
- */
- public abstract boolean index(Resource resource, Resource parentReference);
-
- /**
- * Returns true if the referenced resource is excluded. An excluded resource is not indexed.
- * @since 2.6
- */
- public abstract boolean isExcluded(Resource reference);
-
- /**
- * @since 2.6
- */
- public abstract boolean isIndexed(Resource reference, boolean acceptExcluded);
-
- /**
- * Search for an indexed resource.
- *
- * @param reference the resource reference
- * @return the indexed resource, null if it's not indexed
- * @since 1.10. Generic types since 2.6.
- */
- public abstract <R extends Resource> R getResource(R reference);
-
- /**
- * @since 2.6
- */
- public abstract Resource getParent(Resource reference);
-
- /**
- * @since 2.6
- */
-
- public abstract Collection<Resource> getChildren(Resource reference);
-
- /**
- * Save the source code of a file. The file must be have been indexed before.
- * Note: the source stream is not closed.
- *
- * @return false if the resource is excluded or not indexed
- * @throws org.sonar.api.resources.DuplicatedSourceException
- * if the source has already been set on this resource
- */
- public abstract void setSource(Resource reference, String source) throws DuplicatedSourceException;
-
- public abstract Project getProject();
-
- public final Collection<Resource> getResources() {
- return getVertices();
- }
-
- /**
- * Indexes the resource.
- * @return the indexed resource, even if it's excluded
- * @deprecated since 2.6. Use methods index()
- */
- @Deprecated
- public abstract Resource addResource(Resource resource);
-
- public abstract Measure getMeasure(Resource resource, Metric metric);
-
- public abstract <M> M getMeasures(Resource resource, MeasuresFilter<M> filter);
-
- /**
- * Returns the violations that match the {@link ViolationQuery} parameters.
- *
- * @since 2.8
- * @param violationQuery
- * the request parameters specified as a {@link ViolationQuery}
- * @return the list of violations that match those parameters
- */
- public abstract List<Violation> getViolations(ViolationQuery violationQuery);
-
- /**
- * Returns all the active (= non switched-off) violations found on the given resource. Equivalent to
- * {@link #getViolations(ViolationQuery)} called with <code>ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true)</code>
- * as a parameter.
- *
- * @since 2.7
- * @param the
- * resource on which violations are searched
- * @return the list of violations
- */
- public final List<Violation> getViolations(Resource resource) {
- return getViolations(ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true));
- }
-
- /**
- * @since 2.5
- */
- public abstract void addViolation(Violation violation, boolean force);
-
- public final void addViolation(Violation violation) {
- addViolation(violation, false);
- }
-
- /**
- * Warning: the resource is automatically indexed for backward-compatibility, but it should be explictly
- * indexed before. Next versions will deactivate this automatic indexation.
- *
- * @throws SonarException if the metric is unknown.
- */
- public abstract Measure addMeasure(Resource resource, Measure measure);
-
- public abstract Dependency addDependency(Dependency dependency);
-
- public abstract Set<Dependency> getDependencies();
-
- public abstract void addLink(ProjectLink link);
-
- public abstract void deleteLink(String key);
-
- public abstract List<Event> getEvents(Resource resource);
-
- public abstract void deleteEvent(Event event);
-
- public abstract Event addEvent(Resource resource, String name, String description, String category, Date date);
-
- public final Collection<Dependency> getOutgoingDependencies(Resource from) {
- return getOutgoingEdges(from);
- }
-
- public final Collection<Dependency> getIncomingDependencies(Resource to) {
- return getIncomingEdges(to);
- }
-}
+/* + * 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.api.batch; + +import org.sonar.api.design.Dependency; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilter; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.DuplicatedSourceException; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.ProjectLink; +import org.sonar.api.resources.Resource; +import org.sonar.api.rules.Violation; +import org.sonar.api.violations.ViolationQuery; +import org.sonar.graph.DirectedGraphAccessor; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; + +public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Dependency> { + + /** + * Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed. + * If the method resource.getParent() does not return null, then this parent will be indexed too. + * + * @return false if the resource is excluded + * @since 2.6 + */ + public abstract boolean index(Resource resource); + + + /** + * Indexes a resource. This method does nothing if the resource is already indexed. + * + * @param resource the resource to index. Not nullable + * @param parentReference a reference to the indexed parent. If null, the resource is indexed as a direct child of project. + * @return false if the parent is not indexed or if the resource is excluded + * @since 2.6 + */ + public abstract boolean index(Resource resource, Resource parentReference); + + /** + * Returns true if the referenced resource is excluded. An excluded resource is not indexed. + * @since 2.6 + */ + public abstract boolean isExcluded(Resource reference); + + /** + * @since 2.6 + */ + public abstract boolean isIndexed(Resource reference, boolean acceptExcluded); + + /** + * Search for an indexed resource. + * + * @param reference the resource reference + * @return the indexed resource, null if it's not indexed + * @since 1.10. Generic types since 2.6. + */ + public abstract <R extends Resource> R getResource(R reference); + + /** + * @since 2.6 + */ + public abstract Resource getParent(Resource reference); + + /** + * @since 2.6 + */ + + public abstract Collection<Resource> getChildren(Resource reference); + + /** + * Save the source code of a file. The file must be have been indexed before. + * Note: the source stream is not closed. + * + * @return false if the resource is excluded or not indexed + * @throws org.sonar.api.resources.DuplicatedSourceException + * if the source has already been set on this resource + */ + public abstract void setSource(Resource reference, String source) throws DuplicatedSourceException; + + public abstract Project getProject(); + + public final Collection<Resource> getResources() { + return getVertices(); + } + + /** + * Indexes the resource. + * @return the indexed resource, even if it's excluded + * @deprecated since 2.6. Use methods index() + */ + @Deprecated + public abstract Resource addResource(Resource resource); + + public abstract Measure getMeasure(Resource resource, Metric metric); + + public abstract <M> M getMeasures(Resource resource, MeasuresFilter<M> filter); + + /** + * Returns the violations that match the {@link ViolationQuery} parameters. + * + * @since 2.8 + * @param violationQuery + * the request parameters specified as a {@link ViolationQuery} + * @return the list of violations that match those parameters + */ + public abstract List<Violation> getViolations(ViolationQuery violationQuery); + + /** + * Returns all the active (= non switched-off) violations found on the given resource. Equivalent to + * {@link #getViolations(ViolationQuery)} called with <code>ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true)</code> + * as a parameter. + * + * @since 2.7 + * @param the + * resource on which violations are searched + * @return the list of violations + */ + public final List<Violation> getViolations(Resource resource) { + return getViolations(ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true)); + } + + /** + * @since 2.5 + */ + public abstract void addViolation(Violation violation, boolean force); + + public final void addViolation(Violation violation) { + addViolation(violation, false); + } + + /** + * Warning: the resource is automatically indexed for backward-compatibility, but it should be explictly + * indexed before. Next versions will deactivate this automatic indexation. + * + * @throws SonarException if the metric is unknown. + */ + public abstract Measure addMeasure(Resource resource, Measure measure); + + public abstract Dependency addDependency(Dependency dependency); + + public abstract Set<Dependency> getDependencies(); + + public abstract void addLink(ProjectLink link); + + public abstract void deleteLink(String key); + + public abstract List<Event> getEvents(Resource resource); + + public abstract void deleteEvent(Event event); + + public abstract Event addEvent(Resource resource, String name, String description, String category, Date date); + + public final Collection<Dependency> getOutgoingDependencies(Resource from) { + return getOutgoingEdges(from); + } + + public final Collection<Dependency> getIncomingDependencies(Resource to) { + return getIncomingEdges(to); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseSession.java b/sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseSession.java index dc416bc5257..19bf31cd5c6 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseSession.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseSession.java @@ -1,80 +1,80 @@ -/*
- * 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.api.database;
-
-import org.sonar.api.BatchComponent;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
-import java.util.List;
-
-/**
- * This component should not accessible from plugin API
- *
- * @since 1.10
- */
-public abstract class DatabaseSession implements BatchComponent {
-
-
- // IMPORTANT : this value must be the same than the property
- // hibernate.jdbc.batch_size from /META-INF/persistence.xml (module sonar-database)
- public static final int BATCH_SIZE = 30;
-
-
- public abstract EntityManager getEntityManager();
-
- public abstract void start();
-
- public abstract void stop();
-
- public abstract void commit();
-
- public abstract void rollback();
-
- public abstract <T> T save(T entity);
-
- public abstract Object saveWithoutFlush(Object entity);
-
- public abstract boolean contains(Object entity);
-
- public abstract void save(Object... entities);
-
- public abstract Object merge(Object entity);
-
- public abstract void remove(Object entity);
-
- public abstract void removeWithoutFlush(Object entity);
-
- public abstract <T> T reattach(Class<T> entityClass, Object primaryKey);
-
- public abstract Query createQuery(String hql);
-
- public abstract Query createNativeQuery(String sql);
-
- public abstract <T> T getSingleResult(Query query, T defaultValue);
-
- public abstract <T> T getEntity(Class<T> entityClass, Object id);
-
- public abstract <T> T getSingleResult(Class<T> entityClass, Object... criterias);
-
- public abstract <T> List<T> getResults(Class<T> entityClass, Object... criterias);
-
- public abstract <T> List<T> getResults(Class<T> entityClass);
-}
+/* + * 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.api.database; + +import org.sonar.api.BatchComponent; + +import javax.persistence.EntityManager; +import javax.persistence.Query; +import java.util.List; + +/** + * This component should not accessible from plugin API + * + * @since 1.10 + */ +public abstract class DatabaseSession implements BatchComponent { + + + // IMPORTANT : this value must be the same than the property + // hibernate.jdbc.batch_size from /META-INF/persistence.xml (module sonar-database) + public static final int BATCH_SIZE = 30; + + + public abstract EntityManager getEntityManager(); + + public abstract void start(); + + public abstract void stop(); + + public abstract void commit(); + + public abstract void rollback(); + + public abstract <T> T save(T entity); + + public abstract Object saveWithoutFlush(Object entity); + + public abstract boolean contains(Object entity); + + public abstract void save(Object... entities); + + public abstract Object merge(Object entity); + + public abstract void remove(Object entity); + + public abstract void removeWithoutFlush(Object entity); + + public abstract <T> T reattach(Class<T> entityClass, Object primaryKey); + + public abstract Query createQuery(String hql); + + public abstract Query createNativeQuery(String sql); + + public abstract <T> T getSingleResult(Query query, T defaultValue); + + public abstract <T> T getEntity(Class<T> entityClass, Object id); + + public abstract <T> T getSingleResult(Class<T> entityClass, Object... criterias); + + public abstract <T> List<T> getResults(Class<T> entityClass, Object... criterias); + + public abstract <T> List<T> getResults(Class<T> entityClass); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java index fd2b06ec1c2..3e4aa063a8b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java @@ -1,253 +1,253 @@ -/*
- * 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.api.rules;
-
-import org.apache.commons.lang.builder.EqualsBuilder;
-import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.sonar.api.resources.Resource;
-
-import java.util.Date;
-
-/**
- * A class that represents a violation. A violation happens when a resource does not respect a defined rule.
- */
-public class Violation {
-
- private Resource resource;
- private Rule rule;
- private String message;
- private RulePriority severity;
- private Integer lineId;
- private Double cost;
- private Date createdAt;
- private boolean switchedOff;
-
- /**
- * Creates of a violation from a rule. Will need to define the resource later on
- *
- * @deprecated since 2.3. Use the factory method create()
- */
- @Deprecated
- public Violation(Rule rule) {
- this.rule = rule;
- }
-
- /**
- * Creates a fully qualified violation
- *
- * @param rule
- * the rule that has been violated
- * @param resource
- * the resource the violation should be attached to
- * @deprecated since 2.3. Use the factory method create()
- */
- @Deprecated
- public Violation(Rule rule, Resource resource) {
- this.resource = resource;
- this.rule = rule;
- }
-
- public Resource getResource() {
- return resource;
- }
-
- /**
- * Sets the resource the violation applies to
- *
- * @return the current object
- */
- public Violation setResource(Resource resource) {
- this.resource = resource;
- return this;
- }
-
- public Rule getRule() {
- return rule;
- }
-
- /**
- * Sets the rule violated
- *
- * @return the current object
- */
- public Violation setRule(Rule rule) {
- this.rule = rule;
- return this;
- }
-
- public String getMessage() {
- return message;
- }
-
- /**
- * Sets the violation message
- *
- * @return the current object
- */
- public Violation setMessage(String message) {
- this.message = message;
- return this;
- }
-
- /**
- * @see #setLineId(Integer)
- */
- public Integer getLineId() {
- return lineId;
- }
-
- /**
- * Sets the violation line. Note that numbering starts from 1.
- *
- * @return the current object
- */
- public Violation setLineId(Integer lineId) {
- this.lineId = lineId;
- return this;
- }
-
- /**
- * @since 2.5
- */
- public RulePriority getSeverity() {
- return severity;
- }
-
- /**
- * For internal use only.
- *
- * @since 2.5
- */
- public Violation setSeverity(RulePriority severity) {
- this.severity = severity;
- return this;
- }
-
- /**
- * @deprecated since 2.5 use {@link #getSeverity()} instead. See http://jira.codehaus.org/browse/SONAR-1829
- */
- @Deprecated
- public RulePriority getPriority() {
- return severity;
- }
-
- /**
- * For internal use only
- *
- * @deprecated since 2.5 use {@link #setSeverity(RulePriority)} instead. See http://jira.codehaus.org/browse/SONAR-1829
- */
- @Deprecated
- public Violation setPriority(RulePriority priority) {
- this.severity = priority;
- return this;
- }
-
- /**
- * @see #setCost(Double)
- * @since 2.4
- */
- public Double getCost() {
- return cost;
- }
-
- /**
- * The cost to fix a violation can't be precisely computed without this information. Let's take the following example : a rule forbids to
- * have methods whose complexity is greater than 10. Without this field "cost", the same violation is created with a method whose
- * complexity is 15 and a method whose complexity is 100. If the cost to fix one point of complexity is 0.05h, then 15mn is necessary to
- * fix the method whose complexity is 15, and 3h5mn is required to fix the method whose complexity is 100.
- *
- * @since 2.4
- */
- public Violation setCost(Double d) {
- this.cost = d;
- return this;
- }
-
- /**
- * @since 2.5
- */
- public Date getCreatedAt() {
- return createdAt;
- }
-
- /**
- * For internal use only
- *
- * @since 2.5
- */
- public Violation setCreatedAt(Date createdAt) {
- this.createdAt = createdAt;
- return this;
- }
-
- /**
- * Switches off the current violation. This is a kind of "mute", which means the violation exists but won't be counted as an active
- * violation (and thus, won't be counted in the total number of violations).
- *
- * @since 2.8
- * @param switchedOff
- * if true, the violation is considered OFF
- */
- public void setSwitchedOff(boolean switchedOff) {
- this.switchedOff = switchedOff;
- }
-
- /**
- * Tells wether this violation is ON or OFF.
- *
- * @since 2.8
- * @return true if the violation has been switched off
- */
- public boolean isSwitchedOff() {
- return switchedOff;
- }
-
- @Override
- public boolean equals(Object obj) {
- if ( !(obj instanceof Violation)) {
- return false;
- }
- if (this == obj) {
- return true;
- }
- Violation other = (Violation) obj;
- return new EqualsBuilder().append(rule, other.getRule()).append(resource, other.getResource()).isEquals();
- }
-
- @Override
- public int hashCode() {
- return new HashCodeBuilder(17, 37).append(getRule()).append(getResource()).toHashCode();
- }
-
- @Override
- public String toString() {
- return ReflectionToStringBuilder.toString(this);
- }
-
- public static Violation create(ActiveRule activeRule, Resource resource) {
- return new Violation(activeRule.getRule()).setResource(resource);
- }
-
- public static Violation create(Rule rule, Resource resource) {
- return new Violation(rule).setResource(resource);
- }
-
-}
+/* + * 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.api.rules; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.sonar.api.resources.Resource; + +import java.util.Date; + +/** + * A class that represents a violation. A violation happens when a resource does not respect a defined rule. + */ +public class Violation { + + private Resource resource; + private Rule rule; + private String message; + private RulePriority severity; + private Integer lineId; + private Double cost; + private Date createdAt; + private boolean switchedOff; + + /** + * Creates of a violation from a rule. Will need to define the resource later on + * + * @deprecated since 2.3. Use the factory method create() + */ + @Deprecated + public Violation(Rule rule) { + this.rule = rule; + } + + /** + * Creates a fully qualified violation + * + * @param rule + * the rule that has been violated + * @param resource + * the resource the violation should be attached to + * @deprecated since 2.3. Use the factory method create() + */ + @Deprecated + public Violation(Rule rule, Resource resource) { + this.resource = resource; + this.rule = rule; + } + + public Resource getResource() { + return resource; + } + + /** + * Sets the resource the violation applies to + * + * @return the current object + */ + public Violation setResource(Resource resource) { + this.resource = resource; + return this; + } + + public Rule getRule() { + return rule; + } + + /** + * Sets the rule violated + * + * @return the current object + */ + public Violation setRule(Rule rule) { + this.rule = rule; + return this; + } + + public String getMessage() { + return message; + } + + /** + * Sets the violation message + * + * @return the current object + */ + public Violation setMessage(String message) { + this.message = message; + return this; + } + + /** + * @see #setLineId(Integer) + */ + public Integer getLineId() { + return lineId; + } + + /** + * Sets the violation line. Note that numbering starts from 1. + * + * @return the current object + */ + public Violation setLineId(Integer lineId) { + this.lineId = lineId; + return this; + } + + /** + * @since 2.5 + */ + public RulePriority getSeverity() { + return severity; + } + + /** + * For internal use only. + * + * @since 2.5 + */ + public Violation setSeverity(RulePriority severity) { + this.severity = severity; + return this; + } + + /** + * @deprecated since 2.5 use {@link #getSeverity()} instead. See http://jira.codehaus.org/browse/SONAR-1829 + */ + @Deprecated + public RulePriority getPriority() { + return severity; + } + + /** + * For internal use only + * + * @deprecated since 2.5 use {@link #setSeverity(RulePriority)} instead. See http://jira.codehaus.org/browse/SONAR-1829 + */ + @Deprecated + public Violation setPriority(RulePriority priority) { + this.severity = priority; + return this; + } + + /** + * @see #setCost(Double) + * @since 2.4 + */ + public Double getCost() { + return cost; + } + + /** + * The cost to fix a violation can't be precisely computed without this information. Let's take the following example : a rule forbids to + * have methods whose complexity is greater than 10. Without this field "cost", the same violation is created with a method whose + * complexity is 15 and a method whose complexity is 100. If the cost to fix one point of complexity is 0.05h, then 15mn is necessary to + * fix the method whose complexity is 15, and 3h5mn is required to fix the method whose complexity is 100. + * + * @since 2.4 + */ + public Violation setCost(Double d) { + this.cost = d; + return this; + } + + /** + * @since 2.5 + */ + public Date getCreatedAt() { + return createdAt; + } + + /** + * For internal use only + * + * @since 2.5 + */ + public Violation setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + /** + * Switches off the current violation. This is a kind of "mute", which means the violation exists but won't be counted as an active + * violation (and thus, won't be counted in the total number of violations). + * + * @since 2.8 + * @param switchedOff + * if true, the violation is considered OFF + */ + public void setSwitchedOff(boolean switchedOff) { + this.switchedOff = switchedOff; + } + + /** + * Tells wether this violation is ON or OFF. + * + * @since 2.8 + * @return true if the violation has been switched off + */ + public boolean isSwitchedOff() { + return switchedOff; + } + + @Override + public boolean equals(Object obj) { + if ( !(obj instanceof Violation)) { + return false; + } + if (this == obj) { + return true; + } + Violation other = (Violation) obj; + return new EqualsBuilder().append(rule, other.getRule()).append(resource, other.getResource()).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37).append(getRule()).append(getResource()).toHashCode(); + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } + + public static Violation create(ActiveRule activeRule, Resource resource) { + return new Violation(activeRule.getRule()).setResource(resource); + } + + public static Violation create(Rule rule, Resource resource) { + return new Violation(rule).setResource(resource); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java b/sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java index e9f5ebdbdfa..10be756b640 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java @@ -1,89 +1,89 @@ -/*
- * 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.api.violations;
-
-import org.sonar.api.resources.Resource;
-
-/**
- * Class that allows to query the Sonar index about violations.
- *
- * @since 2.8
- */
-public final class ViolationQuery {
-
- private boolean ignoreSwitchedOff;
- private Resource resource;
-
- /**
- * Use the factory method <code>create()</code>
- */
- ViolationQuery() {
- }
-
- /**
- * Creates a new {@link ViolationQuery} object.
- *
- * @return the new query
- */
- public static ViolationQuery create() {
- return new ViolationQuery();
- }
-
- /**
- * Specifies if the query should returned switched-off violations or not.
- *
- * @param ignore
- * if true, the query will return only active violations.
- * @return the current violation query
- */
- public ViolationQuery ignoreSwitchedOff(boolean ignore) {
- this.ignoreSwitchedOff = ignore;
- return this;
- }
-
- /**
- * Tells if the query should returned switched-off violations or not.
- *
- * @return
- */
- public boolean ignoreSwitchedOff() {
- return ignoreSwitchedOff;
- }
-
- /**
- * Specifies the resource which violations are search from.
- *
- * @param resource
- * the resource
- */
- public ViolationQuery forResource(Resource resource) {
- this.resource = resource;
- return this;
- }
-
- /**
- * Returns the resource which violations are search from.
- *
- * @return the resource
- */
- public Resource getResource() {
- return resource;
- }
-}
+/* + * 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.api.violations; + +import org.sonar.api.resources.Resource; + +/** + * Class that allows to query the Sonar index about violations. + * + * @since 2.8 + */ +public final class ViolationQuery { + + private boolean ignoreSwitchedOff; + private Resource resource; + + /** + * Use the factory method <code>create()</code> + */ + ViolationQuery() { + } + + /** + * Creates a new {@link ViolationQuery} object. + * + * @return the new query + */ + public static ViolationQuery create() { + return new ViolationQuery(); + } + + /** + * Specifies if the query should returned switched-off violations or not. + * + * @param ignore + * if true, the query will return only active violations. + * @return the current violation query + */ + public ViolationQuery ignoreSwitchedOff(boolean ignore) { + this.ignoreSwitchedOff = ignore; + return this; + } + + /** + * Tells if the query should returned switched-off violations or not. + * + * @return + */ + public boolean ignoreSwitchedOff() { + return ignoreSwitchedOff; + } + + /** + * Specifies the resource which violations are search from. + * + * @param resource + * the resource + */ + public ViolationQuery forResource(Resource resource) { + this.resource = resource; + return this; + } + + /** + * Returns the resource which violations are search from. + * + * @return the resource + */ + public Resource getResource() { + return resource; + } +} diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb index 12bfbb61ff6..bc4d569dd8d 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb @@ -1,339 +1,339 @@ -#
-# Sonar, entreprise quality control 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
-#
-class ResourceController < ApplicationController
-
- SECTION=Navigation::SECTION_RESOURCE
- helper DashboardHelper
-
- def index
- @resource = Project.by_key(params[:id])
-
- if (@resource && has_role?(:user, @resource))
- params[:layout]='false'
- @snapshot=@resource.last_snapshot
-
- load_extensions()
-
- if @extension
- if (@extension.getId()=='violations')
- render_violations()
- elsif (@extension.getId()=='coverage')
- render_coverage()
- elsif (@extension.getId()=='source')
- render_source()
- else
- render_extension()
- end
- else
- render_nothing()
- end
- else
- access_denied
- end
- end
-
- private
-
- def load_extensions
- @extensions=[]
- java_facade.getResourceTabs(@resource.scope, @resource.qualifier, @resource.language).each do |tab|
- tab.getUserRoles().each do |role|
- if has_role?(role, @resource)
- @extensions<<tab
- break
- end
- end
- end
-
- if !params[:tab].blank?
- @extension=@extensions.find{|extension| extension.getId()==params[:tab]}
-
- elsif !params[:metric].blank?
- metric=Metric.by_key(params[:metric])
- @extension=@extensions.find{|extension| extension.getDefaultTabForMetrics().include?(metric.key)}
-
- end
- @extension=@extensions.find{|extension| extension.isDefaultTab()} if @extension==nil
- end
-
- def load_sources
- @period = params[:period].to_i unless params[:period].blank?
- @expanded=(params[:expand]=='true')
-
- if @snapshot.source
- source_lines=Java::OrgSonarServerUi::JRubyFacade.new.colorizeCode(@snapshot.source.data, @snapshot.project.language).split("\n")
- init_scm()
-
- @lines=[]
- source_lines.each_with_index do |source, index|
- line=Line.new(source)
- @lines<<line
-
- line.revision=@revisions_by_line[index+1]
- line.author=@authors_by_line[index+1]
-
- date_string=@dates_by_line[index+1]
- line.datetime=(date_string ? Java::OrgSonarApiUtils::DateUtils.parseDateTime(date_string): nil)
- end
- end
- end
-
- def init_scm
- @scm_available=(@snapshot.measure('last_commit_datetimes_by_line')!=nil)
- @authors_by_line=load_distribution('authors_by_line')
- @revisions_by_line=load_distribution('revisions_by_line')
- @dates_by_line=load_distribution('last_commit_datetimes_by_line')
- end
-
- def load_distribution(metric_key)
- m=@snapshot.measure(metric_key)
- m ? m.data_as_line_distribution() : {}
- end
-
- def render_coverage
- load_sources()
- @display_coverage=true
- @expandable=(@lines!=nil)
- if @lines
- @hits_by_line=load_distribution('coverage_line_hits_data')
- @conditions_by_line=load_distribution('conditions_by_line')
- @covered_conditions_by_line=load_distribution('covered_conditions_by_line')
-
- @hits_by_line.each_pair do |line_id,hits|
- line=@lines[line_id-1]
- if line
- line.hits=hits.to_i
- line.conditions=@conditions_by_line[line_id].to_i
- line.covered_conditions=@covered_conditions_by_line[line_id].to_i
- end
- end
-
- if @snapshot.measure('conditions_by_line').nil?
- # TODO remove this code when branch_coverage_hits_data is fully removed from CoreMetrics
- deprecated_branches_by_line=load_distribution('branch_coverage_hits_data')
- deprecated_branches_by_line.each_pair do |line_id,label|
- line=@lines[line_id-1]
- if line
- line.deprecated_conditions_label=label
- end
- end
- end
-
- to=(@period ? Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000) : nil)
- metric=Metric.by_key(params[:coverage_filter]||params[:metric])
- @coverage_filter=(metric ? metric.key : 'coverage')
- @filtered=true
- if ('lines_to_cover'==@coverage_filter || 'coverage'==@coverage_filter || 'line_coverage'==@coverage_filter ||
- 'new_lines_to_cover'==@coverage_filter || 'new_coverage'==@coverage_filter || 'new_line_coverage'==@coverage_filter)
- @coverage_filter='lines_to_cover'
- filter_lines{|line| line.hits && line.after(to)}
-
- elsif 'uncovered_lines'==@coverage_filter || 'new_uncovered_lines'==@coverage_filter
- @coverage_filter='uncovered_lines'
- filter_lines{|line| line.hits && line.hits==0 && line.after(to)}
-
- elsif 'conditions_to_cover'==@coverage_filter || 'branch_coverage'==@coverage_filter ||
- 'new_conditions_to_cover'==@coverage_filter || 'new_branch_coverage'==@coverage_filter
- @coverage_filter='conditions_to_cover'
- filter_lines{|line| line.conditions && line.conditions>0 && line.after(to)}
-
- elsif 'uncovered_conditions'==@coverage_filter || 'new_uncovered_conditions'==@coverage_filter
- @coverage_filter='uncovered_conditions'
- filter_lines{|line| line.conditions && line.covered_conditions && line.covered_conditions<line.conditions && line.after(to)}
- end
- end
- render :action => 'index', :layout => !request.xhr?
- end
-
-
-
- def render_violations
- load_sources()
- @display_violations=true
- @global_violations=[]
- @expandable=(@lines!=nil)
- @filtered=!@expanded
-
- conditions='switched_off is not true AND snapshot_id=?'
- values=[@snapshot.id]
- unless params[:rule].blank?
- severity=Sonar::RulePriority.id(params[:rule])
- if severity
- conditions += ' AND failure_level=?'
- values<<severity
- else
- rule=Rule.by_key_or_id(params[:rule])
- conditions += ' AND rule_id=?'
- values<<(rule ? rule.id : -1)
- end
- end
-
- if @period
- date=@snapshot.period_datetime(@period)
- if date
- conditions+=' AND created_at>?'
- values<<date.advance(:minutes => 1)
- else
- conditions+=' AND id=-1'
- end
- end
-
- RuleFailure.find(:all, :include => ['rule', 'reviews' ], :conditions => [conditions] + values, :order => 'failure_level DESC').each do |violation|
- # sorted by severity => from blocker to info
- if violation.line && violation.line>0 && @lines
- @lines[violation.line-1].add_violation(violation)
- else
- @global_violations<<violation
- end
- # if the permanent_id does not exist, set it to the current id
- unless violation.permanent_id
- violation.permanent_id = violation.id
- violation.save
- end
- end
-
- if !@expanded && @lines
- filter_lines{|line| line.violations?}
- end
- render :action => 'index', :layout => !request.xhr?
- end
-
-
- def render_source
- load_sources()
- filter_lines_by_date()
- render :action => 'index', :layout => !request.xhr?
- end
-
-
- def filter_lines_by_date
- if @period
- @filtered=true
- to=Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000)
- if to
- @lines.each do |line|
- line.flag_as_hidden() if !line.after(to)
- end
- end
- end
- end
-
- def filter_lines(&block)
- @lines.each_with_index do |line,index|
- if yield(line)
- for i in index-4...index
- @lines[i].flag_as_highlight_context() if i>=0
- end
- line.flag_as_highlighted()
- for i in index+1..index+4
- @lines[i].flag_as_highlight_context() if i<@lines.size
- end
- else
- line.flag_as_hidden()
- end
- end
- end
-
- class Line
- attr_accessor :source, :revision, :author, :datetime, :violations, :hits, :conditions, :covered_conditions, :hidden, :highlighted, :deprecated_conditions_label
-
- def initialize(source)
- @source=source
- end
-
- def add_violation(violation)
- @violations||=[]
- @violations<<violation
- @visible=true
- end
-
- def violations?
- @violations && @violations.size>0
- end
-
- def violation_severity
- if @violations && @violations.size>0
- @violations[0].failure_level
- else
- nil
- end
- end
-
- def after(date)
- if date && @datetime
- @datetime.after(date)
- else
- true
- end
- end
-
- def flag_as_highlighted
- @highlighted=true
- @hidden=false
- end
-
- def flag_as_highlight_context
- # do not force if highlighted has already been set to true
- @highlighted=false if @highlighted.nil?
- @hidden=false
- end
-
- def flag_as_hidden
- # do not force if it has already been flagged as visible
- if @hidden.nil?
- @hidden=true
- @highlighted=false
- end
- end
-
- def hidden?
- @hidden==true
- end
-
- def highlighted?
- # highlighted if the @highlighted has not been set or has been set to true
- !hidden? && @highlighted!=false
- end
-
- def deprecated_conditions_label=(label)
- if label
- @deprecated_conditions_label=label
- if label=='0%'
- @conditions=2
- @covered_conditions=0
- elsif label=='100%'
- @conditions=2
- @covered_conditions=2
- else
- @conditions=2
- @covered_conditions=1
- end
- end
- end
- end
-
- def render_extension()
- render :action => 'extension', :layout => !request.xhr?
- end
-
- def render_nothing()
- render :action => 'nothing', :layout => !request.xhr?
+# +# Sonar, entreprise quality control 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 +# +class ResourceController < ApplicationController + + SECTION=Navigation::SECTION_RESOURCE + helper DashboardHelper + + def index + @resource = Project.by_key(params[:id]) + + if (@resource && has_role?(:user, @resource)) + params[:layout]='false' + @snapshot=@resource.last_snapshot + + load_extensions() + + if @extension + if (@extension.getId()=='violations') + render_violations() + elsif (@extension.getId()=='coverage') + render_coverage() + elsif (@extension.getId()=='source') + render_source() + else + render_extension() + end + else + render_nothing() + end + else + access_denied + end + end + + private + + def load_extensions + @extensions=[] + java_facade.getResourceTabs(@resource.scope, @resource.qualifier, @resource.language).each do |tab| + tab.getUserRoles().each do |role| + if has_role?(role, @resource) + @extensions<<tab + break + end + end + end + + if !params[:tab].blank? + @extension=@extensions.find{|extension| extension.getId()==params[:tab]} + + elsif !params[:metric].blank? + metric=Metric.by_key(params[:metric]) + @extension=@extensions.find{|extension| extension.getDefaultTabForMetrics().include?(metric.key)} + + end + @extension=@extensions.find{|extension| extension.isDefaultTab()} if @extension==nil + end + + def load_sources + @period = params[:period].to_i unless params[:period].blank? + @expanded=(params[:expand]=='true') + + if @snapshot.source + source_lines=Java::OrgSonarServerUi::JRubyFacade.new.colorizeCode(@snapshot.source.data, @snapshot.project.language).split("\n") + init_scm() + + @lines=[] + source_lines.each_with_index do |source, index| + line=Line.new(source) + @lines<<line + + line.revision=@revisions_by_line[index+1] + line.author=@authors_by_line[index+1] + + date_string=@dates_by_line[index+1] + line.datetime=(date_string ? Java::OrgSonarApiUtils::DateUtils.parseDateTime(date_string): nil) + end + end + end + + def init_scm + @scm_available=(@snapshot.measure('last_commit_datetimes_by_line')!=nil) + @authors_by_line=load_distribution('authors_by_line') + @revisions_by_line=load_distribution('revisions_by_line') + @dates_by_line=load_distribution('last_commit_datetimes_by_line') + end + + def load_distribution(metric_key) + m=@snapshot.measure(metric_key) + m ? m.data_as_line_distribution() : {} + end + + def render_coverage + load_sources() + @display_coverage=true + @expandable=(@lines!=nil) + if @lines + @hits_by_line=load_distribution('coverage_line_hits_data') + @conditions_by_line=load_distribution('conditions_by_line') + @covered_conditions_by_line=load_distribution('covered_conditions_by_line') + + @hits_by_line.each_pair do |line_id,hits| + line=@lines[line_id-1] + if line + line.hits=hits.to_i + line.conditions=@conditions_by_line[line_id].to_i + line.covered_conditions=@covered_conditions_by_line[line_id].to_i + end + end + + if @snapshot.measure('conditions_by_line').nil? + # TODO remove this code when branch_coverage_hits_data is fully removed from CoreMetrics + deprecated_branches_by_line=load_distribution('branch_coverage_hits_data') + deprecated_branches_by_line.each_pair do |line_id,label| + line=@lines[line_id-1] + if line + line.deprecated_conditions_label=label + end + end + end + + to=(@period ? Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000) : nil) + metric=Metric.by_key(params[:coverage_filter]||params[:metric]) + @coverage_filter=(metric ? metric.key : 'coverage') + @filtered=true + if ('lines_to_cover'==@coverage_filter || 'coverage'==@coverage_filter || 'line_coverage'==@coverage_filter || + 'new_lines_to_cover'==@coverage_filter || 'new_coverage'==@coverage_filter || 'new_line_coverage'==@coverage_filter) + @coverage_filter='lines_to_cover' + filter_lines{|line| line.hits && line.after(to)} + + elsif 'uncovered_lines'==@coverage_filter || 'new_uncovered_lines'==@coverage_filter + @coverage_filter='uncovered_lines' + filter_lines{|line| line.hits && line.hits==0 && line.after(to)} + + elsif 'conditions_to_cover'==@coverage_filter || 'branch_coverage'==@coverage_filter || + 'new_conditions_to_cover'==@coverage_filter || 'new_branch_coverage'==@coverage_filter + @coverage_filter='conditions_to_cover' + filter_lines{|line| line.conditions && line.conditions>0 && line.after(to)} + + elsif 'uncovered_conditions'==@coverage_filter || 'new_uncovered_conditions'==@coverage_filter + @coverage_filter='uncovered_conditions' + filter_lines{|line| line.conditions && line.covered_conditions && line.covered_conditions<line.conditions && line.after(to)} + end + end + render :action => 'index', :layout => !request.xhr? + end + + + + def render_violations + load_sources() + @display_violations=true + @global_violations=[] + @expandable=(@lines!=nil) + @filtered=!@expanded + + conditions='switched_off is not true AND snapshot_id=?' + values=[@snapshot.id] + unless params[:rule].blank? + severity=Sonar::RulePriority.id(params[:rule]) + if severity + conditions += ' AND failure_level=?' + values<<severity + else + rule=Rule.by_key_or_id(params[:rule]) + conditions += ' AND rule_id=?' + values<<(rule ? rule.id : -1) + end + end + + if @period + date=@snapshot.period_datetime(@period) + if date + conditions+=' AND created_at>?' + values<<date.advance(:minutes => 1) + else + conditions+=' AND id=-1' + end + end + + RuleFailure.find(:all, :include => ['rule', 'reviews' ], :conditions => [conditions] + values, :order => 'failure_level DESC').each do |violation| + # sorted by severity => from blocker to info + if violation.line && violation.line>0 && @lines + @lines[violation.line-1].add_violation(violation) + else + @global_violations<<violation + end + # if the permanent_id does not exist, set it to the current id + unless violation.permanent_id + violation.permanent_id = violation.id + violation.save + end + end + + if !@expanded && @lines + filter_lines{|line| line.violations?} + end + render :action => 'index', :layout => !request.xhr? + end + + + def render_source + load_sources() + filter_lines_by_date() + render :action => 'index', :layout => !request.xhr? + end + + + def filter_lines_by_date + if @period + @filtered=true + to=Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000) + if to + @lines.each do |line| + line.flag_as_hidden() if !line.after(to) + end + end + end + end + + def filter_lines(&block) + @lines.each_with_index do |line,index| + if yield(line) + for i in index-4...index + @lines[i].flag_as_highlight_context() if i>=0 + end + line.flag_as_highlighted() + for i in index+1..index+4 + @lines[i].flag_as_highlight_context() if i<@lines.size + end + else + line.flag_as_hidden() + end + end + end + + class Line + attr_accessor :source, :revision, :author, :datetime, :violations, :hits, :conditions, :covered_conditions, :hidden, :highlighted, :deprecated_conditions_label + + def initialize(source) + @source=source + end + + def add_violation(violation) + @violations||=[] + @violations<<violation + @visible=true + end + + def violations? + @violations && @violations.size>0 + end + + def violation_severity + if @violations && @violations.size>0 + @violations[0].failure_level + else + nil + end + end + + def after(date) + if date && @datetime + @datetime.after(date) + else + true + end + end + + def flag_as_highlighted + @highlighted=true + @hidden=false + end + + def flag_as_highlight_context + # do not force if highlighted has already been set to true + @highlighted=false if @highlighted.nil? + @hidden=false + end + + def flag_as_hidden + # do not force if it has already been flagged as visible + if @hidden.nil? + @hidden=true + @highlighted=false + end + end + + def hidden? + @hidden==true + end + + def highlighted? + # highlighted if the @highlighted has not been set or has been set to true + !hidden? && @highlighted!=false + end + + def deprecated_conditions_label=(label) + if label + @deprecated_conditions_label=label + if label=='0%' + @conditions=2 + @covered_conditions=0 + elsif label=='100%' + @conditions=2 + @covered_conditions=2 + else + @conditions=2 + @covered_conditions=1 + end + end + end + end + + def render_extension() + render :action => 'extension', :layout => !request.xhr? + end + + def render_nothing() + render :action => 'nothing', :layout => !request.xhr? end end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb index d5c3b7c56a0..ca8ef32259a 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb @@ -1,263 +1,263 @@ -#
-# Sonar, entreprise quality control 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
-#
-
-class ReviewsController < ApplicationController
-
- SECTION=Navigation::SECTION_HOME
-
- verify :method => :post, :only => [ :create, :create_comment ], :redirect_to => { :action => :error_not_post }
-
- def index
- init_params
-
- @reviews = []
- unless params.blank?
- find_reviews_for_user_query
- end
- end
-
- def list
- reviews = find_reviews_for_rule_failure params[:rule_failure_permanent_id]
- render :partial => "list", :locals => { :reviews => reviews }
- end
-
- def display_violation
- violation = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]
- render :partial => "resource/violation", :locals => { :violation => violation }
- end
-
- def form
- rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]
- @review = Review.new
- @review.rule_failure_permanent_id = rule_failure.permanent_id
- @review_comment = ReviewComment.new
- @review_comment.review_text = ""
- if params[:switch_off]
- @review.review_type = "f-positive"
- else
- @review.review_type = Review.default_type
- end
- render :partial => "form"
- end
-
- def create
- rule_failure = find_last_rule_failure_with_permanent_id params[:review][:rule_failure_permanent_id]
- unless has_rights_to_create? rule_failure
- render :text => "<b>Cannot create the review</b> : access denied."
- return
- end
-
- @review = Review.new(params[:review])
- @review.user = current_user
- if params[:assign_to_me]
- @review.assignee = current_user
- end
- @review.title = rule_failure.message
- @review.status = Review.default_status
- @review.severity = Sonar::RulePriority.to_s rule_failure.failure_level
- @review.resource = RuleFailure.find( @review.rule_failure_permanent_id, :include => ['snapshot'] ).snapshot.project
- @review_comment = ReviewComment.new(params[:review_comment])
- @review_comment.user = current_user
- @review.review_comments << @review_comment
- if @review.valid?
- if @review.review_type == "f-positive"
- if rule_failure.get_open_review
- current_open_review = rule_failure.get_open_review
- current_open_review.status = "closed"
- current_open_review.save
- end
- rule_failure.switched_off = true
- rule_failure.save
- end
- @review.save
- @violation = rule_failure
- end
- render "create_result"
- end
-
- def form_comment
- @review_comment = ReviewComment.new
- @review_comment.user = current_user
- @review_comment.review_id = params[:review_id]
- @review_comment.review_text = ""
- @rule_failure_permanent_id = params[:rule_failure_permanent_id]
- if params[:update_comment]
- @update_comment = true
- @review_comment.review_text = params[:review_text]
- end
- render :partial => "form_comment"
- end
-
- def create_comment
- rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]
- unless has_rights_to_create? rule_failure
- render :text => "<b>Cannot create the comment</b> : access denied."
- return
- end
-
- @review_comment = ReviewComment.new(params[:review_comment])
- @review_comment.user = current_user
- @rule_failure_permanent_id = params[:rule_failure_permanent_id]
- if @review_comment.valid?
- @review_comment.save
- # -- TODO : should create a Review#create_comment and put the following logic in it
- review = @review_comment.review
- review.updated_at = @review_comment.created_at
- review.save
- # -- End of TODO code --
- @violation = rule_failure
- end
- render "create_comment_result"
- end
-
- def update_comment
- review = Review.find params[:review_comment][:review_id]
- @review_comment = review.review_comments.last
- unless current_user && current_user.id == @review_comment.user_id
- render :text => "<b>Cannot modify the comment</b> : access denied."
- return
- end
-
- @review_comment.review_text = params[:review_comment][:review_text]
- @review_comment.created_at = DateTime.now
- @rule_failure_permanent_id = params[:rule_failure_permanent_id]
- if @review_comment.valid?
- @review_comment.save
- review.updated_at = @review_comment.updated_at
- review.save
- @violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id
- end
- render "create_comment_result"
- end
-
- def form_assign
- @user_options = add_all_users []
- @review_id = params[:review_id]
- @rule_failure_permanent_id = params[:rule_failure_permanent_id]
- render :partial => "form_assign"
- end
-
- def assign
- review = Review.find params[:review_id]
- unless current_user
- render :text => "<b>Cannot edit the review</b> : access denied."
- return
- end
-
- review.assignee = User.find params[:assignee_id]
- review.save
- violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id
- render :partial => "resource/violation", :locals => { :violation => violation }
- end
-
- def close_review
- review = Review.find params[:review_id]
- unless current_user
- render :text => "<b>Cannot edit the review</b> : access denied."
- return
- end
-
- review.status = "closed"
- review.save
- violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id
- render :partial => "resource/violation", :locals => { :violation => violation }
- end
-
- ## -------------- PRIVATE -------------- ##
- private
-
- def init_params
- @user_names = [["Any", ""]]
- default_user = [""]
- if current_user
- default_user = [current_user.id]
- end
- add_all_users @user_names
- @review_authors = filter_any(params[:review_authors]) || default_user
- @comment_authors = filter_any(params[:comment_authors]) || default_user
- @severities = filter_any(params[:severities]) || [""]
- @statuses = filter_any(params[:statuses]) || ["open"]
- end
-
- def add_all_users ( user_options )
- User.find( :all ).each do |user|
- userName = user.name
- if current_user.id == user.id
- userName = "Me (" + user.name + ")"
- end
- user_options << [userName, user.id.to_s]
- end
- return user_options
- end
-
- def filter_any(array)
- if array && array.size>1 && array.include?("")
- array=[""]
- end
- array
- end
-
- def find_reviews_for_user_query
- conditions=[]
- values={}
-
- unless @statuses == [""]
- conditions << "reviews.status in (:statuses)"
- values[:statuses]=@statuses
- end
- unless @severities == [""]
- conditions << "reviews.severity in (:severities)"
- values[:severities]=@severities
- end
- unless @review_authors == [""]
- conditions << "reviews.user_id in (:review_authors)"
- values[:review_authors]=@review_authors
- end
- unless @comment_authors == [""]
- conditions << "review_comments.user_id in (:comment_authors)"
- values[:comment_authors]=@comment_authors
- end
-
- @reviews = Review.find( :all, :order => "created_at DESC", :joins => :review_comments, :conditions => [ conditions.join(" AND "), values] ).uniq
- end
-
- def find_reviews_for_rule_failure ( rule_failure_permanent_id )
- return Review.find :all, :conditions => ['rule_failure_permanent_id=?', rule_failure_permanent_id]
- end
-
- def find_last_rule_failure_with_permanent_id ( rule_failure_permanent_id )
- return RuleFailure.last( :all, :conditions => [ "permanent_id = ?", rule_failure_permanent_id ], :include => ['snapshot'] )
- end
-
- def has_rights_to_create? ( rule_failure )
- return false unless current_user
-
- project = rule_failure.snapshot.root_project
- unless has_role?(:user, project)
- return false
- end
- return true
- end
-
- def error_not_post
- render :text => "Create actions must use POST method."
- end
-
-end
+# +# Sonar, entreprise quality control 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 +# + +class ReviewsController < ApplicationController + + SECTION=Navigation::SECTION_HOME + + verify :method => :post, :only => [ :create, :create_comment ], :redirect_to => { :action => :error_not_post } + + def index + init_params + + @reviews = [] + unless params.blank? + find_reviews_for_user_query + end + end + + def list + reviews = find_reviews_for_rule_failure params[:rule_failure_permanent_id] + render :partial => "list", :locals => { :reviews => reviews } + end + + def display_violation + violation = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id] + render :partial => "resource/violation", :locals => { :violation => violation } + end + + def form + rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id] + @review = Review.new + @review.rule_failure_permanent_id = rule_failure.permanent_id + @review_comment = ReviewComment.new + @review_comment.review_text = "" + if params[:switch_off] + @review.review_type = "f-positive" + else + @review.review_type = Review.default_type + end + render :partial => "form" + end + + def create + rule_failure = find_last_rule_failure_with_permanent_id params[:review][:rule_failure_permanent_id] + unless has_rights_to_create? rule_failure + render :text => "<b>Cannot create the review</b> : access denied." + return + end + + @review = Review.new(params[:review]) + @review.user = current_user + if params[:assign_to_me] + @review.assignee = current_user + end + @review.title = rule_failure.message + @review.status = Review.default_status + @review.severity = Sonar::RulePriority.to_s rule_failure.failure_level + @review.resource = RuleFailure.find( @review.rule_failure_permanent_id, :include => ['snapshot'] ).snapshot.project + @review_comment = ReviewComment.new(params[:review_comment]) + @review_comment.user = current_user + @review.review_comments << @review_comment + if @review.valid? + if @review.review_type == "f-positive" + if rule_failure.get_open_review + current_open_review = rule_failure.get_open_review + current_open_review.status = "closed" + current_open_review.save + end + rule_failure.switched_off = true + rule_failure.save + end + @review.save + @violation = rule_failure + end + render "create_result" + end + + def form_comment + @review_comment = ReviewComment.new + @review_comment.user = current_user + @review_comment.review_id = params[:review_id] + @review_comment.review_text = "" + @rule_failure_permanent_id = params[:rule_failure_permanent_id] + if params[:update_comment] + @update_comment = true + @review_comment.review_text = params[:review_text] + end + render :partial => "form_comment" + end + + def create_comment + rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id] + unless has_rights_to_create? rule_failure + render :text => "<b>Cannot create the comment</b> : access denied." + return + end + + @review_comment = ReviewComment.new(params[:review_comment]) + @review_comment.user = current_user + @rule_failure_permanent_id = params[:rule_failure_permanent_id] + if @review_comment.valid? + @review_comment.save + # -- TODO : should create a Review#create_comment and put the following logic in it + review = @review_comment.review + review.updated_at = @review_comment.created_at + review.save + # -- End of TODO code -- + @violation = rule_failure + end + render "create_comment_result" + end + + def update_comment + review = Review.find params[:review_comment][:review_id] + @review_comment = review.review_comments.last + unless current_user && current_user.id == @review_comment.user_id + render :text => "<b>Cannot modify the comment</b> : access denied." + return + end + + @review_comment.review_text = params[:review_comment][:review_text] + @review_comment.created_at = DateTime.now + @rule_failure_permanent_id = params[:rule_failure_permanent_id] + if @review_comment.valid? + @review_comment.save + review.updated_at = @review_comment.updated_at + review.save + @violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id + end + render "create_comment_result" + end + + def form_assign + @user_options = add_all_users [] + @review_id = params[:review_id] + @rule_failure_permanent_id = params[:rule_failure_permanent_id] + render :partial => "form_assign" + end + + def assign + review = Review.find params[:review_id] + unless current_user + render :text => "<b>Cannot edit the review</b> : access denied." + return + end + + review.assignee = User.find params[:assignee_id] + review.save + violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id + render :partial => "resource/violation", :locals => { :violation => violation } + end + + def close_review + review = Review.find params[:review_id] + unless current_user + render :text => "<b>Cannot edit the review</b> : access denied." + return + end + + review.status = "closed" + review.save + violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id + render :partial => "resource/violation", :locals => { :violation => violation } + end + + ## -------------- PRIVATE -------------- ## + private + + def init_params + @user_names = [["Any", ""]] + default_user = [""] + if current_user + default_user = [current_user.id] + end + add_all_users @user_names + @review_authors = filter_any(params[:review_authors]) || default_user + @comment_authors = filter_any(params[:comment_authors]) || default_user + @severities = filter_any(params[:severities]) || [""] + @statuses = filter_any(params[:statuses]) || ["open"] + end + + def add_all_users ( user_options ) + User.find( :all ).each do |user| + userName = user.name + if current_user.id == user.id + userName = "Me (" + user.name + ")" + end + user_options << [userName, user.id.to_s] + end + return user_options + end + + def filter_any(array) + if array && array.size>1 && array.include?("") + array=[""] + end + array + end + + def find_reviews_for_user_query + conditions=[] + values={} + + unless @statuses == [""] + conditions << "reviews.status in (:statuses)" + values[:statuses]=@statuses + end + unless @severities == [""] + conditions << "reviews.severity in (:severities)" + values[:severities]=@severities + end + unless @review_authors == [""] + conditions << "reviews.user_id in (:review_authors)" + values[:review_authors]=@review_authors + end + unless @comment_authors == [""] + conditions << "review_comments.user_id in (:comment_authors)" + values[:comment_authors]=@comment_authors + end + + @reviews = Review.find( :all, :order => "created_at DESC", :joins => :review_comments, :conditions => [ conditions.join(" AND "), values] ).uniq + end + + def find_reviews_for_rule_failure ( rule_failure_permanent_id ) + return Review.find :all, :conditions => ['rule_failure_permanent_id=?', rule_failure_permanent_id] + end + + def find_last_rule_failure_with_permanent_id ( rule_failure_permanent_id ) + return RuleFailure.last( :all, :conditions => [ "permanent_id = ?", rule_failure_permanent_id ], :include => ['snapshot'] ) + end + + def has_rights_to_create? ( rule_failure ) + return false unless current_user + + project = rule_failure.snapshot.root_project + unless has_role?(:user, project) + return false + end + return true + end + + def error_not_post + render :text => "Create actions must use POST method." + end + +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb index df4179f309d..8cd7857e7ef 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb @@ -1,72 +1,72 @@ -#
-# Sonar, entreprise quality control 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
-#
-class Review < ActiveRecord::Base
- belongs_to :user
- belongs_to :assignee, :class_name => "User", :foreign_key => "assignee_id"
- belongs_to :resource, :class_name => "Project", :foreign_key => "resource_id"
- has_many :review_comments, :order => "created_at", :dependent => :destroy
- validates_presence_of :user, :message => "can't be empty"
- validates_presence_of :title, :message => "can't be empty"
- validates_presence_of :review_type, :message => "can't be empty"
- validates_presence_of :status, :message => "can't be empty"
-
- SEVERITY_INFO = "INFO"
- SEVERITY_MINOR = "MINOR"
- SEVERITY_MAJOR = "MAJOR"
- SEVERITY_CRITICAL = "CRITICAL"
- SEVERITY_BLOCKER = "BLOCKER"
-
- TYPE_COMMENTS = "comments"
- TYPE_FALSE_POSITIVE = "f-positive"
-
- STATUS_OPEN = "open"
- STATUS_CLOSED = "closed"
-
-
- def self.default_severity
- return SEVERITY_MAJOR
- end
-
- def self.default_type
- return TYPE_COMMENTS
- end
-
- def self.default_status
- return STATUS_OPEN
- end
-
- def self.severity_options
- severity_ops = []
- severity_ops << ["Info", SEVERITY_INFO]
- severity_ops << ["Minor", SEVERITY_MINOR]
- severity_ops << ["Major", SEVERITY_MAJOR]
- severity_ops << ["Critical", SEVERITY_CRITICAL]
- severity_ops << ["Blocker", SEVERITY_BLOCKER]
- return severity_ops
- end
-
- def self.status_options
- status_ops = []
- status_ops << ["Open", STATUS_OPEN]
- status_ops << ["Closed", STATUS_CLOSED]
- return status_ops
- end
-
-end
+# +# Sonar, entreprise quality control 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 +# +class Review < ActiveRecord::Base + belongs_to :user + belongs_to :assignee, :class_name => "User", :foreign_key => "assignee_id" + belongs_to :resource, :class_name => "Project", :foreign_key => "resource_id" + has_many :review_comments, :order => "created_at", :dependent => :destroy + validates_presence_of :user, :message => "can't be empty" + validates_presence_of :title, :message => "can't be empty" + validates_presence_of :review_type, :message => "can't be empty" + validates_presence_of :status, :message => "can't be empty" + + SEVERITY_INFO = "INFO" + SEVERITY_MINOR = "MINOR" + SEVERITY_MAJOR = "MAJOR" + SEVERITY_CRITICAL = "CRITICAL" + SEVERITY_BLOCKER = "BLOCKER" + + TYPE_COMMENTS = "comments" + TYPE_FALSE_POSITIVE = "f-positive" + + STATUS_OPEN = "open" + STATUS_CLOSED = "closed" + + + def self.default_severity + return SEVERITY_MAJOR + end + + def self.default_type + return TYPE_COMMENTS + end + + def self.default_status + return STATUS_OPEN + end + + def self.severity_options + severity_ops = [] + severity_ops << ["Info", SEVERITY_INFO] + severity_ops << ["Minor", SEVERITY_MINOR] + severity_ops << ["Major", SEVERITY_MAJOR] + severity_ops << ["Critical", SEVERITY_CRITICAL] + severity_ops << ["Blocker", SEVERITY_BLOCKER] + return severity_ops + end + + def self.status_options + status_ops = [] + status_ops << ["Open", STATUS_OPEN] + status_ops << ["Closed", STATUS_CLOSED] + return status_ops + end + +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb index 45253ed2da9..bb62d4e80f2 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb @@ -1,84 +1,84 @@ -#
-# Sonar, entreprise quality control 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 {library}; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
-#
-
-class RuleFailure < ActiveRecord::Base
-
- belongs_to :rule
- belongs_to :snapshot
- has_many :reviews, :primary_key => "permanent_id", :foreign_key => "rule_failure_permanent_id", :order => "created_at"
-
- def get_open_review
- reviews.each do |review|
- if review.status == "open"
- return review
- end
- end
- return nil
- end
-
- def to_hash_json
- json = {}
- json['message'] = message
- json['line'] = line if line
- json['priority'] = Sonar::RulePriority.to_s(failure_level).upcase
- if created_at
- json['createdAt'] = format_datetime(created_at)
- end
- json['rule'] = {
- :key => rule.key,
- :name => rule.name
- }
- json['resource'] = {
- :key => snapshot.project.key,
- :name => snapshot.project.name,
- :scope => snapshot.project.scope,
- :qualifier => snapshot.project.qualifier,
- :language => snapshot.project.language
- }
- json
- end
-
- def to_xml(xml=Builder::XmlMarkup.new(:indent => 0))
- xml.violation do
- xml.message(message)
- xml.line(line) if line
- xml.priority(Sonar::RulePriority.to_s(failure_level))
- if created_at
- xml.createdAt(format_datetime(created_at))
- end
- xml.rule do
- xml.key(rule.key)
- xml.name(rule.name)
- end
- xml.resource do
- xml.key(snapshot.project.key)
- xml.name(snapshot.project.name)
- xml.scope(snapshot.project.scope)
- xml.qualifier(snapshot.project.qualifier)
- xml.language(snapshot.project.language)
- end
- end
- end
-
- def format_datetime(datetime)
- datetime.strftime("%Y-%m-%dT%H:%M:%S%z")
- end
-
-end
+# +# Sonar, entreprise quality control 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 {library}; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# + +class RuleFailure < ActiveRecord::Base + + belongs_to :rule + belongs_to :snapshot + has_many :reviews, :primary_key => "permanent_id", :foreign_key => "rule_failure_permanent_id", :order => "created_at" + + def get_open_review + reviews.each do |review| + if review.status == "open" + return review + end + end + return nil + end + + def to_hash_json + json = {} + json['message'] = message + json['line'] = line if line + json['priority'] = Sonar::RulePriority.to_s(failure_level).upcase + if created_at + json['createdAt'] = format_datetime(created_at) + end + json['rule'] = { + :key => rule.key, + :name => rule.name + } + json['resource'] = { + :key => snapshot.project.key, + :name => snapshot.project.name, + :scope => snapshot.project.scope, + :qualifier => snapshot.project.qualifier, + :language => snapshot.project.language + } + json + end + + def to_xml(xml=Builder::XmlMarkup.new(:indent => 0)) + xml.violation do + xml.message(message) + xml.line(line) if line + xml.priority(Sonar::RulePriority.to_s(failure_level)) + if created_at + xml.createdAt(format_datetime(created_at)) + end + xml.rule do + xml.key(rule.key) + xml.name(rule.name) + end + xml.resource do + xml.key(snapshot.project.key) + xml.name(snapshot.project.name) + xml.scope(snapshot.project.scope) + xml.qualifier(snapshot.project.qualifier) + xml.language(snapshot.project.language) + end + end + end + + def format_datetime(datetime) + datetime.strftime("%Y-%m-%dT%H:%M:%S%z") + end + +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form.html.erb index ceb5210de51..e9ac1210093 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form.html.erb @@ -1,30 +1,30 @@ -<% form_for :review, @review do |f| %>
- <%= f.hidden_field :rule_failure_permanent_id -%>
- <%= f.hidden_field :review_type -%>
-
- <% if @review.review_type == "f-positive" %>
- <b>Reason for flagging this violation as a false-positive:</b>
- <% end %>
- <%= text_area :review_comment, :review_text,
- :id => "reviewText", :rows => 8,
- :style => "width:100%", :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" -%>
- <br/>
-
- <div>
- <%
- if @review.review_type == "comments"
- button_text = "Post review"
- else
- button_text = "Switch-off violation"
- end
- %>
- <%= submit_to_remote "submit_btn", button_text, :url => { :action => 'create' }, :html => { :id => "submit_btn", :disabled => "true" } -%>
-
- <a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a>
- <% if @review.review_type == "comments" %>
-
- <%= check_box_tag "assign_to_me", "me", true -%> Assign to me
- <% end %>
- </div>
- </div class="clear"></div>
+<% form_for :review, @review do |f| %> + <%= f.hidden_field :rule_failure_permanent_id -%> + <%= f.hidden_field :review_type -%> + + <% if @review.review_type == "f-positive" %> + <b>Reason for flagging this violation as a false-positive:</b> + <% end %> + <%= text_area :review_comment, :review_text, + :id => "reviewText", :rows => 8, + :style => "width:100%", :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" -%> + <br/> + + <div> + <% + if @review.review_type == "comments" + button_text = "Post review" + else + button_text = "Switch-off violation" + end + %> + <%= submit_to_remote "submit_btn", button_text, :url => { :action => 'create' }, :html => { :id => "submit_btn", :disabled => "true" } -%> + + <a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a> + <% if @review.review_type == "comments" %> + + <%= check_box_tag "assign_to_me", "me", true -%> Assign to me + <% end %> + </div> + </div class="clear"></div> <% end %>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form_comment.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form_comment.html.erb index 79ad5010402..016e8052e99 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form_comment.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form_comment.html.erb @@ -1,28 +1,28 @@ -<% form_for :review_comment, @review_comment do |f| %>
- <%= f.hidden_field :review_id %>
- <%= f.text_area :review_text, :rows => 8,
- :id => "commentText" + @rule_failure_permanent_id.to_s,
- :style => "width:100%",
- :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" %>
- <br/>
-
- <% if @update_comment %>
- <%= submit_to_remote 'submit_btn', 'Update comment',
- :url => { :action => 'update_comment',
- :rule_failure_permanent_id => @rule_failure_permanent_id },
- :html => { :id => "submit_btn" } %>
-
- <%= link_to_remote 'Cancel',
- :url => { :action => 'display_violation',
- :rule_failure_permanent_id => @rule_failure_permanent_id },
- :update => "vId" + @rule_failure_permanent_id.to_s %>
- <% else %>
- <%= submit_to_remote 'submit_btn', 'Post comment',
- :url => { :action => 'create_comment',
- :rule_failure_permanent_id => @rule_failure_permanent_id },
- :html => { :id => "submit_btn", :disabled => true } %>
-
- <a onclick="$('reviewForm<%= @rule_failure_permanent_id.to_s -%>').style.display='none'; $('commentAction<%= @rule_failure_permanent_id.to_s -%>').style.display='';" href="#">Cancel</a>
- <% end %>
-
+<% form_for :review_comment, @review_comment do |f| %> + <%= f.hidden_field :review_id %> + <%= f.text_area :review_text, :rows => 8, + :id => "commentText" + @rule_failure_permanent_id.to_s, + :style => "width:100%", + :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" %> + <br/> + + <% if @update_comment %> + <%= submit_to_remote 'submit_btn', 'Update comment', + :url => { :action => 'update_comment', + :rule_failure_permanent_id => @rule_failure_permanent_id }, + :html => { :id => "submit_btn" } %> + + <%= link_to_remote 'Cancel', + :url => { :action => 'display_violation', + :rule_failure_permanent_id => @rule_failure_permanent_id }, + :update => "vId" + @rule_failure_permanent_id.to_s %> + <% else %> + <%= submit_to_remote 'submit_btn', 'Post comment', + :url => { :action => 'create_comment', + :rule_failure_permanent_id => @rule_failure_permanent_id }, + :html => { :id => "submit_btn", :disabled => true } %> + + <a onclick="$('reviewForm<%= @rule_failure_permanent_id.to_s -%>').style.display='none'; $('commentAction<%= @rule_failure_permanent_id.to_s -%>').style.display='';" href="#">Cancel</a> + <% end %> + <% end %>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_view.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_view.html.erb index 41de20ad0f7..aa12cbc38fb 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_view.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_view.html.erb @@ -1,65 +1,65 @@ - <div id="review<%= review.id -%>">
- <div>
- <b>Review #<%= review.id -%> - <%= h(review.title) -%></b>
- <br/>
- <% if review.assignee %>
- <i>Assigned to <%= h(review.assignee.name) -%></i>
- <% end %>
- </div>
-
- <div style="margin-top: 10px; margin-left: 20px">
- <% unless review.review_comments.blank?
- last_comment = review.review_comments.last
- review.review_comments.each do |review_comment|
- %>
- <table style="width:100%; margin-bottom: 3px">
- <tr style="border: solid 1px grey; background-color: #F7F7F7">
- <td style="width:180px; vertical-align:top; padding: 2px 2px 2px 10px; font-weight: bold">
- <%= image_tag("user.png") -%> <b><%= h(review_comment.user.name) -%></b>
- </td>
- <td style="vertical-align: top; padding: 2px 10px 2px 2px; color: grey; text-align: right; font-style: italic">
- <%= l review_comment.created_at -%>
- </td>
- </tr>
- <tr style="border: solid 1px grey;">
- <td colspan="2" style="padding: 5px;">
- <% if review_comment == last_comment %>
- <div id="lastComment<%= review.id -%>">
- <%= h(review_comment.review_text) -%>
- </div>
- <% else %>
- <%= h(review_comment.review_text) -%>
- <% end %>
- </td>
- </tr>
- </table>
- <%
- end
- end
- %>
-
- <% if current_user %>
- <div style="text-align: right; padding: 5px">
- <% if current_user.id == review.review_comments.last.user_id %>
- <%= image_tag("pencil.png") -%>
- <%= link_to_remote "Edit my last comment",
- :url => { :controller => "reviews", :action => "form_comment",
- :review_id => review.id,
- :rule_failure_permanent_id => review.rule_failure_permanent_id,
- :review_text => review.review_comments.last.review_text,
- :update_comment => "true" },
- :update => "lastComment" + review.id.to_s,
- :complete => "$('commentText" + review.id.to_s + "').focus()" -%>
-
- <% end %>
- <%= image_tag("pencil.png") -%>
- <%= link_to_remote "Add a new comment",
- :url => { :controller => "reviews", :action => "form_comment", :review_id => review.id, :rule_failure_permanent_id => review.rule_failure_permanent_id },
- :update => "createComment" + review.id.to_s,
- :complete => "$('commentText" + review.id.to_s + "').focus()" -%>
- </div>
- <div id="createComment<%= review.id -%>"></div>
- <% end %>
- </div>
-
- </div>
+ <div id="review<%= review.id -%>"> + <div> + <b>Review #<%= review.id -%> - <%= h(review.title) -%></b> + <br/> + <% if review.assignee %> + <i>Assigned to <%= h(review.assignee.name) -%></i> + <% end %> + </div> + + <div style="margin-top: 10px; margin-left: 20px"> + <% unless review.review_comments.blank? + last_comment = review.review_comments.last + review.review_comments.each do |review_comment| + %> + <table style="width:100%; margin-bottom: 3px"> + <tr style="border: solid 1px grey; background-color: #F7F7F7"> + <td style="width:180px; vertical-align:top; padding: 2px 2px 2px 10px; font-weight: bold"> + <%= image_tag("user.png") -%> <b><%= h(review_comment.user.name) -%></b> + </td> + <td style="vertical-align: top; padding: 2px 10px 2px 2px; color: grey; text-align: right; font-style: italic"> + <%= l review_comment.created_at -%> + </td> + </tr> + <tr style="border: solid 1px grey;"> + <td colspan="2" style="padding: 5px;"> + <% if review_comment == last_comment %> + <div id="lastComment<%= review.id -%>"> + <%= h(review_comment.review_text) -%> + </div> + <% else %> + <%= h(review_comment.review_text) -%> + <% end %> + </td> + </tr> + </table> + <% + end + end + %> + + <% if current_user %> + <div style="text-align: right; padding: 5px"> + <% if current_user.id == review.review_comments.last.user_id %> + <%= image_tag("pencil.png") -%> + <%= link_to_remote "Edit my last comment", + :url => { :controller => "reviews", :action => "form_comment", + :review_id => review.id, + :rule_failure_permanent_id => review.rule_failure_permanent_id, + :review_text => review.review_comments.last.review_text, + :update_comment => "true" }, + :update => "lastComment" + review.id.to_s, + :complete => "$('commentText" + review.id.to_s + "').focus()" -%> + + <% end %> + <%= image_tag("pencil.png") -%> + <%= link_to_remote "Add a new comment", + :url => { :controller => "reviews", :action => "form_comment", :review_id => review.id, :rule_failure_permanent_id => review.rule_failure_permanent_id }, + :update => "createComment" + review.id.to_s, + :complete => "$('commentText" + review.id.to_s + "').focus()" -%> + </div> + <div id="createComment<%= review.id -%>"></div> + <% end %> + </div> + + </div> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_comment_result.js.rjs b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_comment_result.js.rjs index f177aae9cb2..3281ad51d3b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_comment_result.js.rjs +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_comment_result.js.rjs @@ -1,5 +1,5 @@ -if @violation
- page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation }
-else
- page.replace_html "reviewForm" + @rule_failure_permanent_id.to_s, :partial => "form_comment"
+if @violation + page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation } +else + page.replace_html "reviewForm" + @rule_failure_permanent_id.to_s, :partial => "form_comment" end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_result.js.rjs b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_result.js.rjs index 720e00f11b3..9e735242a22 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_result.js.rjs +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_result.js.rjs @@ -1,5 +1,5 @@ -if @violation
- page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation }
-else
- page.replace_html "reviewForm" + @review.rule_failure_permanent_id.to_s, :partial => "form"
+if @violation + page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation } +else + page.replace_html "reviewForm" + @review.rule_failure_permanent_id.to_s, :partial => "form" end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/191_create_review.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/191_create_review.rb index f67cadcf715..937c1f60ac9 100644 --- a/sonar-server/src/main/webapp/WEB-INF/db/migrate/191_create_review.rb +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/191_create_review.rb @@ -1,54 +1,54 @@ -#
-# Sonar, entreprise quality control 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
-#
-
-#
-# Sonar 2.8
-#
-class CreateReview < ActiveRecord::Migration
-
- def self.up
- create_table 'reviews' do |t|
- t.column 'created_at', :datetime
- t.column 'updated_at', :datetime
- t.column 'user_id', :integer, :null => true
- t.column 'assignee_id', :integer, :null => true
- t.column 'title', :string, :null => true, :limit => 500
- t.column 'review_type', :string, :null => true, :limit => 10
- t.column 'status', :string, :null => true, :limit => 10
- t.column 'severity', :string, :null => true, :limit => 10
- t.column 'rule_failure_permanent_id', :integer, :null => true
- t.column 'resource_id', :integer, :null => true
- t.column 'resource_line', :integer, :null => true
- end
-
- create_table 'review_comments' do |t|
- t.column 'created_at', :datetime
- t.column 'updated_at', :datetime
- t.column 'review_id', :integer
- t.column 'user_id', :integer, :null => true
- t.column 'review_text', :text, :null => true
- end
-
- alter_to_big_primary_key('reviews')
- alter_to_big_primary_key('review_comments')
-
- end
-
-end
+# +# Sonar, entreprise quality control 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 +# + +# +# Sonar 2.8 +# +class CreateReview < ActiveRecord::Migration + + def self.up + create_table 'reviews' do |t| + t.column 'created_at', :datetime + t.column 'updated_at', :datetime + t.column 'user_id', :integer, :null => true + t.column 'assignee_id', :integer, :null => true + t.column 'title', :string, :null => true, :limit => 500 + t.column 'review_type', :string, :null => true, :limit => 10 + t.column 'status', :string, :null => true, :limit => 10 + t.column 'severity', :string, :null => true, :limit => 10 + t.column 'rule_failure_permanent_id', :integer, :null => true + t.column 'resource_id', :integer, :null => true + t.column 'resource_line', :integer, :null => true + end + + create_table 'review_comments' do |t| + t.column 'created_at', :datetime + t.column 'updated_at', :datetime + t.column 'review_id', :integer + t.column 'user_id', :integer, :null => true + t.column 'review_text', :text, :null => true + end + + alter_to_big_primary_key('reviews') + alter_to_big_primary_key('review_comments') + + end + +end diff --git a/start-mac-derby.sh b/start-mac-derby.sh index 5ed4ecb42ac..a26c7b10af0 100755 --- a/start-mac-derby.sh +++ b/start-mac-derby.sh @@ -1,4 +1,5 @@ #!/bin/sh + # # NOTE: sonar must be built # @@ -6,4 +7,3 @@ cd sonar-application/target/ unzip sonar-*.zip cd sonar-* bin/macosx-universal-64/sonar.sh console - |