@@ -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/> |
@@ -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' |
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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,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 |
@@ -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 |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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> |
@@ -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> |
@@ -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> |
@@ -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> |
@@ -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 "); | |||
} | |||
} | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -1,30 +1,30 @@ | |||
<% form_for :review, @review do |f| %> | |||
<%= f.hidden_field :rule_failure_permanent_id -%> | |||
<%= f.hidden_field :review_type -%> | |||
<% if @review.review_type == "f-positive" %> | |||
<b>Reason for flagging this violation as a false-positive:</b> | |||
<% end %> | |||
<%= text_area :review_comment, :review_text, | |||
:id => "reviewText", :rows => 8, | |||
:style => "width:100%", :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" -%> | |||
<br/> | |||
<div> | |||
<% | |||
if @review.review_type == "comments" | |||
button_text = "Post review" | |||
else | |||
button_text = "Switch-off violation" | |||
end | |||
%> | |||
<%= submit_to_remote "submit_btn", button_text, :url => { :action => 'create' }, :html => { :id => "submit_btn", :disabled => "true" } -%> | |||
| |||
<a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a> | |||
<% if @review.review_type == "comments" %> | |||
| |||
<%= check_box_tag "assign_to_me", "me", true -%> Assign to me | |||
<% end %> | |||
</div> | |||
</div class="clear"></div> | |||
<% form_for :review, @review do |f| %> | |||
<%= f.hidden_field :rule_failure_permanent_id -%> | |||
<%= f.hidden_field :review_type -%> | |||
<% if @review.review_type == "f-positive" %> | |||
<b>Reason for flagging this violation as a false-positive:</b> | |||
<% end %> | |||
<%= text_area :review_comment, :review_text, | |||
:id => "reviewText", :rows => 8, | |||
:style => "width:100%", :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" -%> | |||
<br/> | |||
<div> | |||
<% | |||
if @review.review_type == "comments" | |||
button_text = "Post review" | |||
else | |||
button_text = "Switch-off violation" | |||
end | |||
%> | |||
<%= submit_to_remote "submit_btn", button_text, :url => { :action => 'create' }, :html => { :id => "submit_btn", :disabled => "true" } -%> | |||
| |||
<a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a> | |||
<% if @review.review_type == "comments" %> | |||
| |||
<%= check_box_tag "assign_to_me", "me", true -%> Assign to me | |||
<% end %> | |||
</div> | |||
</div class="clear"></div> | |||
<% end %> |
@@ -1,28 +1,28 @@ | |||
<% form_for :review_comment, @review_comment do |f| %> | |||
<%= f.hidden_field :review_id %> | |||
<%= f.text_area :review_text, :rows => 8, | |||
:id => "commentText" + @rule_failure_permanent_id.to_s, | |||
:style => "width:100%", | |||
:onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" %> | |||
<br/> | |||
<% if @update_comment %> | |||
<%= submit_to_remote 'submit_btn', 'Update comment', | |||
:url => { :action => 'update_comment', | |||
:rule_failure_permanent_id => @rule_failure_permanent_id }, | |||
:html => { :id => "submit_btn" } %> | |||
| |||
<%= link_to_remote 'Cancel', | |||
:url => { :action => 'display_violation', | |||
:rule_failure_permanent_id => @rule_failure_permanent_id }, | |||
:update => "vId" + @rule_failure_permanent_id.to_s %> | |||
<% else %> | |||
<%= submit_to_remote 'submit_btn', 'Post comment', | |||
:url => { :action => 'create_comment', | |||
:rule_failure_permanent_id => @rule_failure_permanent_id }, | |||
:html => { :id => "submit_btn", :disabled => true } %> | |||
| |||
<a onclick="$('reviewForm<%= @rule_failure_permanent_id.to_s -%>').style.display='none'; $('commentAction<%= @rule_failure_permanent_id.to_s -%>').style.display='';" href="#">Cancel</a> | |||
<% end %> | |||
<% form_for :review_comment, @review_comment do |f| %> | |||
<%= f.hidden_field :review_id %> | |||
<%= f.text_area :review_text, :rows => 8, | |||
:id => "commentText" + @rule_failure_permanent_id.to_s, | |||
:style => "width:100%", | |||
:onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" %> | |||
<br/> | |||
<% if @update_comment %> | |||
<%= submit_to_remote 'submit_btn', 'Update comment', | |||
:url => { :action => 'update_comment', | |||
:rule_failure_permanent_id => @rule_failure_permanent_id }, | |||
:html => { :id => "submit_btn" } %> | |||
| |||
<%= link_to_remote 'Cancel', | |||
:url => { :action => 'display_violation', | |||
:rule_failure_permanent_id => @rule_failure_permanent_id }, | |||
:update => "vId" + @rule_failure_permanent_id.to_s %> | |||
<% else %> | |||
<%= submit_to_remote 'submit_btn', 'Post comment', | |||
:url => { :action => 'create_comment', | |||
:rule_failure_permanent_id => @rule_failure_permanent_id }, | |||
:html => { :id => "submit_btn", :disabled => true } %> | |||
| |||
<a onclick="$('reviewForm<%= @rule_failure_permanent_id.to_s -%>').style.display='none'; $('commentAction<%= @rule_failure_permanent_id.to_s -%>').style.display='';" href="#">Cancel</a> | |||
<% end %> | |||
<% end %> |
@@ -1,65 +1,65 @@ | |||
<div id="review<%= review.id -%>"> | |||
<div> | |||
<b>Review #<%= review.id -%> - <%= h(review.title) -%></b> | |||
<br/> | |||
<% if review.assignee %> | |||
<i>Assigned to <%= h(review.assignee.name) -%></i> | |||
<% end %> | |||
</div> | |||
<div style="margin-top: 10px; margin-left: 20px"> | |||
<% unless review.review_comments.blank? | |||
last_comment = review.review_comments.last | |||
review.review_comments.each do |review_comment| | |||
%> | |||
<table style="width:100%; margin-bottom: 3px"> | |||
<tr style="border: solid 1px grey; background-color: #F7F7F7"> | |||
<td style="width:180px; vertical-align:top; padding: 2px 2px 2px 10px; font-weight: bold"> | |||
<%= image_tag("user.png") -%> <b><%= h(review_comment.user.name) -%></b> | |||
</td> | |||
<td style="vertical-align: top; padding: 2px 10px 2px 2px; color: grey; text-align: right; font-style: italic"> | |||
<%= l review_comment.created_at -%> | |||
</td> | |||
</tr> | |||
<tr style="border: solid 1px grey;"> | |||
<td colspan="2" style="padding: 5px;"> | |||
<% if review_comment == last_comment %> | |||
<div id="lastComment<%= review.id -%>"> | |||
<%= h(review_comment.review_text) -%> | |||
</div> | |||
<% else %> | |||
<%= h(review_comment.review_text) -%> | |||
<% end %> | |||
</td> | |||
</tr> | |||
</table> | |||
<% | |||
end | |||
end | |||
%> | |||
<% if current_user %> | |||
<div style="text-align: right; padding: 5px"> | |||
<% if current_user.id == review.review_comments.last.user_id %> | |||
<%= image_tag("pencil.png") -%> | |||
<%= link_to_remote "Edit my last comment", | |||
:url => { :controller => "reviews", :action => "form_comment", | |||
:review_id => review.id, | |||
:rule_failure_permanent_id => review.rule_failure_permanent_id, | |||
:review_text => review.review_comments.last.review_text, | |||
:update_comment => "true" }, | |||
:update => "lastComment" + review.id.to_s, | |||
:complete => "$('commentText" + review.id.to_s + "').focus()" -%> | |||
| |||
<% end %> | |||
<%= image_tag("pencil.png") -%> | |||
<%= link_to_remote "Add a new comment", | |||
:url => { :controller => "reviews", :action => "form_comment", :review_id => review.id, :rule_failure_permanent_id => review.rule_failure_permanent_id }, | |||
:update => "createComment" + review.id.to_s, | |||
:complete => "$('commentText" + review.id.to_s + "').focus()" -%> | |||
</div> | |||
<div id="createComment<%= review.id -%>"></div> | |||
<% end %> | |||
</div> | |||
</div> | |||
<div id="review<%= review.id -%>"> | |||
<div> | |||
<b>Review #<%= review.id -%> - <%= h(review.title) -%></b> | |||
<br/> | |||
<% if review.assignee %> | |||
<i>Assigned to <%= h(review.assignee.name) -%></i> | |||
<% end %> | |||
</div> | |||
<div style="margin-top: 10px; margin-left: 20px"> | |||
<% unless review.review_comments.blank? | |||
last_comment = review.review_comments.last | |||
review.review_comments.each do |review_comment| | |||
%> | |||
<table style="width:100%; margin-bottom: 3px"> | |||
<tr style="border: solid 1px grey; background-color: #F7F7F7"> | |||
<td style="width:180px; vertical-align:top; padding: 2px 2px 2px 10px; font-weight: bold"> | |||
<%= image_tag("user.png") -%> <b><%= h(review_comment.user.name) -%></b> | |||
</td> | |||
<td style="vertical-align: top; padding: 2px 10px 2px 2px; color: grey; text-align: right; font-style: italic"> | |||
<%= l review_comment.created_at -%> | |||
</td> | |||
</tr> | |||
<tr style="border: solid 1px grey;"> | |||
<td colspan="2" style="padding: 5px;"> | |||
<% if review_comment == last_comment %> | |||
<div id="lastComment<%= review.id -%>"> | |||
<%= h(review_comment.review_text) -%> | |||
</div> | |||
<% else %> | |||
<%= h(review_comment.review_text) -%> | |||
<% end %> | |||
</td> | |||
</tr> | |||
</table> | |||
<% | |||
end | |||
end | |||
%> | |||
<% if current_user %> | |||
<div style="text-align: right; padding: 5px"> | |||
<% if current_user.id == review.review_comments.last.user_id %> | |||
<%= image_tag("pencil.png") -%> | |||
<%= link_to_remote "Edit my last comment", | |||
:url => { :controller => "reviews", :action => "form_comment", | |||
:review_id => review.id, | |||
:rule_failure_permanent_id => review.rule_failure_permanent_id, | |||
:review_text => review.review_comments.last.review_text, | |||
:update_comment => "true" }, | |||
:update => "lastComment" + review.id.to_s, | |||
:complete => "$('commentText" + review.id.to_s + "').focus()" -%> | |||
| |||
<% end %> | |||
<%= image_tag("pencil.png") -%> | |||
<%= link_to_remote "Add a new comment", | |||
:url => { :controller => "reviews", :action => "form_comment", :review_id => review.id, :rule_failure_permanent_id => review.rule_failure_permanent_id }, | |||
:update => "createComment" + review.id.to_s, | |||
:complete => "$('commentText" + review.id.to_s + "').focus()" -%> | |||
</div> | |||
<div id="createComment<%= review.id -%>"></div> | |||
<% end %> | |||
</div> | |||
</div> |
@@ -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 |
@@ -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 |
@@ -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,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 | |||