]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2505 core components which write to database are disabled on dry runs
authorSimon Brandhof <simon.brandhof@gmail.com>
Wed, 15 Jun 2011 08:55:55 +0000 (10:55 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Wed, 15 Jun 2011 08:56:24 +0000 (10:56 +0200)
29 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AsynchronousMeasuresSensor.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CloseReviewsDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/VersionEventsSensor.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TendencyDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersister.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/PurgeRunner.java
sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionInstaller.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRun.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/Module.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExtensionInstaller.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java
sonar-batch/src/main/java/org/sonar/batch/components/PastViolationsLoader.java
sonar-batch/src/main/java/org/sonar/batch/index/ReadOnlyPersistenceManager.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java
sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionInstallerTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/DryRunTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectExtensionInstallerTest.java
sonar-batch/src/test/java/org/sonar/batch/phases/PhasesTest.java
sonar-core/src/main/java/org/sonar/core/NotDryRun.java [new file with mode: 0644]

index e3f1a8c8726415e4fcb600181f51718860a52418..3a23449aec931737d73e459a349fabf2817627e9 100644 (file)
@@ -22,11 +22,13 @@ package org.sonar.plugins.core.sensors;
 import org.sonar.api.batch.Phase;
 import org.sonar.api.batch.Sensor;
 import org.sonar.api.batch.SensorContext;
+import org.sonar.core.NotDryRun;
 import org.sonar.jpa.dao.AsyncMeasuresService;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.ResourceUtils;
 
+@NotDryRun
 @Phase(name = Phase.Name.PRE)
 public class AsynchronousMeasuresSensor implements Sensor {
 
index 49ee853d902d4c5412126e656c3083cba0f73f2a..f0fe71402de19fcb677ac574a06fcc1e55cefa25 100644 (file)
@@ -33,10 +33,12 @@ import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.ResourceUtils;
 import org.sonar.batch.index.ResourcePersister;
+import org.sonar.core.NotDryRun;
 
 /**
  * Decorator that currently only closes a review when its corresponding violation has been fixed.
  */
+@NotDryRun
 @DependsUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
 public class CloseReviewsDecorator implements Decorator {
 
index 555d53e80b2968850161c5713834b66585300751..21f9489dbce833e86275bf5a987fc333e545e5c7 100644 (file)
@@ -25,9 +25,11 @@ import org.sonar.api.batch.Event;
 import org.sonar.api.batch.Sensor;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.resources.Project;
+import org.sonar.core.NotDryRun;
 
 import java.util.Iterator;
 
+@NotDryRun
 public class VersionEventsSensor implements Sensor {
 
   private static final String SNAPSHOT_SUFFIX = "-SNAPSHOT";
index 78a988d6d16e36dfdb586d4d732bfc245dec6856..5686c6d4eccf89f219352f1ab483354dc8480d33 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.api.resources.Scopes;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.batch.components.PastSnapshot;
 import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.core.NotDryRun;
 
 import java.util.Arrays;
 import java.util.Date;
@@ -42,6 +43,7 @@ import java.util.Map;
 /**
  * @since 2.7
  */
+@NotDryRun
 @DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
 public final class NewCoverageFileAnalyzer implements Decorator {
 
index 5df64a2b139d54217a5332b0ece6a90103bcf606..358c3394edc77a6d5c7e8ccb93849ebb9116a0e7 100644 (file)
@@ -32,9 +32,11 @@ import org.sonar.api.rules.RulePriority;
 import org.sonar.api.rules.Violation;
 import org.sonar.batch.components.PastSnapshot;
 import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.core.NotDryRun;
 
 import java.util.*;
 
+@NotDryRun
 @DependsUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
 public class NewViolationsDecorator implements Decorator {
 
index 0758fdeb57d0c8049a7bebf27544e1b900a2506c..ade65afb788b3be99ff2bc48f81a232dee38cd01 100644 (file)
@@ -32,9 +32,11 @@ import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.Scopes;
 import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.core.NotDryRun;
 
 import java.util.List;
 
+@NotDryRun
 @DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
 public class TendencyDecorator implements Decorator {
 
index 092f59bed7a3350f88d8b3dd688648a6fac45244..889a9010d78086f02cbd6c02b07df7d93780e4d6 100644 (file)
@@ -28,9 +28,11 @@ import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.ResourceUtils;
 import org.sonar.batch.components.PastSnapshot;
 import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.core.NotDryRun;
 
 import java.util.List;
 
+@NotDryRun
 public final class TimeMachineConfigurationPersister implements Decorator {
 
   private TimeMachineConfiguration configuration;
index 9a5eac592ad7265fb9da11466c434f9eda9922c0..1fe3ec56cc1b347a23380e7119fb385a5cb83983 100644 (file)
@@ -30,11 +30,13 @@ import org.sonar.api.resources.Scopes;
 import org.sonar.batch.components.PastMeasuresLoader;
 import org.sonar.batch.components.PastSnapshot;
 import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.core.NotDryRun;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+@NotDryRun
 @DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
 public class VariationDecorator implements Decorator {
 
index 0126aad10453b763638af1ebbf2d5dc8ca2fb53a..b14e76496701e9ba0c3a9ddf056eaeaeefc394b4 100644 (file)
@@ -44,7 +44,9 @@ import org.sonar.batch.index.ViolationPersister;
 import com.google.common.collect.LinkedHashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Multimap;
+import org.sonar.core.NotDryRun;
 
+@NotDryRun
 @DependsUpon({ DecoratorBarriers.END_OF_VIOLATIONS_GENERATION, DecoratorBarriers.START_VIOLATION_TRACKING })
 @DependedUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
 public class ViolationPersisterDecorator implements Decorator {
index 3cfb209410da36be6fc03583f27c6ae3a78d9829..12542a55a22b434229e4cb16f72de1b12bdeda52 100644 (file)
@@ -27,10 +27,12 @@ import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.TimeProfiler;
+import org.sonar.core.NotDryRun;
 import org.sonar.plugins.dbcleaner.api.Purge;
 
 import javax.persistence.Query;
 
+@NotDryRun
 public final class PurgeRunner implements PostJob {
 
   private DatabaseSession session;
index add063534aa90c5675c265d82be03f4418451ec8..0ff9542667b0fb1657df586c4a0226ab10d53927 100644 (file)
@@ -29,7 +29,6 @@ import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Resource;
 import org.sonar.batch.index.DefaultIndex;
@@ -68,14 +67,14 @@ public class DefaultTimeMachine implements TimeMachine {
     Map<Integer, Metric> metricById = getMetricsById(query);
     List<Object[]> rows = execute(query, false, metricById.keySet());
     for (Object[] fields : rows) {
-      fields[1]=metricById.get(fields[1]);
+      fields[1] = metricById.get(fields[1]);
     }
     return rows;
   }
 
   protected List execute(TimeMachineQuery query, boolean selectAllFields, Set<Integer> metricIds) {
     Resource resource = query.getResource();
-    if (resource!=null && resource.getId()==null) {
+    if (resource != null && resource.getId() == null) {
       resource = index.getResource(query.getResource());
     }
     if (resource == null) {
index cee17e434d7fe133a09fe0c66342021013db1605..f91054793b8fd7b6ec177ae0fbc0f809a0e4d9cb 100644 (file)
@@ -34,10 +34,12 @@ public final class BatchExtensionInstaller implements BatchComponent {
 
   private BatchPluginRepository pluginRepository;
   private EnvironmentInformation environment;
+  private DryRun dryRun;
 
-  public BatchExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation environment) {
+  public BatchExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation environment, DryRun dryRun) {
     this.pluginRepository = pluginRepository;
     this.environment = environment;
+    this.dryRun = dryRun;
   }
 
   public void install(Module module) {
@@ -75,6 +77,7 @@ public final class BatchExtensionInstaller implements BatchComponent {
   void installExtension(Module module, Object extension) {
     if (ExtensionUtils.isBatchExtension(extension) &&
         ExtensionUtils.isSupportedEnvironment(extension, environment) &&
+        ExtensionUtils.checkDryRun(extension, dryRun.isEnabled()) &&
         ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_BATCH)) {
       if (ExtensionUtils.isType(extension, CoverageExtension.class)) {
         throw new IllegalArgumentException("Instantiation strategy " + InstantiationStrategy.PER_BATCH + " is not supported on CoverageExtension components: " + extension);
index 8081cda1366bca3ebc5fbd7ec4878e30e580f8f7..eb6c4552073ab9197ecad8b2514cd30837025682 100644 (file)
@@ -36,20 +36,33 @@ import org.sonar.jpa.dao.MeasuresDao;
  * Level-2 components. Connected to database.
  */
 public class BatchModule extends Module {
+
+  private final boolean dryRun;
+
+  public BatchModule(boolean dryRun) {
+    this.dryRun = dryRun;
+  }
+
   @Override
   protected void configure() {
     addComponent(ProjectTree.class);
     addComponent(DefaultResourceCreationLock.class);
     addComponent(DefaultIndex.class);
-    addComponent(DefaultPersistenceManager.class);
-    addComponent(DependencyPersister.class);
-    addComponent(EventPersister.class);
-    addComponent(LinkPersister.class);
-    addComponent(MeasurePersister.class);
-    addComponent(MemoryOptimizer.class);
-    addComponent(DefaultResourcePersister.class);
-    addComponent(SourcePersister.class);
-    addComponent(ViolationPersister.class);
+
+    if (dryRun) {
+      addComponent(ReadOnlyPersistenceManager.class);
+    } else {
+      addComponent(DefaultPersistenceManager.class);
+      addComponent(DependencyPersister.class);
+      addComponent(EventPersister.class);
+      addComponent(LinkPersister.class);
+      addComponent(MeasurePersister.class);
+      addComponent(MemoryOptimizer.class);
+      addComponent(DefaultResourcePersister.class);
+      addComponent(SourcePersister.class);
+      addComponent(ViolationPersister.class);
+    }
+
     addComponent(Plugins.class);
     addComponent(ServerHttpClient.class);
     addComponent(MeasuresDao.class);
@@ -87,7 +100,7 @@ public class BatchModule extends Module {
       analyze(subProject);
     }
 
-    Module projectComponents = installChild(new ProjectModule(project));
+    Module projectComponents = installChild(new ProjectModule(project, dryRun));
     try {
       projectComponents.start();
     } finally {
index fc09ef25dd0aa17ac589e72939faf1c59869ed94..6d0a84372b5f7950ffb0965dfd7c61471f0ac79f 100644 (file)
@@ -51,6 +51,7 @@ public class BootstrapModule extends Module {
   protected void configure() {
     addComponent(reactor);
     addComponent(configuration);
+    addComponent(DryRun.class);
     addComponent(ServerMetadata.class);// registered here because used by BootstrapClassLoader
     addComponent(TempDirectories.class);// registered here because used by BootstrapClassLoader
     addComponent(HttpDownloader.class);// registered here because used by BootstrapClassLoader
@@ -90,7 +91,8 @@ public class BootstrapModule extends Module {
   @Override
   protected void doStart() {
     addPlugins();
-    Module batchComponents = installChild(new BatchModule());
+    boolean dryRun = getComponent(DryRun.class).isEnabled();
+    Module batchComponents = installChild(new BatchModule(dryRun));
     batchComponents.start();
   }
 
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRun.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRun.java
new file mode 100644 (file)
index 0000000..0137602
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.bootstrap;
+
+import org.apache.commons.configuration.Configuration;
+
+public class DryRun {
+  private boolean enabled;
+
+  public DryRun(Configuration conf) {
+    enabled=conf.getBoolean("sonar.dryRun", Boolean.FALSE);
+  }
+
+  DryRun(boolean enabled) {
+    this.enabled = enabled;
+  }
+
+  public boolean isEnabled() {
+    return enabled;
+  }
+}
index 6214d8d4e53949ff7544a6570c710c828962ee6c..a1f6c0643f827eb1005859073994a5d90a1ba9bd 100644 (file)
@@ -23,9 +23,11 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.Extension;
 import org.sonar.api.batch.InstantiationStrategy;
+import org.sonar.api.batch.Purge;
 import org.sonar.api.batch.SupportedEnvironment;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.core.NotDryRun;
 
 public final class ExtensionUtils {
 
@@ -60,6 +62,10 @@ public final class ExtensionUtils {
     return false;
   }
 
+  static boolean checkDryRun(Object extension, boolean dryRun) {
+    return !dryRun || AnnotationUtils.getClassAnnotation(extension, NotDryRun.class)==null;
+  }
+
   static boolean isMavenExtensionOnly(Object extension) {
     Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass());
     SupportedEnvironment env = AnnotationUtils.getClassAnnotation(clazz, SupportedEnvironment.class);
index 0fab9682c7ba3ed347e9241cb65e868256b836ed..df9991e89a50e35ada10b51971d29d18c7a84b4c 100644 (file)
@@ -35,6 +35,7 @@ public abstract class Module {
 
   private MutablePicoContainer container;
 
+
   /**
    * @return this
    */
index 194d2f022edd5b95867830ef235a054b3d285369..0ec164f7ca412b7ad82fe86ce0744a9241320f66 100644 (file)
@@ -39,10 +39,12 @@ public final class ProjectExtensionInstaller implements BatchComponent {
 
   private BatchPluginRepository pluginRepository;
   private EnvironmentInformation environment;
+  private DryRun dryRun;
 
-  public ProjectExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation environment) {
+  public ProjectExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation environment, DryRun dryRun) {
     this.pluginRepository = pluginRepository;
     this.environment = environment;
+    this.dryRun = dryRun;
   }
 
   public void install(Module module, Project project) {
@@ -72,6 +74,7 @@ public final class ProjectExtensionInstaller implements BatchComponent {
     if (ExtensionUtils.isBatchExtension(extension) &&
         ExtensionUtils.isSupportedEnvironment(extension, environment) &&
         ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT) &&
+        ExtensionUtils.checkDryRun(extension, dryRun.isEnabled()) &&
         !isDeactivatedCoverageExtension(extension, project, pluginKey) &&
         !isMavenExtensionOnEmulatedMavenProject(extension, project)) {
       module.addComponent(extension);
index ae0c69aec40733bb051c75ee4d6d80661e4bf24d..d603c34a1df073780680b7d70618bcec053d566e 100644 (file)
@@ -23,9 +23,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.BatchExtensionDictionnary;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.Metrics;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
@@ -49,9 +46,11 @@ import java.util.Arrays;
 public class ProjectModule extends Module {
   private static final Logger LOG = LoggerFactory.getLogger(ProjectModule.class);
   private Project project;
+  private boolean dryRun;
 
-  public ProjectModule(Project project) {
+  public ProjectModule(Project project, boolean dryRun) {
     this.project = project;
+    this.dryRun = dryRun;
   }
 
   @Override
@@ -77,8 +76,12 @@ public class ProjectModule extends Module {
     addComponent(DaoFacade.class);
     addComponent(RulesDao.class);
 
-    // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
-    addComponent(getComponent(DefaultResourcePersister.class).getSnapshot(project));
+    if (!dryRun) {
+      // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
+      addComponent(getComponent(DefaultResourcePersister.class).getSnapshot(project));
+      addComponent(TimeMachineConfiguration.class);
+      addComponent(PastViolationsLoader.class);
+    }
     addComponent(org.sonar.api.database.daos.MeasuresDao.class);
     addComponent(ProfilesDao.class);
     addComponent(AsyncMeasuresDao.class);
@@ -91,8 +94,6 @@ public class ProjectModule extends Module {
     addComponent(ViolationFilters.class);
     addComponent(ResourceFilters.class);
     addComponent(DefaultModelFinder.class);
-    addComponent(TimeMachineConfiguration.class);
-    addComponent(PastViolationsLoader.class);
     addComponent(ProfileLoader.class, DefaultProfileLoader.class);
     addAdapter(new ProfileProvider());
   }
@@ -101,7 +102,7 @@ public class ProjectModule extends Module {
     addComponent(EventBus.class);
     addComponent(Phases.class);
     addComponent(PhasesTimeProfiler.class);
-    for (Class clazz : Phases.getPhaseClasses()) {
+    for (Class clazz : Phases.getPhaseClasses(dryRun)) {
       addComponent(clazz);
     }
   }
index 805a2b696e3ddbdc3e9a78bc1a0481a72c1f2580..6168ebca1994999d8e8084f5e6d44cb581a518a0 100644 (file)
@@ -27,10 +27,12 @@ import org.sonar.api.database.model.SnapshotSource;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.index.ResourcePersister;
+import org.sonar.core.NotDryRun;
 
 import java.util.Collections;
 import java.util.List;
 
+@NotDryRun
 public class PastViolationsLoader implements BatchExtension {
 
   private DatabaseSession session;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ReadOnlyPersistenceManager.java b/sonar-batch/src/main/java/org/sonar/batch/index/ReadOnlyPersistenceManager.java
new file mode 100644 (file)
index 0000000..7682a3d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.batch.Event;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectLink;
+import org.sonar.api.resources.Resource;
+
+import java.util.Collections;
+import java.util.List;
+
+public final class ReadOnlyPersistenceManager implements PersistenceManager {
+
+  public void clear() {
+  }
+
+  public void setDelayedMode(boolean b) {
+  }
+
+  public void dump() {
+  }
+
+  public void saveProject(Project project, Project parent) {
+  }
+
+  public Snapshot saveResource(Project project, Resource resource, Resource parent) {
+    return null;
+  }
+
+  public void setSource(Resource file, String source) {
+  }
+
+  public void saveMeasure(Resource resource, Measure measure) {
+  }
+
+  public Measure reloadMeasure(Measure measure) {
+    return measure;
+  }
+
+  public void saveDependency(Project project, Dependency dependency, Dependency parentDependency) {
+  }
+
+  public void saveLink(Project project, ProjectLink link) {
+  }
+
+  public void deleteLink(Project project, String key) {
+  }
+
+  public List<Event> getEvents(Resource resource) {
+    return Collections.emptyList();
+  }
+
+  public void deleteEvent(Event event) {
+  }
+
+  public void saveEvent(Resource resource, Event event) {
+  }
+}
index a9d69e72a23d6567648950d10b4b70f4593db829..d8a7506303d5cd9db8bfa0cf5a217e4ba918b5ee 100644 (file)
  */
 package org.sonar.batch.phases;
 
+import com.google.common.collect.Lists;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.resources.Project;
 import org.sonar.batch.events.EventBus;
 import org.sonar.batch.index.DefaultIndex;
 import org.sonar.batch.index.PersistenceManager;
 
-import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 
 public final class Phases {
 
-  public static Collection<Class> getPhaseClasses() {
-    return Arrays.<Class> asList(
-        DecoratorsExecutor.class, MavenPhaseExecutor.class, MavenPluginsConfigurator.class,
-        PostJobsExecutor.class, SensorsExecutor.class, UpdateStatusJob.class,
+  public static Collection<Class> getPhaseClasses(boolean dryRun) {
+    List<Class> classes = Lists.<Class>newArrayList(DecoratorsExecutor.class, MavenPhaseExecutor.class, MavenPluginsConfigurator.class,
+        PostJobsExecutor.class, SensorsExecutor.class,
         InitializersExecutor.class);
+    if (!dryRun) {
+      classes.add(UpdateStatusJob.class);
+    }
+    return classes;
   }
 
   private EventBus eventBus;
@@ -51,20 +55,29 @@ public final class Phases {
 
   public Phases(DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
                 MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
-                PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, UpdateStatusJob updateStatusJob,
+                PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
                 PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
-                EventBus eventBus) {
+                EventBus eventBus, UpdateStatusJob updateStatusJob) {
     this.decoratorsExecutor = decoratorsExecutor;
     this.mavenPhaseExecutor = mavenPhaseExecutor;
     this.mavenPluginsConfigurator = mavenPluginsConfigurator;
     this.postJobsExecutor = postJobsExecutor;
     this.initializersExecutor = initializersExecutor;
     this.sensorsExecutor = sensorsExecutor;
-    this.updateStatusJob = updateStatusJob;
     this.persistenceManager = persistenceManager;
     this.sensorContext = sensorContext;
     this.index = index;
     this.eventBus = eventBus;
+    this.updateStatusJob = updateStatusJob;
+  }
+
+  public Phases(DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
+                MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
+                PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
+                PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
+                EventBus eventBus) {
+    this(decoratorsExecutor, mavenPhaseExecutor, mavenPluginsConfigurator, initializersExecutor, postJobsExecutor,
+        sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null);
   }
 
   /**
@@ -83,7 +96,9 @@ public final class Phases {
     persistenceManager.setDelayedMode(false);
 
     if (project.isRoot()) {
-      updateStatusJob.execute();
+      if (updateStatusJob != null) {
+        updateStatusJob.execute();
+      }
       postJobsExecutor.execute(sensorContext);
     }
     cleanMemory();
index cc742bdc0d459e1a7527574b0dce9179b6040529..ea93e4992a739b808e65d25a80823c98ba07720d 100644 (file)
@@ -26,10 +26,12 @@ import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Scopes;
 import org.sonar.batch.ServerMetadata;
 import org.sonar.batch.index.ResourcePersister;
+import org.sonar.core.NotDryRun;
 
 import javax.persistence.Query;
 import java.util.List;
 
+@NotDryRun
 public class UpdateStatusJob implements BatchComponent {
 
   private DatabaseSession session;
index 4f81bd34294c7bb33cf4ef6924e4f0cc13500832..10c19e6d415bfdc78e8c7b7cdef730d7ba0c6172 100644 (file)
@@ -45,7 +45,7 @@ public class BatchExtensionInstallerTest {
       }
     }));
     Module module = new FakeModule().init();
-    BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"));
+    BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
     installer.install(module);
 
@@ -63,7 +63,7 @@ public class BatchExtensionInstallerTest {
       }
     }));
     Module module = new FakeModule().init();
-    BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"));
+    BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
     installer.install(module);
 
@@ -82,7 +82,7 @@ public class BatchExtensionInstallerTest {
       }
     }));
     Module module = new FakeModule().init();
-    BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"));
+    BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
     installer.install(module);
   }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DryRunTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DryRunTest.java
new file mode 100644 (file)
index 0000000..5b278b0
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.bootstrap;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.hamcrest.core.Is;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+
+public class DryRunTest {
+
+  @Test
+  public void shouldReadConfiguration() {
+    PropertiesConfiguration conf = new PropertiesConfiguration();
+    conf.setProperty("sonar.dryRun", "true");
+    assertThat(new DryRun(conf).isEnabled(), Is.is(true));
+
+    conf.setProperty("sonar.dryRun", "false");
+    assertThat(new DryRun(conf).isEnabled(), Is.is(false));
+  }
+
+  @Test
+  public void shouldNotEnableDryRunByDefault() {
+    PropertiesConfiguration conf = new PropertiesConfiguration();
+    assertThat(new DryRun(conf).isEnabled(), Is.is(false));
+  }
+}
index 2e6abe8621ca525228c55843f9881ad5b6f3461d..23cc30d560a37f2a7834c5b6a29b064d7f1ebfbc 100644 (file)
@@ -25,6 +25,7 @@ import org.sonar.api.ServerExtension;
 import org.sonar.api.batch.InstantiationStrategy;
 import org.sonar.api.batch.SupportedEnvironment;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.core.NotDryRun;
 
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertThat;
@@ -75,6 +76,18 @@ public class ExtensionUtilsTest {
     assertThat(ExtensionUtils.isMavenExtensionOnly(BuildToolService.class), is(false));
   }
 
+  @Test
+  public void shouldCheckDryRun() {
+    assertThat(ExtensionUtils.checkDryRun(BatchService.class, true), is(true));
+    assertThat(ExtensionUtils.checkDryRun(PersistentService.class, true), is(false));
+  }
+
+  @Test
+  public void shouldNotCheckDryRun() {
+    assertThat(ExtensionUtils.checkDryRun(BatchService.class, false), is(true));
+    assertThat(ExtensionUtils.checkDryRun(PersistentService.class, false), is(true));
+  }
+
   @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
   public static class BatchService implements BatchExtension {
 
@@ -102,4 +115,9 @@ public class ExtensionUtilsTest {
   public static class BuildToolService implements BatchExtension {
 
   }
+
+  @NotDryRun
+  public static class PersistentService implements BatchExtension {
+
+  }
 }
index b8020422a1535a74b6b078a1efbbbb2116d3416f..9e9fcd60fa64154bb021b15a883046460547a548 100644 (file)
@@ -66,7 +66,7 @@ public class ProjectExtensionInstallerTest {
     });
     when(pluginRepository.getPluginsByKey()).thenReturn(pluginsMap);
     Module module = new FakeModule().init();
-    ProjectExtensionInstaller installer = new ProjectExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"));
+    ProjectExtensionInstaller installer = new ProjectExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
     installer.install(module, new Project("foo"));
 
@@ -86,7 +86,7 @@ public class ProjectExtensionInstallerTest {
     });
     when(pluginRepository.getPluginsByKey()).thenReturn(pluginsMap);
     Module module = new FakeModule().init();
-    ProjectExtensionInstaller installer = new ProjectExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"));
+    ProjectExtensionInstaller installer = new ProjectExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
     installer.install(module, new Project("foo"));
 
index d14d30d7ae47733703b4aba5195e55ed9d2ffa6d..ae8a6d0b962baab8729dadd1fab983b0485aeea0 100644 (file)
@@ -28,6 +28,11 @@ public class PhasesTest {
 
   @Test
   public void shouldDefinePhaseClasses() {
-    assertThat(Phases.getPhaseClasses().size(), greaterThan(4));
+    assertThat(Phases.getPhaseClasses(false).size(), greaterThan(4));
+  }
+
+  @Test
+  public void someComponentsShouldBeDisabledOnDryRun() {
+    assertThat(Phases.getPhaseClasses(false).size(), greaterThan(Phases.getPhaseClasses(true).size()));
   }
 }
diff --git a/sonar-core/src/main/java/org/sonar/core/NotDryRun.java b/sonar-core/src/main/java/org/sonar/core/NotDryRun.java
new file mode 100644 (file)
index 0000000..46a5e23
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.core;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Disables component on dry runs.
+ * This annotation must be used by core modules only. It MUST not be used by external plugins.
+ * @since 2.9
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface NotDryRun {
+}