Browse Source

SONAR-3895 fix compatibility of dry-run mode with ProjectBuilder extensions

tags/3.4
Simon Brandhof 11 years ago
parent
commit
8bccd3cd3d
45 changed files with 415 additions and 258 deletions
  1. 1
    1
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/DefaultResourceTypes.java
  2. 2
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/batch/IndexProjectPostJob.java
  3. 1
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewWorkflowDecorator.java
  4. 2
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/VersionEventsSensor.java
  5. 1
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
  6. 1
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TendencyDecorator.java
  7. 2
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersister.java
  8. 1
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java
  9. 2
    2
      plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/ProjectPurgePostJob.java
  10. 4
    7
      sonar-batch/src/main/java/org/sonar/batch/DefaultResourceCreationLock.java
  11. 3
    5
      sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
  12. 9
    3
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java
  13. 39
    0
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactory.java
  14. 41
    3
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
  15. 1
    0
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java
  16. 0
    38
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
  17. 3
    3
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRun.java
  18. 1
    1
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
  19. 3
    3
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java
  20. 2
    2
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcDriverHolder.java
  21. 2
    1
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcLeakPrevention.java
  22. 1
    1
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/MetricProvider.java
  23. 6
    2
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java
  24. 15
    19
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java
  25. 18
    16
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectReactorReady.java
  26. 4
    1
      sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java
  27. 2
    2
      sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java
  28. 23
    7
      sonar-batch/src/test/java/org/sonar/batch/DefaultResourceCreationLockTest.java
  29. 36
    0
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactoryTest.java
  30. 2
    1
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseTest.java
  31. 1
    1
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchModuleTest.java
  32. 0
    74
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutorTest.java
  33. 22
    5
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
  34. 16
    16
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java
  35. 16
    0
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/PluginDownloaderTest.java
  36. 72
    0
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java
  37. 40
    0
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectReactorReadyTest.java
  38. 2
    1
      sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
  39. 2
    1
      sonar-batch/src/test/java/org/sonar/batch/local/DryRunDatabaseTest.java
  40. 12
    5
      sonar-plugin-api/src/main/java/org/sonar/api/batch/DryRunIncompatible.java
  41. 0
    19
      sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java
  42. 1
    1
      sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java
  43. 1
    1
      sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
  44. 1
    1
      sonar-plugin-api/src/main/java/org/sonar/api/measures/Metrics.java
  45. 1
    1
      sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceTypeTree.java

+ 1
- 1
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/DefaultResourceTypes.java View 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() {

+ 2
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/batch/IndexProjectPostJob.java View File

@@ -19,16 +19,16 @@
*/
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;


+ 1
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewWorkflowDecorator.java View 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 {

+ 2
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/VersionEventsSensor.java View File

@@ -20,15 +20,15 @@
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) {

+ 1
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java View 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 {


+ 1
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TendencyDecorator.java View 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 {


+ 2
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersister.java View 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;

+ 1
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java View 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 {

+ 2
- 2
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/ProjectPurgePostJob.java View File

@@ -19,13 +19,13 @@
*/
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;

+ 4
- 7
sonar-batch/src/main/java/org/sonar/batch/DefaultResourceCreationLock.java View 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() {

+ 3
- 5
sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java View 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());
}

+ 9
- 3
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java View 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);
}


+ 39
- 0
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactory.java View File

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

+ 41
- 3
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java View 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

+ 1
- 0
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java View 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;

+ 0
- 38
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java View 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() {

+ 3
- 3
sonar-batch/src/main/java/org/sonar/batch/bootstrap/DryRun.java View 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;

+ 1
- 1
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java View 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;
}

+ 3
- 3
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionUtils.java View 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) {

+ 2
- 2
sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcDriverHolder.java View 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>

+ 2
- 1
sonar-batch/src/main/java/org/sonar/batch/bootstrap/JdbcLeakPrevention.java View 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;
}

+ 1
- 1
sonar-batch/src/main/java/org/sonar/batch/bootstrap/MetricProvider.java View 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;

+ 6
- 2
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java View 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()) {

+ 15
- 19
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java View 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);
}

sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutor.java → sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectReactorReady.java View File

@@ -19,27 +19,29 @@
*/
package org.sonar.batch.bootstrap;

import org.slf4j.LoggerFactory;
import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.batch.bootstrap.ProjectBuilder;

public class BootstrapExtensionExecutor {
/**
* 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 {

private ComponentContainer container;
private ExtensionInstaller installer;
public ProjectReactorReady(ProjectExclusions exclusions, ProjectBuilder[] projectBuilders) {
}

public BootstrapExtensionExecutor(ComponentContainer container, ExtensionInstaller installer) {
this.container = container;
this.installer = installer;
public ProjectReactorReady(ProjectExclusions exclusions) {
this(exclusions, new ProjectBuilder[0]);
}

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

}
}

+ 4
- 1
sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java View 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;

+ 2
- 2
sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java View 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;

+ 23
- 7
sonar-batch/src/test/java/org/sonar/batch/DefaultResourceCreationLockTest.java View File

@@ -19,25 +19,41 @@
*/
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();
}
}

+ 36
- 0
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseSessionFactoryTest.java View File

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

+ 2
- 1
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchDatabaseTest.java View 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);

+ 1
- 1
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchModuleTest.java View 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();
}
}

+ 0
- 74
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapExtensionExecutorTest.java View File

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


}

+ 22
- 5
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java View 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

+ 16
- 16
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionUtilsTest.java View 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 {

}

+ 16
- 0
sonar-batch/src/test/java/org/sonar/batch/bootstrap/PluginDownloaderTest.java View 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();
}
}

+ 72
- 0
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java View File

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

+ 40
- 0
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectReactorReadyTest.java View File

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

+ 2
- 1
sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java View 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);


+ 2
- 1
sonar-batch/src/test/java/org/sonar/batch/local/DryRunDatabaseTest.java View 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

sonar-core/src/main/java/org/sonar/core/NotDryRun.java → sonar-plugin-api/src/main/java/org/sonar/api/batch/DryRunIncompatible.java View File

@@ -17,7 +17,7 @@
* 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;
package org.sonar.api.batch;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -25,11 +25,18 @@ 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
* 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 NotDryRun {
public @interface DryRunIncompatible {
}

+ 0
- 19
sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java View 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();
}

+ 1
- 1
sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java View 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;

+ 1
- 1
sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java View 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 {

/**

+ 1
- 1
sonar-plugin-api/src/main/java/org/sonar/api/measures/Metrics.java View 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();
}

+ 1
- 1
sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceTypeTree.java View 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;

Loading…
Cancel
Save