]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3895 fix compatibility of dry-run mode with ProjectBuilder extensions
authorSimon Brandhof <simon.brandhof@gmail.com>
Wed, 31 Oct 2012 17:50:40 +0000 (18:50 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Wed, 31 Oct 2012 17:52:54 +0000 (18:52 +0100)
47 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/DefaultResourceTypes.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/batch/IndexProjectPostJob.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewWorkflowDecorator.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/AbstractNewCoverageFileAnalyzer.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/ViolationPersisterDecorator.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/ProjectPurgePostJob.java
sonar-batch/src/main/java/org/sonar/batch/DefaultResourceCreationLock.java
sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactory.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutor.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRun.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcDriverHolder.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcLeakPrevention.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/MetricProvider.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectReactorReady.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java
sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java
sonar-batch/src/test/java/org/sonar/batch/DefaultResourceCreationLockTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactoryTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchModuleTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutorTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/PluginDownloaderTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectReactorReadyTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
sonar-batch/src/test/java/org/sonar/batch/local/DryRunDatabaseTest.java
sonar-core/src/main/java/org/sonar/core/NotDryRun.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/DryRunIncompatible.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Metrics.java
sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceTypeTree.java

index 4dfb6d301aee41bd2006062dba8453e21682995b..e2b9328d31fcf0a2d7d7decb3bd408ce8bb8a62e 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypeTree;
 
-@InstantiationStrategy(InstantiationStrategy.BATCH)
+@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 public final class DefaultResourceTypes extends ExtensionProvider implements BatchExtension, ServerExtension {
   @Override
   public ResourceTypeTree provide() {
index 1b3186ee047a4dd9070b1fa9e206d1a99f2156b4..9e9c79948e0fa6614436b939e03b54c4967db6aa 100644 (file)
  */
 package org.sonar.plugins.core.batch;
 
+import org.sonar.api.batch.DryRunIncompatible;
 import org.sonar.api.batch.PostJob;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.resources.Project;
-import org.sonar.core.NotDryRun;
 import org.sonar.core.resource.ResourceIndexerDao;
 
 /**
  * @since 2.13
  */
-@NotDryRun
+@DryRunIncompatible
 public class IndexProjectPostJob implements PostJob {
   private ResourceIndexerDao indexer;
 
index b5195812e8e9f45bbd493419b30d2333d6ecf7b5..16f4a37bdbcca250e3921c87c6e178705266c7fe 100644 (file)
@@ -34,14 +34,13 @@ import org.sonar.api.resources.ResourceUtils;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.violations.ViolationQuery;
 import org.sonar.batch.index.ResourcePersister;
-import org.sonar.core.NotDryRun;
 import org.sonar.core.review.ReviewDao;
 import org.sonar.core.review.ReviewDto;
 
 import javax.annotation.Nullable;
 import java.util.*;
 
-@NotDryRun
+@DryRunIncompatible
 @DependsUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
 @DependedUpon(ReviewWorkflowDecorator.END_OF_REVIEWS_UPDATES)
 public class ReviewWorkflowDecorator implements Decorator {
index 0c4825fc77a9a700b23afa2b83ce2a1de37ef7f0..dabbbb682dcee17faca63e04ea35e2e8c0fe3abd 100644 (file)
 package org.sonar.plugins.core.sensors;
 
 import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.DryRunIncompatible;
 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
+@DryRunIncompatible
 public class VersionEventsSensor implements Sensor {
 
   public boolean shouldExecuteOnProject(Project project) {
index 411fd0ac690c14d2caf4d033f8f1f8b154158b2a..d007f5fa8cdd7561df535a2eef5e8c68006c9c7f 100644 (file)
@@ -33,7 +33,6 @@ 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;
@@ -43,7 +42,7 @@ import java.util.Map;
 /**
  * @since 2.7
  */
-@NotDryRun
+@DryRunIncompatible
 @DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
 public abstract class AbstractNewCoverageFileAnalyzer implements Decorator {
 
index 046520fea32a3bde3f54d140789c03c919bdb717..e5046a5f2f10fb801ee668e148f5b9496e2a66cc 100644 (file)
@@ -32,11 +32,10 @@ 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
+@DryRunIncompatible
 @DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
 public class TendencyDecorator implements Decorator {
 
index 213d8d631934d3b5e43fccfd6ae0489aa60bfce6..77b3d874175b37e4c1e95fc2321ff0c3a3b02e84 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.plugins.core.timemachine;
 
 import org.sonar.api.batch.Decorator;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.batch.DryRunIncompatible;
 import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Project;
@@ -28,11 +29,10 @@ 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
+@DryRunIncompatible
 public final class TimeMachineConfigurationPersister implements Decorator {
 
   private TimeMachineConfiguration configuration;
index 5a610cbc539fe2a64b5fb8b640e1b47039487f07..f4801867d279d94c7036dc4d0b543b54e4d7f29f 100644 (file)
@@ -30,11 +30,10 @@ import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.violations.ViolationQuery;
 import org.sonar.batch.index.ResourcePersister;
-import org.sonar.core.NotDryRun;
 
 import java.util.List;
 
-@NotDryRun
+@DryRunIncompatible
 @DependsUpon({ DecoratorBarriers.END_OF_VIOLATION_TRACKING, DecoratorBarriers.START_VIOLATION_PERSISTENCE })
 @DependedUpon(DecoratorBarriers.END_OF_VIOLATION_PERSISTENCE)
 public class ViolationPersisterDecorator implements Decorator {
index b844c588f6cf042e042f9a15a3c60983bd1587a2..c092927f4bcf87b843cdf6791110c13a5e40ea6a 100644 (file)
  */
 package org.sonar.plugins.dbcleaner;
 
+import org.sonar.api.batch.DryRunIncompatible;
 import org.sonar.api.batch.PostJob;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.resources.Project;
-import org.sonar.core.NotDryRun;
 import org.sonar.plugins.dbcleaner.api.PurgeTask;
 
-@NotDryRun
+@DryRunIncompatible
 public class ProjectPurgePostJob implements PostJob {
 
   private PurgeTask purgeTask;
index bcb4558acca2235a9e10285fa4fd2381b6eb5753..8b1151f9e229051e7e5545ded51d1b702efd0e68 100644 (file)
@@ -19,8 +19,8 @@
  */
 package org.sonar.batch;
 
-import org.apache.commons.configuration.Configuration;
 import org.sonar.api.batch.ResourceCreationLock;
+import org.sonar.api.config.Settings;
 
 /**
  * This lock is used to ensure that Sonar resources (files, packages, directories) are not created by buggy plugins
@@ -31,13 +31,10 @@ import org.sonar.api.batch.ResourceCreationLock;
 public final class DefaultResourceCreationLock implements ResourceCreationLock {
 
   private boolean locked = false;
-  private boolean failWhenLocked=false;
+  private boolean failWhenLocked = false;
 
-  public DefaultResourceCreationLock() {
-  }
-
-  public DefaultResourceCreationLock(Configuration configuration) {
-    this.failWhenLocked = configuration.getBoolean("sonar.hardIndexLock", false);
+  public DefaultResourceCreationLock(Settings settings) {
+    this.failWhenLocked = settings.getBoolean("sonar.hardIndexLock");
   }
 
   public boolean isLocked() {
index 6e13d83e527de1daf93b2a15b30ecbd054e77863..b2317a2e8120facabbdc3e4826c5e8b779665b51 100644 (file)
@@ -25,6 +25,7 @@ import org.apache.commons.lang.ObjectUtils;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.resources.Project;
+import org.sonar.batch.bootstrap.ProjectReactorReady;
 
 import java.util.List;
 import java.util.Map;
@@ -38,15 +39,12 @@ public class ProjectTree {
   private Map<ProjectDefinition, Project> projectsByDef;
 
   public ProjectTree(ProjectReactor projectReactor,
-                     ProjectConfigurator projectConfigurator) {
+                     ProjectConfigurator projectConfigurator,
+                     ProjectReactorReady reactorReady) {
     this.projectReactor = projectReactor;
     this.configurator = projectConfigurator;
   }
 
-  ProjectTree(ProjectConfigurator configurator) {
-    this.configurator = configurator;
-  }
-
   public void start() {
     doStart(projectReactor.getProjects());
   }
index 0ed7b77a24c7f999bfdb034d26a087438126ca66..9171f213788849b9343a19c5a1f63c29e731f3d0 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.batch.bootstrap;
 
 import org.sonar.api.config.Settings;
+import org.sonar.batch.local.DryRunDatabase;
 import org.sonar.core.persistence.DefaultDatabase;
 
 import java.util.Properties;
@@ -29,9 +30,14 @@ import java.util.Properties;
  */
 public class BatchDatabase extends DefaultDatabase {
 
-  // the dependency on JdbcDriverHolder is required to be sure that the JDBC driver
-  // has been downloaded and injected into classloader
-  public BatchDatabase(Settings settings, JdbcDriverHolder jdbcDriverHolder) {
+  public BatchDatabase(Settings settings,
+                       // The dependency on JdbcDriverHolder is required to be sure that the JDBC driver
+                       // has been downloaded and injected into classloader
+                       JdbcDriverHolder jdbcDriverHolder,
+
+                       // The dependency on DryRunDatabase is required to be sure that the dryRun mode
+                       // changed settings
+                       DryRunDatabase dryRun) {
     super(settings);
   }
 
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactory.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactory.java
new file mode 100644 (file)
index 0000000..7196a9c
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.sonar.api.database.DatabaseSession;
+import org.sonar.jpa.session.DatabaseSessionFactory;
+
+public class BatchDatabaseSessionFactory implements DatabaseSessionFactory {
+
+  private DatabaseSession session;
+
+  public BatchDatabaseSessionFactory(DatabaseSession session) {
+    this.session = session;
+  }
+
+  public DatabaseSession getSession() {
+    return session;
+  }
+
+  public void clear() {
+  }
+}
index e005e4f948f0bcc6c80d0c4203099c6c7ee68500..590d503bcf15bfc9624558265d0647fff267b438 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.batch.bootstrap;
 
 import org.sonar.api.batch.InstantiationStrategy;
+import org.sonar.api.config.EmailSettings;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.batch.DefaultFileLinesContextFactory;
@@ -33,6 +34,7 @@ import org.sonar.batch.components.PastSnapshotFinderByDays;
 import org.sonar.batch.components.PastSnapshotFinderByPreviousAnalysis;
 import org.sonar.batch.components.PastSnapshotFinderByPreviousVersion;
 import org.sonar.batch.components.PastSnapshotFinderByVersion;
+import org.sonar.batch.config.BatchDatabaseSettingsLoader;
 import org.sonar.batch.index.DefaultIndex;
 import org.sonar.batch.index.DefaultPersistenceManager;
 import org.sonar.batch.index.DefaultResourcePersister;
@@ -42,11 +44,19 @@ import org.sonar.batch.index.LinkPersister;
 import org.sonar.batch.index.MeasurePersister;
 import org.sonar.batch.index.MemoryOptimizer;
 import org.sonar.batch.index.SourcePersister;
+import org.sonar.batch.local.DryRunDatabase;
+import org.sonar.core.i18n.I18nManager;
+import org.sonar.core.i18n.RuleI18nManager;
 import org.sonar.core.metric.CacheMetricFinder;
 import org.sonar.core.notification.DefaultNotificationManager;
+import org.sonar.core.persistence.DaoUtils;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.rule.CacheRuleFinder;
 import org.sonar.core.user.DefaultUserFinder;
 import org.sonar.jpa.dao.MeasuresDao;
+import org.sonar.jpa.session.DefaultDatabaseConnector;
+import org.sonar.jpa.session.JpaDatabaseSession;
 
 /**
  * Level-2 components. Connected to database.
@@ -55,6 +65,17 @@ public class BatchModule extends Module {
 
   @Override
   protected void configure() {
+    registerCoreComponents();
+    registerDatabaseComponents();
+    registerBatchExtensions();
+  }
+
+  private void registerCoreComponents() {
+    container.addSingleton(EmailSettings.class);
+    container.addSingleton(I18nManager.class);
+    container.addSingleton(RuleI18nManager.class);
+    container.addSingleton(ProjectExclusions.class);
+    container.addSingleton(ProjectReactorReady.class);
     container.addSingleton(ProjectTree.class);
     container.addSingleton(ProjectConfigurator.class);
     container.addSingleton(DefaultResourceCreationLock.class);
@@ -82,12 +103,29 @@ public class BatchModule extends Module {
     container.addSingleton(DefaultUserFinder.class);
     container.addSingleton(ResourceTypes.class);
     container.addSingleton(MetricProvider.class);
-    addBatchExtensions();
   }
 
-  private void addBatchExtensions() {
+  private void registerDatabaseComponents() {
+    container.addSingleton(JdbcDriverHolder.class);
+    container.addSingleton(DryRunDatabase.class);
+    container.addSingleton(BatchDatabase.class);
+    container.addSingleton(MyBatis.class);
+    container.addSingleton(DatabaseVersion.class);
+    container.addSingleton(DatabaseBatchCompatibility.class);
+    for (Class daoClass : DaoUtils.getDaoClasses()) {
+      container.addSingleton(daoClass);
+    }
+
+    // hibernate
+    container.addSingleton(DefaultDatabaseConnector.class);
+    container.addSingleton(JpaDatabaseSession.class);
+    container.addSingleton(BatchDatabaseSessionFactory.class);
+    container.addSingleton(BatchDatabaseSettingsLoader.class);
+  }
+
+  private void registerBatchExtensions() {
     ExtensionInstaller installer = container.getComponentByType(ExtensionInstaller.class);
-    installer.install(container, InstantiationStrategy.BATCH);
+    installer.install(container, InstantiationStrategy.PER_BATCH);
   }
 
   @Override
index 2adca6754bb08d8c9f31ef6709a67b9008f7d27f..d0674039a48a7abf7e5afbcb42a28f952d9b1687 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.api.Plugin;
 import org.sonar.api.config.Settings;
 import org.sonar.api.platform.PluginMetadata;
 import org.sonar.api.platform.PluginRepository;
+import org.sonar.batch.config.BootstrapSettings;
 import org.sonar.core.plugins.PluginClassloaders;
 import org.sonar.core.plugins.PluginInstaller;
 import org.sonar.core.plugins.RemotePlugin;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutor.java
deleted file mode 100644 (file)
index 6fc42e4..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 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.slf4j.LoggerFactory;
-import org.sonar.api.batch.InstantiationStrategy;
-import org.sonar.api.platform.ComponentContainer;
-
-public class BootstrapExtensionExecutor {
-
-  private ComponentContainer container;
-  private ExtensionInstaller installer;
-
-  public BootstrapExtensionExecutor(ComponentContainer container, ExtensionInstaller installer) {
-    this.container = container;
-    this.installer = installer;
-  }
-
-  public void start() {
-    LoggerFactory.getLogger(BootstrapExtensionExecutor.class).debug("Execute bootstrap extensions");
-    ComponentContainer childContainer = container.createChild();
-    installer.install(childContainer, InstantiationStrategy.BOOTSTRAP);
-    childContainer.addSingleton(ProjectExclusions.class);
-    childContainer.startComponents();
-    childContainer.stopComponents();
-    container.removeChild();
-  }
-}
index bc6f746351f1c246b26811f1b6412022a51e07a1..bff8f081095b6edfa20a326c2553ce1c35a6db4e 100644 (file)
@@ -21,25 +21,13 @@ package org.sonar.batch.bootstrap;
 
 import org.apache.commons.configuration.PropertiesConfiguration;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.config.EmailSettings;
 import org.sonar.api.utils.HttpDownloader;
 import org.sonar.api.utils.UriReader;
 import org.sonar.batch.FakeMavenPluginExecutor;
 import org.sonar.batch.MavenPluginExecutor;
 import org.sonar.batch.ServerMetadata;
-import org.sonar.batch.config.BatchDatabaseSettingsLoader;
 import org.sonar.batch.config.BootstrapSettings;
-import org.sonar.batch.local.DryRunDatabase;
-import org.sonar.batch.local.DryRunExporter;
 import org.sonar.core.config.Logback;
-import org.sonar.core.i18n.I18nManager;
-import org.sonar.core.i18n.RuleI18nManager;
-import org.sonar.core.persistence.DaoUtils;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.jpa.session.DatabaseSessionProvider;
-import org.sonar.jpa.session.DefaultDatabaseConnector;
-import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
 import org.sonar.wsclient.Sonar;
 
 /**
@@ -72,40 +60,14 @@ public class BootstrapModule extends Module {
     container.addSingleton(HttpDownloader.class);
     container.addSingleton(UriReader.class);
     container.addSingleton(PluginDownloader.class);
-    container.addSingleton(EmailSettings.class);
-    container.addSingleton(I18nManager.class);
-    container.addSingleton(RuleI18nManager.class);
     for (Object component : boostrapperComponents) {
       if (component != null) {
         container.addSingleton(component);
       }
     }
-    container.addSingleton(BootstrapExtensionExecutor.class);
     if (!isMavenPluginExecutorRegistered()) {
       container.addSingleton(FakeMavenPluginExecutor.class);
     }
-    addDatabaseComponents();
-  }
-
-  private void addDatabaseComponents() {
-    container.addSingleton(JdbcDriverHolder.class);
-    container.addSingleton(DryRunDatabase.class);
-
-    // mybatis
-    container.addSingleton(BatchDatabase.class);
-    container.addSingleton(MyBatis.class);
-    container.addSingleton(DatabaseVersion.class);
-    container.addSingleton(DatabaseBatchCompatibility.class);
-    for (Class daoClass : DaoUtils.getDaoClasses()) {
-      container.addSingleton(daoClass);
-    }
-
-    // hibernate
-    container.addSingleton(DefaultDatabaseConnector.class);
-    container.addSingleton(ThreadLocalDatabaseSessionFactory.class);
-    container.addPicoAdapter(new DatabaseSessionProvider());
-
-    container.addSingleton(BatchDatabaseSettingsLoader.class);
   }
 
   boolean isMavenPluginExecutorRegistered() {
index ebebfee9b69d3b4df94c8d0806aad95c8fe65826..531f2c7dedbf73ab068089d8a7d850c279095fe7 100644 (file)
@@ -27,11 +27,11 @@ import org.sonar.api.PropertyType;
 import org.sonar.api.config.Settings;
 
 @Properties({
-  @Property(key = "sonar.dryRun", defaultValue = "false", name = "Dry Run", type = PropertyType.BOOLEAN),
-  @Property(key = "sonar.dryRun.export.path", defaultValue = "dryRun.json", name = "Dry Run Results Export File", type = PropertyType.STRING)
+  @Property(key = "sonar.dryRun", defaultValue = "false", name = "Dry Run", type = PropertyType.BOOLEAN, global = false, project = false),
+  @Property(key = "sonar.dryRun.export.path", defaultValue = "dryRun.json", name = "Dry Run Results Export File", type = PropertyType.STRING, global = false, project = false)
 })
 public class DryRun implements BatchComponent {
-  private final Settings settings;
+  private Settings settings;
 
   public DryRun(Settings settings) {
     this.settings = settings;
index 0e31db355fa9895ab26d280c6eb7825c4520ba9f..42dbd7a414e64962edb3de90469104fdd4d59473 100644 (file)
@@ -98,7 +98,7 @@ public class ExtensionInstaller implements BatchComponent {
    * Example : C# plugin adds sub-projects at runtime, even if they are not defined in root pom.
    */
   static boolean isMavenExtensionOnEmulatedMavenProject(Object extension, String instantiationStrategy, ComponentContainer container) {
-    if (InstantiationStrategy.PROJECT.equals(instantiationStrategy) && ExtensionUtils.isMavenExtensionOnly(extension)) {
+    if (InstantiationStrategy.PER_PROJECT.equals(instantiationStrategy) && ExtensionUtils.isMavenExtensionOnly(extension)) {
       Project project = container.getComponentByType(Project.class);
       return project!=null && project.getPom()==null;
     }
index 901dad13ab62ca829e1e8d80b7459123f2887561..1c850db0212711fde3b0a03c509a1d573e32cf24 100644 (file)
@@ -22,11 +22,11 @@ package org.sonar.batch.bootstrap;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.Extension;
+import org.sonar.api.batch.DryRunIncompatible;
 import org.sonar.api.batch.InstantiationStrategy;
 import org.sonar.api.batch.SupportedEnvironment;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import org.sonar.core.NotDryRun;
 
 final class ExtensionUtils {
 
@@ -39,7 +39,7 @@ final class ExtensionUtils {
     if (annotation != null) {
       return strategy.equals(annotation.value());
     }
-    return InstantiationStrategy.PROJECT.equals(strategy);
+    return InstantiationStrategy.PER_PROJECT.equals(strategy);
   }
 
   static boolean isBatchExtension(Object extension) {
@@ -60,7 +60,7 @@ final class ExtensionUtils {
   }
 
   static boolean supportsDryRun(Object extension) {
-    return AnnotationUtils.getAnnotation(extension, NotDryRun.class) == null;
+    return AnnotationUtils.getAnnotation(extension, DryRunIncompatible.class) == null;
   }
 
   static boolean isMavenExtensionOnly(Object extension) {
index d170217cc389f313fc655433da8ec43335d67415..3b8142654210053afac7dbdd0208cac8152e3cdc 100644 (file)
@@ -83,11 +83,11 @@ public class JdbcDriverHolder {
   }
 
   /**
-   * This method automatically invoked by PicoContainer and deregisters JDBC drivers, which were forgotten.
+   * This method automatically invoked by PicoContainer and unregisters JDBC drivers, which were forgotten.
    * <p>
    * Dynamically loaded JDBC drivers can not be simply used and this is a well known problem of {@link java.sql.DriverManager},
    * so <a href="http://stackoverflow.com/questions/288828/how-to-use-a-jdbc-driver-from-an-arbitrary-location">workaround is to use proxy</a>.
-   * However DriverManager also contains memory leak, thus not only proxy, but also original driver must be deregistered,
+   * However DriverManager also contains memory leak, thus not only proxy, but also original driver must be unregistered,
    * otherwise our class loader would be kept in memory.
    * </p>
    * <p>
index 001ecc3cf57237365da59a46a25120c612aeabf4..3f70dbb93706418a26ce3d72385932df7dac1594 100644 (file)
@@ -63,7 +63,8 @@ public class JdbcLeakPrevention {
     Set<Driver> registeredDrivers = new HashSet<Driver>();
     Enumeration<Driver> drivers = DriverManager.getDrivers();
     while (drivers.hasMoreElements()) {
-      registeredDrivers.add(drivers.nextElement());
+      Driver driver = drivers.nextElement();
+      registeredDrivers.add(driver);
     }
     return registeredDrivers;
   }
index d74c221b1d92cf98a5c137576589fead45944b57..139b1f73df1199209b75b74fe0ab6970ecc8ac37 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.measures.Metrics;
 
 import java.util.List;
 
-@InstantiationStrategy(InstantiationStrategy.BATCH)
+@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 public class MetricProvider extends ExtensionProvider implements BatchExtension {
 
   private Metrics[] factories;
index acbc33b3c47a20dfcb8c8cca2e84cd460938d9d9..050dae891544974f80068ca5113f91a755663f34 100644 (file)
@@ -25,6 +25,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.BatchComponent;
 import org.sonar.api.batch.InstantiationStrategy;
+import org.sonar.api.batch.bootstrap.ProjectBuilder;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.config.Settings;
@@ -34,7 +35,6 @@ import org.sonar.api.config.Settings;
  *
  * @since 2.12
  */
-@InstantiationStrategy(InstantiationStrategy.BOOTSTRAP)
 public class ProjectExclusions implements BatchComponent {
 
   private static final Logger LOG = LoggerFactory.getLogger(ProjectExclusions.class);
@@ -42,11 +42,15 @@ public class ProjectExclusions implements BatchComponent {
   private Settings settings;
   private ProjectReactor reactor;
 
-  public ProjectExclusions(Settings settings, ProjectReactor reactor) {
+  public ProjectExclusions(Settings settings, ProjectReactor reactor, ProjectBuilder[] projectBuilders) {
     this.settings = settings;
     this.reactor = reactor;
   }
 
+  public ProjectExclusions(Settings settings, ProjectReactor reactor) {
+      this(settings, reactor, new ProjectBuilder[0]);
+    }
+
   public void start() {
     LOG.info("Apply project exclusions");
     for (ProjectDefinition project : reactor.getProjects()) {
index ffb2a2f54fda121021029071584cd9f7cb68841c..4d3450b6247c5cd33180924b9d314a1d5e1e4277 100644 (file)
@@ -41,7 +41,7 @@ import org.sonar.batch.config.ProjectSettings;
 import org.sonar.batch.config.UnsupportedProperties;
 import org.sonar.batch.events.EventBus;
 import org.sonar.batch.index.DefaultIndex;
-import org.sonar.batch.index.DefaultResourcePersister;
+import org.sonar.batch.index.ResourcePersister;
 import org.sonar.batch.local.DryRunExporter;
 import org.sonar.batch.phases.Phases;
 import org.sonar.batch.phases.PhasesTimeProfiler;
@@ -61,11 +61,16 @@ public class ProjectModule extends Module {
   protected void configure() {
     logSettings();
     addCoreComponents();
-    addProjectComponents();
-    addProjectPluginExtensions();
+    addPluginExtensions();
   }
 
-  private void addProjectComponents() {
+  private void addCoreComponents() {
+    container.addSingleton(EventBus.class);
+    container.addSingleton(Phases.class);
+    container.addSingleton(PhasesTimeProfiler.class);
+    for (Class clazz : Phases.getPhaseClasses()) {
+      container.addSingleton(clazz);
+    }
     ProjectDefinition projectDefinition = container.getComponentByType(ProjectTree.class).getProjectDefinition(project);
     container.addSingleton(projectDefinition);
     container.addSingleton(project);
@@ -82,7 +87,7 @@ public class ProjectModule extends Module {
     container.addSingleton(RulesDao.class);
 
     // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
-    container.addSingleton(container.getComponentByType(DefaultResourcePersister.class).getSnapshot(project));
+    container.addSingleton(container.getComponentByType(ResourcePersister.class).getSnapshot(project));
 
     container.addSingleton(TimeMachineConfiguration.class);
     container.addSingleton(org.sonar.api.database.daos.MeasuresDao.class);
@@ -98,18 +103,9 @@ public class ProjectModule extends Module {
     container.addPicoAdapter(new ProfileProvider());
   }
 
-  private void addCoreComponents() {
-    container.addSingleton(EventBus.class);
-    container.addSingleton(Phases.class);
-    container.addSingleton(PhasesTimeProfiler.class);
-    for (Class clazz : Phases.getPhaseClasses()) {
-      container.addSingleton(clazz);
-    }
-  }
-
-  private void addProjectPluginExtensions() {
+  private void addPluginExtensions() {
     ExtensionInstaller installer = container.getComponentByType(ExtensionInstaller.class);
-    installer.install(container, InstantiationStrategy.PROJECT);
+    installer.install(container, InstantiationStrategy.PER_PROJECT);
   }
 
   private void logSettings() {
@@ -124,9 +120,9 @@ public class ProjectModule extends Module {
   protected void doStart() {
     DefaultIndex index = container.getComponentByType(DefaultIndex.class);
     index.setCurrentProject(project,
-        container.getComponentByType(ResourceFilters.class),
-        container.getComponentByType(ViolationFilters.class),
-        container.getComponentByType(RulesProfile.class));
+      container.getComponentByType(ResourceFilters.class),
+      container.getComponentByType(ViolationFilters.class),
+      container.getComponentByType(RulesProfile.class));
 
     container.getComponentByType(Phases.class).execute(project);
   }
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectReactorReady.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectReactorReady.java
new file mode 100644 (file)
index 0000000..08a3907
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.sonar.api.batch.bootstrap.ProjectBuilder;
+
+/**
+ * Barrier to control the project lifecycle :
+ * <p/>
+ * <ul>
+ * <li>initialize the project configuration by executing ProjectBuilder extensions</li>
+ * <li>apply sub-project exclusions (sonar.skippedModules, ...)</li>
+ * <li>---- this barrier ----</li>
+ * <li>run optional dry run database</li>
+ * <li>connect to dry-run or remote database</li>
+ * </ul>
+ */
+public class ProjectReactorReady {
+
+  public ProjectReactorReady(ProjectExclusions exclusions, ProjectBuilder[] projectBuilders) {
+  }
+
+  public ProjectReactorReady(ProjectExclusions exclusions) {
+    this(exclusions, new ProjectBuilder[0]);
+  }
+
+  public void start() {
+
+  }
+}
index 1b3f0d5547c5235548577f8a2b9583553a4f07a2..56f00e1e64c1fcc92cc987b5d62fcfc87eda8944 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.bootstrap.DryRun;
+import org.sonar.batch.bootstrap.ProjectReactorReady;
 import org.sonar.batch.bootstrap.ServerClient;
 import org.sonar.batch.bootstrap.TempDirectories;
 
@@ -51,7 +52,9 @@ public class DryRunDatabase implements BatchComponent {
   private final TempDirectories tempDirectories;
   private final ProjectReactor reactor;
 
-  public DryRunDatabase(DryRun dryRun, Settings settings, ServerClient server, TempDirectories tempDirectories, ProjectReactor reactor) {
+  public DryRunDatabase(DryRun dryRun, Settings settings, ServerClient server, TempDirectories tempDirectories, ProjectReactor reactor,
+                        // project reactor must be completely built
+                        ProjectReactorReady reactorReady) {
     this.dryRun = dryRun;
     this.settings = settings;
     this.server = server;
index 0862c928ab3cf3576b018524a1e246137d5c1eb9..177bba664539d5202f36b02eee6cdaee905ae499 100644 (file)
@@ -21,18 +21,18 @@ package org.sonar.batch.phases;
 
 import org.slf4j.LoggerFactory;
 import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.DryRunIncompatible;
 import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Scopes;
 import org.sonar.batch.bootstrap.ServerClient;
 import org.sonar.batch.index.ResourcePersister;
-import org.sonar.core.NotDryRun;
 
 import javax.persistence.Query;
 
 import java.util.List;
 
-@NotDryRun
+@DryRunIncompatible
 public class UpdateStatusJob implements BatchComponent {
 
   private DatabaseSession session;
index 4f0ae830355fc67c9dea153a2605f82585ecf808..e6d0ce5102c4e1bca46bdb3fc60fa2ee2ac56f8f 100644 (file)
  */
 package org.sonar.batch;
 
+import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.config.Settings;
 
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
+import static org.fest.assertions.Assertions.assertThat;
 
 public class DefaultResourceCreationLockTest {
 
+  Settings settings;
+
+  @Before
+  public void init() {
+    settings = new Settings();
+  }
+
   @Test
   public void shouldNotBeLockedAtStartup() {
-    assertThat(new DefaultResourceCreationLock().isLocked(), is(false));
+    assertThat(new DefaultResourceCreationLock(settings).isLocked()).isFalse();
+  }
+
+  @Test
+  public void should_fail_if_locked() {
+    DefaultResourceCreationLock lock = new DefaultResourceCreationLock(settings);
+    assertThat(lock.isFailWhenLocked()).isFalse();
+    lock.setFailWhenLocked(true);
+    assertThat(lock.isFailWhenLocked()).isTrue();
   }
 
   @Test
-  public void shouldLock() {
-    DefaultResourceCreationLock lock = new DefaultResourceCreationLock();
+  public void should_lock() {
+    DefaultResourceCreationLock lock = new DefaultResourceCreationLock(settings);
     lock.lock();
-    assertThat(lock.isLocked(), is(true));
+    assertThat(lock.isLocked()).isTrue();
 
     lock.unlock();
-    assertThat(lock.isLocked(), is(false));
+    assertThat(lock.isLocked()).isFalse();
   }
 }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactoryTest.java
new file mode 100644 (file)
index 0000000..d28bf93
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.junit.Test;
+import org.sonar.api.database.DatabaseSession;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class BatchDatabaseSessionFactoryTest {
+  @Test
+  public void getSession() {
+    DatabaseSession session = mock(DatabaseSession.class);
+    BatchDatabaseSessionFactory factory = new BatchDatabaseSessionFactory(session);
+
+    assertThat(factory.getSession()).isSameAs(session);
+  }
+}
index 0be5a53f54c2cd006fb1b74d581c69948f15408c..4399f2bfde87cc5d0507b4955419310ad70a6b80 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.batch.bootstrap;
 
 import org.junit.Test;
 import org.sonar.api.config.Settings;
+import org.sonar.batch.local.DryRunDatabase;
 
 import java.util.Properties;
 
@@ -30,7 +31,7 @@ import static org.mockito.Mockito.mock;
 public class BatchDatabaseTest {
   @Test
   public void should_init_at_least_two_connections() {
-    BatchDatabase db = new BatchDatabase(new Settings(), mock(JdbcDriverHolder.class));
+    BatchDatabase db = new BatchDatabase(new Settings(), mock(JdbcDriverHolder.class), mock(DryRunDatabase.class));
     Properties props = new Properties();
 
     db.doCompleteProperties(props);
index 9f297a762a2b1ce5b654c4b2052ffade8849c9c0..670c558bd00688334beb1989b2bb09f468ae258f 100644 (file)
@@ -44,7 +44,7 @@ public class BatchModuleTest {
     BatchModule module = new BatchModule();
     bootstrapModule.installChild(module);
 
-    verify(extensionInstaller).install(any(ComponentContainer.class), eq(InstantiationStrategy.BATCH));
+    verify(extensionInstaller).install(any(ComponentContainer.class), eq(InstantiationStrategy.PER_BATCH));
     assertThat(module.container.getComponentByType(MetricProvider.class)).isNotNull();
   }
 }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutorTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutorTest.java
deleted file mode 100644 (file)
index a069c45..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 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.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.picocontainer.Startable;
-import org.sonar.api.batch.InstantiationStrategy;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.config.Settings;
-import org.sonar.api.platform.ComponentContainer;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class BootstrapExtensionExecutorTest {
-  private ProjectReactor reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
-
-  @Test
-  public void start() {
-    ComponentContainer container = new ComponentContainer();
-    // dependencies required for ProjectExclusions
-    container.addSingleton(reactor);
-    container.addSingleton(new Settings());
-
-    // declare a bootstrap component
-    final Startable bootstrapComponent = mock(Startable.class);
-    ExtensionInstaller installer = mock(ExtensionInstaller.class);
-    doAnswer(new Answer() {
-      public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
-        ComponentContainer childContainer = (ComponentContainer) invocationOnMock.getArguments()[0];
-        childContainer.addSingleton(bootstrapComponent);
-        return null;
-      }
-    }).when(installer).install(any(ComponentContainer.class), eq(InstantiationStrategy.BOOTSTRAP));
-
-    BootstrapExtensionExecutor executor = new BootstrapExtensionExecutor(container, installer);
-    executor.start();
-
-    // should install bootstrap components into a ephemeral container
-    verify(installer).install(any(ComponentContainer.class), eq(InstantiationStrategy.BOOTSTRAP));
-    verify(bootstrapComponent).start();
-    verify(bootstrapComponent).stop();
-
-    // the ephemeral container is destroyed
-    assertThat(container.getComponentByType(ProjectExclusions.class)).isNull();
-    assertThat(container.getChild()).isNull();
-  }
-
-
-}
index fe972cab9324825aa35663397a320475ddfa4fe3..90f4981efdb4eaf1146bcde3961dac42351ae925 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.api.batch.SupportedEnvironment;
 import org.sonar.api.config.Settings;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.resources.Project;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
 
 import java.util.Arrays;
@@ -64,7 +65,7 @@ public class ExtensionInstallerTest {
     ComponentContainer container = new ComponentContainer();
     ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new Settings());
 
-    installer.install(container, InstantiationStrategy.BATCH);
+    installer.install(container, InstantiationStrategy.PER_BATCH);
 
     assertThat(container.getComponentByType(BatchService.class)).isNotNull();
     assertThat(container.getComponentByType(ProjectService.class)).isNull();
@@ -78,7 +79,7 @@ public class ExtensionInstallerTest {
     ComponentContainer container = new ComponentContainer();
     ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new Settings());
 
-    installer.install(container, InstantiationStrategy.BATCH);
+    installer.install(container, InstantiationStrategy.PER_BATCH);
 
     assertThat(container.getComponentByType(BatchService.class)).isNotNull();
     assertThat(container.getComponentByType(ProjectService.class)).isNull();
@@ -94,13 +95,29 @@ public class ExtensionInstallerTest {
     ComponentContainer container = new ComponentContainer();
     ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new Settings());
 
-    installer.install(container, InstantiationStrategy.PROJECT);
+    installer.install(container, InstantiationStrategy.PER_PROJECT);
 
     assertThat(container.getComponentByType(MavenService.class)).isNull();
     assertThat(container.getComponentByType(BuildToolService.class)).isNotNull();
   }
 
-  @InstantiationStrategy(InstantiationStrategy.BATCH)
+  @Test
+  public void should_disable_maven_extensions_if_virtual_module_in_maven_project() {
+    Project project = mock(Project.class);
+    when(project.getPom()).thenReturn(null);
+    BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
+    when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(MavenService.class));
+
+    ComponentContainer container = new ComponentContainer();
+    container.addSingleton(project);
+    ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("maven", "2.2.1"), new Settings());
+
+    installer.install(container, InstantiationStrategy.PER_PROJECT);
+
+    assertThat(container.getComponentByType(MavenService.class)).isNull();
+  }
+
+  @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
   public static class BatchService implements BatchExtension {
 
   }
@@ -113,7 +130,7 @@ public class ExtensionInstallerTest {
 
   }
 
-  @InstantiationStrategy(InstantiationStrategy.BATCH)
+  @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
   public static class BatchServiceProvider extends ExtensionProvider implements BatchExtension {
 
     @Override
index 5b08e03ccab4fd50bab966fac738605b012ba120..3ce49c8a4b9ab1bfa6aeb332aa0ef0d9782bf40e 100644 (file)
@@ -22,10 +22,10 @@ package org.sonar.batch.bootstrap;
 import org.junit.Test;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.ServerExtension;
+import org.sonar.api.batch.DryRunIncompatible;
 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.fest.assertions.Assertions.assertThat;
 
@@ -33,22 +33,22 @@ public class ExtensionUtilsTest {
 
   @Test
   public void shouldBeBatchInstantiationStrategy() {
-    assertThat(ExtensionUtils.isInstantiationStrategy(BatchService.class, InstantiationStrategy.BATCH)).isTrue();
-    assertThat(ExtensionUtils.isInstantiationStrategy(new BatchService(), InstantiationStrategy.BATCH)).isTrue();
-    assertThat(ExtensionUtils.isInstantiationStrategy(ProjectService.class, InstantiationStrategy.BATCH)).isFalse();
-    assertThat(ExtensionUtils.isInstantiationStrategy(new ProjectService(), InstantiationStrategy.BATCH)).isFalse();
-    assertThat(ExtensionUtils.isInstantiationStrategy(DefaultService.class, InstantiationStrategy.BATCH)).isFalse();
-    assertThat(ExtensionUtils.isInstantiationStrategy(new DefaultService(), InstantiationStrategy.BATCH)).isFalse();
+    assertThat(ExtensionUtils.isInstantiationStrategy(BatchService.class, InstantiationStrategy.PER_BATCH)).isTrue();
+    assertThat(ExtensionUtils.isInstantiationStrategy(new BatchService(), InstantiationStrategy.PER_BATCH)).isTrue();
+    assertThat(ExtensionUtils.isInstantiationStrategy(ProjectService.class, InstantiationStrategy.PER_BATCH)).isFalse();
+    assertThat(ExtensionUtils.isInstantiationStrategy(new ProjectService(), InstantiationStrategy.PER_BATCH)).isFalse();
+    assertThat(ExtensionUtils.isInstantiationStrategy(DefaultService.class, InstantiationStrategy.PER_BATCH)).isFalse();
+    assertThat(ExtensionUtils.isInstantiationStrategy(new DefaultService(), InstantiationStrategy.PER_BATCH)).isFalse();
   }
 
   @Test
   public void shouldBeProjectInstantiationStrategy() {
-    assertThat(ExtensionUtils.isInstantiationStrategy(BatchService.class, InstantiationStrategy.PROJECT)).isFalse();
-    assertThat(ExtensionUtils.isInstantiationStrategy(new BatchService(), InstantiationStrategy.PROJECT)).isFalse();
-    assertThat(ExtensionUtils.isInstantiationStrategy(ProjectService.class, InstantiationStrategy.PROJECT)).isTrue();
-    assertThat(ExtensionUtils.isInstantiationStrategy(new ProjectService(), InstantiationStrategy.PROJECT)).isTrue();
-    assertThat(ExtensionUtils.isInstantiationStrategy(DefaultService.class, InstantiationStrategy.PROJECT)).isTrue();
-    assertThat(ExtensionUtils.isInstantiationStrategy(new DefaultService(), InstantiationStrategy.PROJECT)).isTrue();
+    assertThat(ExtensionUtils.isInstantiationStrategy(BatchService.class, InstantiationStrategy.PER_PROJECT)).isFalse();
+    assertThat(ExtensionUtils.isInstantiationStrategy(new BatchService(), InstantiationStrategy.PER_PROJECT)).isFalse();
+    assertThat(ExtensionUtils.isInstantiationStrategy(ProjectService.class, InstantiationStrategy.PER_PROJECT)).isTrue();
+    assertThat(ExtensionUtils.isInstantiationStrategy(new ProjectService(), InstantiationStrategy.PER_PROJECT)).isTrue();
+    assertThat(ExtensionUtils.isInstantiationStrategy(DefaultService.class, InstantiationStrategy.PER_PROJECT)).isTrue();
+    assertThat(ExtensionUtils.isInstantiationStrategy(new DefaultService(), InstantiationStrategy.PER_PROJECT)).isTrue();
   }
 
   @Test
@@ -87,12 +87,12 @@ public class ExtensionUtilsTest {
     assertThat(ExtensionUtils.supportsDryRun(new PersistentService())).isFalse();
   }
 
-  @InstantiationStrategy(InstantiationStrategy.BATCH)
+  @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
   public static class BatchService implements BatchExtension {
 
   }
 
-  @InstantiationStrategy(InstantiationStrategy.PROJECT)
+  @InstantiationStrategy(InstantiationStrategy.PER_PROJECT)
   public static class ProjectService implements BatchExtension {
 
   }
@@ -115,7 +115,7 @@ public class ExtensionUtilsTest {
 
   }
 
-  @NotDryRun
+  @DryRunIncompatible
   public static class PersistentService implements BatchExtension {
 
   }
index ac5f92af70ad2053328adb2a7e939ee71287d580..ad32777a15be2ee92985f83e20c08b73c9305398 100644 (file)
@@ -21,13 +21,16 @@ package org.sonar.batch.bootstrap;
 
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.utils.SonarException;
 import org.sonar.core.plugins.RemotePlugin;
 
 import java.io.File;
 import java.util.List;
 
 import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -37,6 +40,9 @@ public class PluginDownloaderTest {
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
   @Test
   public void should_request_list_of_plugins() {
     TempDirectories tempDirs = mock(TempDirectories.class);
@@ -72,4 +78,14 @@ public class PluginDownloaderTest {
     verify(server).download("/deploy/plugins/checkstyle/checkstyle-plugin.jar", pluginFile);
     verify(server).download("/deploy/plugins/checkstyle/checkstyle-extensions.jar", extFile);
   }
+
+  @Test
+  public void should_fail_to_get_plugin_index() throws Exception {
+    thrown.expect(SonarException.class);
+
+    ServerClient server = mock(ServerClient.class);
+    doThrow(new SonarException()).when(server).request("/deploy/plugins/index.txt");
+
+    new PluginDownloader(mock(TempDirectories.class), server).downloadPluginIndex();
+  }
 }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java
new file mode 100644 (file)
index 0000000..2cacc9a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.junit.Test;
+import org.mockito.Matchers;
+import org.sonar.api.batch.InstantiationStrategy;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.platform.ComponentContainer;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.batch.ProjectTree;
+import org.sonar.batch.config.ProjectSettings;
+import org.sonar.batch.index.ResourcePersister;
+import org.sonar.core.properties.PropertiesDao;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ProjectModuleTest {
+  @Test
+  public void should_register_project_extensions() {
+    // components injected in the parent container
+    final Project project = new Project("foo");
+    project.setConfiguration(new PropertiesConfiguration());
+    final ProjectTree projectTree = mock(ProjectTree.class);
+    when(projectTree.getProjectDefinition(project)).thenReturn(ProjectDefinition.create());
+    final ResourcePersister resourcePersister = mock(ResourcePersister.class);
+    when(resourcePersister.getSnapshot(Matchers.<Resource>any())).thenReturn(new Snapshot());
+
+    final ExtensionInstaller extensionInstaller = mock(ExtensionInstaller.class);
+    Module batchModule = new Module() {
+      @Override
+      protected void configure() {
+        container.addSingleton(extensionInstaller);
+        container.addSingleton(projectTree);
+        container.addSingleton(resourcePersister);
+        container.addSingleton(mock(PropertiesDao.class));
+      }
+    };
+
+    batchModule.init();
+    ProjectModule projectModule = new ProjectModule(project);
+    batchModule.installChild(projectModule);
+
+    verify(extensionInstaller).install(any(ComponentContainer.class), eq(InstantiationStrategy.PER_PROJECT));
+    assertThat(projectModule.container.getComponentByType(ProjectSettings.class)).isNotNull();
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectReactorReadyTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectReactorReadyTest.java
new file mode 100644 (file)
index 0000000..df15f27
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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.junit.Test;
+import org.sonar.api.batch.bootstrap.ProjectBuilder;
+
+import static org.mockito.Mockito.mock;
+
+public class ProjectReactorReadyTest {
+  @Test
+  public void should_do_nothing() {
+    // it's only a barrier
+    ProjectReactorReady barrier = new ProjectReactorReady(mock(ProjectExclusions.class), new ProjectBuilder[]{mock(ProjectBuilder.class)});
+    barrier.start();
+  }
+
+  @Test
+  public void project_builders_should_be_optional() {
+    ProjectReactorReady barrier = new ProjectReactorReady(mock(ProjectExclusions.class));
+    barrier.start();
+  }
+}
index 29649a45b6240e0382a82b23770eb4ef33eb6217..19babd292bd3ae92d674b50001ec2d9b179d54f7 100644 (file)
@@ -29,6 +29,7 @@ import org.apache.commons.lang.StringUtils;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.ResourceFilter;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilters;
@@ -60,7 +61,7 @@ public class DefaultIndexTest {
 
   @Before
   public void createIndex() {
-    lock = new DefaultResourceCreationLock();
+    lock = new DefaultResourceCreationLock(new Settings());
     MetricFinder metricFinder = mock(MetricFinder.class);
     when(metricFinder.findByKey("ncloc")).thenReturn(CoreMetrics.NCLOC);
 
index 319da8d467f7a520b08f30a8b80e78267bdc5094..e2b3d27b8161cb5ffa3818c9cfca70e638c69244 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.bootstrap.DryRun;
+import org.sonar.batch.bootstrap.ProjectReactorReady;
 import org.sonar.batch.bootstrap.ServerClient;
 import org.sonar.batch.bootstrap.TempDirectories;
 
@@ -57,7 +58,7 @@ public class DryRunDatabaseTest {
 
   @Before
   public void setUp() {
-    dryRunDatabase = new DryRunDatabase(dryRun, settings, server, tempDirectories, projectReactor);
+    dryRunDatabase = new DryRunDatabase(dryRun, settings, server, tempDirectories, projectReactor, mock(ProjectReactorReady.class));
   }
 
   @Test
diff --git a/sonar-core/src/main/java/org/sonar/core/NotDryRun.java b/sonar-core/src/main/java/org/sonar/core/NotDryRun.java
deleted file mode 100644 (file)
index 074d934..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 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 {
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/DryRunIncompatible.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/DryRunIncompatible.java
new file mode 100644 (file)
index 0000000..aa113c4
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 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 java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The presence of this annotation on an extension class indicates that the extension
+ * may be disabled when the dry-run mode is enabled (-Dsonar.dryRun=true).
+ * It's generally used by the extensions that push data to external systems, for example :
+ * <ul>
+ *   <li>Send emails</li>
+ *   <li>Create a JIRA issue</li>
+ * </ul>
+ *
+ *
+ * @since 3.4
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface DryRunIncompatible {
+}
index a5619a1bdd4dec79da72f995c22ff183aff4428a..a3155b424cd2969036ecc02e7774ce0aaf216912 100644 (file)
@@ -34,32 +34,13 @@ public @interface InstantiationStrategy {
 
   /**
    * Shared extension. Lifecycle is the full analysis.
-   * @deprecated replaced by the constant {@link org.sonar.api.batch.InstantiationStrategy.BATCH} since version 3.4
    */
-  @Deprecated
   String PER_BATCH = "PER_BATCH";
 
   /**
    * Created and initialized for each project and sub-project (a project is a module in Maven terminology).
-   * @deprecated replaced by the constant {@link org.sonar.api.batch.InstantiationStrategy.PROJECT} since version 3.4
    */
-  @Deprecated
   String PER_PROJECT = "PER_PROJECT";
 
-  /**
-   * @since 3.4
-   */
-  String BOOTSTRAP = "BOOTSTRAP";
-
-  /**
-   * @since 3.4
-   */
-  String BATCH = "PER_BATCH";
-
-  /**
-   * @since 3.4
-   */
-  String PROJECT = "PER_PROJECT";
-
   String value();
 }
index 078d5f335a843191f00d120b545169e96dfd0d3c..7de741cc6c96f0439a500bf502b3c77517cae405 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.batch.InstantiationStrategy;
  *
  * @since 2.9
  */
-@InstantiationStrategy(InstantiationStrategy.BOOTSTRAP)
+@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 public abstract class ProjectBuilder implements BatchExtension {
 
   private ProjectReactor reactor;
index e60d3cd90a100f04cd642b1af32b5bee4900ab24..d28a754f410fca8e94dc17ec548028691866630e 100644 (file)
@@ -35,7 +35,7 @@ import javax.persistence.*;
  */
 @Table(name = "metrics")
 @Entity(name = "Metric")
-@InstantiationStrategy(InstantiationStrategy.BATCH)
+@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 public class Metric implements ServerExtension, BatchExtension {
 
   /**
index f22181642ef504e57190e7017d1f7e10cff50b74..fe0170eac4eaa4802834a9bb72ab90fbf733c297 100644 (file)
@@ -28,7 +28,7 @@ import java.util.List;
 /**
  * @since 1.10
  */
-@InstantiationStrategy(InstantiationStrategy.BATCH)
+@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 public interface Metrics extends BatchExtension, ServerExtension {
   List<Metric> getMetrics();
 }
index d02fa97a17aa118c1b4d27c560e41a308168b8c0..88fb6f72379f5dd7f94aac566cca6ee22de2f8c7 100644 (file)
@@ -36,7 +36,7 @@ import java.util.List;
  */
 @Beta
 @Immutable
-@InstantiationStrategy(InstantiationStrategy.BATCH)
+@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 public final class ResourceTypeTree implements BatchExtension, ServerExtension {
 
   private List<ResourceType> types;