Pārlūkot izejas kodu

Fix crlf

tags/2.8
Evgeny Mandrikov pirms 13 gadiem
vecāks
revīzija
ee7b180068
34 mainītis faili ar 3594 papildinājumiem un 3594 dzēšanām
  1. 1
    1
      COPYING
  2. 1
    1
      deploy-docs.sh
  3. 71
    71
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewsDecorator.java
  4. 195
    195
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java
  5. 58
    58
      plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ReviewsDecoratorTest.java
  6. 52
    52
      plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ReviewsDecoratorTest/fixture.xml
  7. 1
    1
      quick-build.bat
  8. 1
    1
      quick-build.sh
  9. 175
    175
      sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
  10. 549
    549
      sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
  11. 88
    88
      sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java
  12. 238
    238
      sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
  13. 96
    96
      sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java
  14. 24
    24
      sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml
  15. 26
    26
      sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml
  16. 27
    27
      sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml
  17. 25
    25
      sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml
  18. 263
    263
      sonar-core/src/main/java/org/sonar/jpa/session/JpaDatabaseSession.java
  19. 159
    159
      sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java
  20. 182
    182
      sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
  21. 80
    80
      sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseSession.java
  22. 253
    253
      sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java
  23. 89
    89
      sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java
  24. 337
    337
      sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb
  25. 263
    263
      sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
  26. 72
    72
      sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
  27. 84
    84
      sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb
  28. 29
    29
      sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form.html.erb
  29. 27
    27
      sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form_comment.html.erb
  30. 65
    65
      sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_view.html.erb
  31. 4
    4
      sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_comment_result.js.rjs
  32. 4
    4
      sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_result.js.rjs
  33. 54
    54
      sonar-server/src/main/webapp/WEB-INF/db/migrate/191_create_review.rb
  34. 1
    1
      start-mac-derby.sh

+ 1
- 1
COPYING Parādīt failu

@@ -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/>

+ 1
- 1
deploy-docs.sh Parādīt failu

@@ -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'
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'

+ 71
- 71
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewsDecorator.java Parādīt failu

@@ -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();
}
}
}

+ 195
- 195
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java Parādīt failu

@@ -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();
}
}

+ 58
- 58
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ReviewsDecoratorTest.java Parādīt failu

@@ -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");
}
}

+ 52
- 52
plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ReviewsDecoratorTest/fixture.xml Parādīt failu

@@ -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>

+ 1
- 1
quick-build.bat Parādīt failu

@@ -1,2 +1,2 @@
set MAVEN_OPTS=-Xmx768m -XX:MaxPermSize=256m
mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev

+ 1
- 1
quick-build.sh Parādīt failu

@@ -9,4 +9,4 @@ echo ''
echo '-------------------------------------------------'

# it is recommended to use maven 3 for faster builds
mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev

+ 175
- 175
sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java Parādīt failu

@@ -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);
}
}

+ 549
- 549
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 88
- 88
sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java Parādīt failu

@@ -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;
}
}

+ 238
- 238
sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java Parādīt failu

@@ -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());
}
}

+ 96
- 96
sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java Parādīt failu

@@ -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");
}
}

+ 24
- 24
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml Parādīt failu

@@ -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>

+ 26
- 26
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml Parādīt failu

@@ -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>

+ 27
- 27
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml Parādīt failu

@@ -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>

+ 25
- 25
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml Parādīt failu

@@ -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>

+ 263
- 263
sonar-core/src/main/java/org/sonar/jpa/session/JpaDatabaseSession.java Parādīt failu

@@ -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 ");
}
}
}
}

+ 159
- 159
sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java Parādīt failu

@@ -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);
}

+ 182
- 182
sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java Parādīt failu

@@ -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);
}
}

+ 80
- 80
sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseSession.java Parādīt failu

@@ -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);
}

+ 253
- 253
sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java Parādīt failu

@@ -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);
}
}

+ 89
- 89
sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java Parādīt failu

@@ -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;
}
}

+ 337
- 337
sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb Parādīt failu

@@ -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

+ 263
- 263
sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb Parādīt failu

@@ -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

+ 72
- 72
sonar-server/src/main/webapp/WEB-INF/app/models/review.rb Parādīt failu

@@ -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

+ 84
- 84
sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb Parādīt failu

@@ -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

+ 29
- 29
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form.html.erb Parādīt failu

@@ -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" } -%>
&nbsp;&nbsp;
<a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a>
<% if @review.review_type == "comments" %>
&nbsp;&nbsp;
<%= 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" } -%>
&nbsp;&nbsp;
<a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a>
<% if @review.review_type == "comments" %>
&nbsp;&nbsp;
<%= check_box_tag "assign_to_me", "me", true -%> Assign to me
<% end %>
</div>
</div class="clear"></div>
<% end %>

+ 27
- 27
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form_comment.html.erb Parādīt failu

@@ -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" } %>
&nbsp;&nbsp;
<%= 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 } %>
&nbsp;&nbsp;
<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" } %>
&nbsp;&nbsp;
<%= 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 } %>
&nbsp;&nbsp;
<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 %>

+ 65
- 65
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_view.html.erb Parādīt failu

@@ -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()" -%>
&nbsp;
<% 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()" -%>
&nbsp;
<% 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>

+ 4
- 4
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_comment_result.js.rjs Parādīt failu

@@ -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

+ 4
- 4
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_result.js.rjs Parādīt failu

@@ -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

+ 54
- 54
sonar-server/src/main/webapp/WEB-INF/db/migrate/191_create_review.rb Parādīt failu

@@ -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

+ 1
- 1
start-mac-derby.sh Parādīt failu

@@ -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


Notiek ielāde…
Atcelt
Saglabāt