]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2861 New Configuration API
authorsimonbrandhof <simon.brandhof@gmail.com>
Tue, 4 Oct 2011 22:44:37 +0000 (00:44 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Fri, 7 Oct 2011 11:36:25 +0000 (13:36 +0200)
The component org.apache.commons.Configuration is still available but plugins should use org.sonar.api.config.Settings.
It also implies the following issues :

SONAR-2870 do not rebuild the WAR file when editing sonar.properties
SONAR-2869 allow to use the annotations @Properties/@Property on extensions

94 files changed:
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/CheckstyleConfiguration.java
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/CheckstyleConstants.java
plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/CheckstyleConfigurationTest.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
sonar-application/src/main/assembly/war/build.xml
sonar-batch/src/main/java/org/sonar/batch/Batch.java
sonar-batch/src/main/java/org/sonar/batch/ProjectConfigurator.java
sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
sonar-batch/src/main/java/org/sonar/batch/ServerMetadata.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionInstaller.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java
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/Module.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExtensionInstaller.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java
sonar-batch/src/main/java/org/sonar/batch/config/BatchSettings.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/config/BatchSettingsEnhancer.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/config/DeprecatedConfigurationProvider.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/DecoratorsSelectorTest.java
sonar-batch/src/test/java/org/sonar/batch/ProjectConfiguratorTest.java
sonar-batch/src/test/java/org/sonar/batch/ProjectTreeTest.java
sonar-batch/src/test/java/org/sonar/batch/ServerMetadataTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionInstallerTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/DryRunTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ModuleTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectExtensionInstallerTest.java
sonar-core/src/main/java/org/sonar/core/config/ConfigurationUtils.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/plugins/PluginClassloaders.java
sonar-core/src/main/java/org/sonar/jpa/session/AbstractDatabaseConnector.java
sonar-core/src/main/java/org/sonar/jpa/session/DriverDatabaseConnector.java
sonar-core/src/main/java/org/sonar/jpa/session/MemoryDatabaseConnector.java
sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/plugin/AbstractPluginRepositoryTest.java
sonar-core/src/test/java/org/sonar/jpa/session/AbstractDatabaseConnectorTest.java
sonar-core/src/test/java/org/sonar/jpa/session/DriverDatabaseConnectorTest.java
sonar-maven-plugin/src/main/java/org/sonar/maven/SonarMojo.java
sonar-maven3-plugin/src/main/java/org/sonar/maven3/SonarMojo.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/BatchExtensionDictionnary.java
sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/resources/Languages.java
sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/HttpDownloader.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/IocContainer.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/BatchExtensionDictionnaryTest.java
sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionsTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/config/SettingsTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentContainerTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/utils/HttpDownloaderTest.java
sonar-plugin-api/src/test/java/org/sonar/api/utils/IocContainerTest.java [deleted file]
sonar-server/src/main/java/org/sonar/server/charts/ChartsServlet.java
sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationException.java [deleted file]
sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationFactory.java [deleted file]
sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationLogger.java [deleted file]
sonar-server/src/main/java/org/sonar/server/configuration/CoreConfiguration.java [deleted file]
sonar-server/src/main/java/org/sonar/server/configuration/ServerSettings.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/database/EmbeddedDatabase.java
sonar-server/src/main/java/org/sonar/server/database/EmbeddedDatabaseFactory.java
sonar-server/src/main/java/org/sonar/server/database/JndiDatabaseConnector.java
sonar-server/src/main/java/org/sonar/server/mavendeployer/MavenRepository.java
sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java
sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
sonar-server/src/main/java/org/sonar/server/platform/Platform.java
sonar-server/src/main/java/org/sonar/server/platform/PlatformLifecycleListener.java
sonar-server/src/main/java/org/sonar/server/plugins/DefaultServerPluginRepository.java
sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java
sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java
sonar-server/src/main/java/org/sonar/server/startup/GwtPublisher.java
sonar-server/src/main/java/org/sonar/server/ui/AuthenticatorFactory.java
sonar-server/src/main/java/org/sonar/server/ui/DatabaseSessionFilter.java
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
sonar-server/src/main/resources/sonar-war.properties [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/settings_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/updatecenter_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/users_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/models/server.rb
sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb
sonar-server/src/main/webapp/WEB-INF/lib/database_version.rb
sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb
sonar-server/src/test/java/org/sonar/server/configuration/ConfigurationFactoryTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/database/EmbeddedDatabaseTest.java
sonar-server/src/test/java/org/sonar/server/database/JndiDatabaseConnectorTest.java
sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java
sonar-server/src/test/java/org/sonar/server/plugins/DefaultServerPluginRepositoryTest.java
sonar-server/src/test/java/org/sonar/server/plugins/ServerExtensionInstallerTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/ui/AuthenticatorFactoryTest.java

index 7461fe4cc6030894451e86b6879ad981111bc8b9..de9d5d5ce7a0c6388d2640a57f86cf7e99f2bfa1 100644 (file)
@@ -23,13 +23,14 @@ import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
 import com.puppycrawl.tools.checkstyle.PropertiesExpander;
 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.CharEncoding;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.Property;
+import org.sonar.api.config.Settings;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.resources.Java;
 import org.sonar.api.resources.ProjectFileSystem;
@@ -41,16 +42,22 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Properties;
 
+@org.sonar.api.Properties({
+    @Property(key = CheckstyleConfiguration.PROPERTY_GENERATE_XML,
+        defaultValue = "false",
+        name = "Generate XML Report",
+        project = false, global = false)})
 public class CheckstyleConfiguration implements BatchExtension {
 
   private static final Logger LOG = LoggerFactory.getLogger(CheckstyleConfiguration.class);
+  public static final String PROPERTY_GENERATE_XML = "sonar.checkstyle.generateXml";
 
   private CheckstyleProfileExporter confExporter;
   private RulesProfile profile;
-  private Configuration conf;
+  private Settings conf;
   private ProjectFileSystem fileSystem;
 
-  public CheckstyleConfiguration(Configuration conf, CheckstyleProfileExporter confExporter, RulesProfile profile, ProjectFileSystem fileSystem) {
+  public CheckstyleConfiguration(Settings conf, CheckstyleProfileExporter confExporter, RulesProfile profile, ProjectFileSystem fileSystem) {
     this.conf = conf;
     this.confExporter = confExporter;
     this.profile = profile;
@@ -79,7 +86,7 @@ public class CheckstyleConfiguration implements BatchExtension {
   }
 
   public File getTargetXMLReport() {
-    if (conf.getBoolean(CheckstyleConstants.GENERATE_XML_KEY, CheckstyleConstants.GENERATE_XML_DEFAULT_VALUE)) {
+    if (conf.getBoolean(PROPERTY_GENERATE_XML)) {
       return new File(fileSystem.getSonarWorkingDirectory(), "checkstyle-result.xml");
     }
     return null;
@@ -112,7 +119,7 @@ public class CheckstyleConfiguration implements BatchExtension {
   }
 
   public Locale getLocale() {
-    return new Locale(conf.getString(CoreProperties.CORE_VIOLATION_LOCALE_PROPERTY, CoreProperties.CORE_VIOLATION_LOCALE_DEFAULT_VALUE));
+    return new Locale(conf.getString(CoreProperties.CORE_VIOLATION_LOCALE_PROPERTY));
   }
 
   public Charset getCharset() {
index e110efcba8467899f6d61414f20f026a01778833..5299f047598f4b5bca855110c50d8f254055ffb1 100644 (file)
@@ -30,8 +30,6 @@ public final class CheckstyleConstants {
   public static final String FILTERS_KEY = "sonar.checkstyle.filters";
 
   public static final String FILTERS_DEFAULT_VALUE = "<module name=\"SuppressionCommentFilter\"/>";
-  public static final String GENERATE_XML_KEY = "sonar.checkstyle.generateXml";
-  public static final boolean GENERATE_XML_DEFAULT_VALUE = false;
 
   private CheckstyleConstants() {
   }
index dac37703a987367b1e93a3d9e5bd4b7876de75e2..e14bac06bb805da3e06db447fc82ca408937db4e 100644 (file)
@@ -19,9 +19,9 @@
  */
 package org.sonar.plugins.checkstyle;
 
-import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.io.FileUtils;
 import org.junit.Test;
+import org.sonar.api.config.Settings;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.resources.Project;
 import org.sonar.api.test.MavenTestUtils;
@@ -48,12 +48,6 @@ public class CheckstyleConfigurationTest {
     assertThat(FileUtils.readFileToString(xmlFile), is("<conf/>"));
   }
 
-  @Test
-  public void shouldGetDefaultLocaleForMessages() {
-    CheckstyleConfiguration configuration = new CheckstyleConfiguration(new PropertiesConfiguration(), null, null, null);
-    assertThat(configuration.getLocale(), is(Locale.ENGLISH));
-  }
-
   public class FakeExporter extends CheckstyleProfileExporter {
     @Override
     public void exportProfile(RulesProfile profile, Writer writer) {
index 354e00c9e379dcea8b92ea6cbafe7a4a54b76799..75f70be23f0c076644d0e984c4071e58a5904581 100644 (file)
@@ -176,7 +176,38 @@ import java.util.List;
         project = true,
         global = false,
         defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_5,
-        category = CoreProperties.CATEGORY_DIFFERENTIAL_VIEWS)
+        category = CoreProperties.CATEGORY_DIFFERENTIAL_VIEWS),
+
+
+    // SERVER-SIDE TECHNICAL PROPERTIES
+
+    @Property(
+        key = "sonar.useStructureDump",
+        name = "Use Structure Dump",
+        description = "Used when creating database schema",
+        project = false,
+        global = false,
+        defaultValue = "true"),
+    @Property(
+        key = "sonar.authenticator.downcase",
+        name = "Downcase login",
+        description = "Downcase login during user authentication, typically for Active Directory",
+        project = false,
+        global = false,
+        defaultValue = "false"),
+    @Property(
+        key = CoreProperties.CORE_AUTHENTICATOR_CREATE_USERS,
+        name = "Create user accounts",
+        description = "Create accounts when authenticating users via an external system",
+        project = false,
+        global = false,
+        defaultValue = "false"),
+    @Property(
+        key = CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE,
+        name = "Ignore failures during authenticator startup",
+        defaultValue = "false",
+        project = false,
+        global = false)
 })
 public class CorePlugin extends SonarPlugin {
 
index b8409fbaa64cae3f75c508aed66516d1051dd6b8..0832a7a58ff5a44e6a3d44d980888dcb5e8ea50b 100644 (file)
@@ -32,17 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
       <fileset dir="../extensions/jdbc-driver" includes="**/*.jar"/>
     </copy>
 
-    <!-- sonar properties -->
-    <copy todir="build/sonar-server/WEB-INF/classes/conf" file="../conf/sonar.properties" overwrite="true"
-          failonerror="true"/>
-
-    <condition property="sonarhome.found">
-      <isfileselected file="build/sonar-server/WEB-INF/classes/conf/sonar.properties">
-        <contains text="sonar.home"/>
-      </isfileselected>
-    </condition>
-
-    <antcall target="append-sonar-home"/>
+    <replace file="build/sonar-server/WEB-INF/classes/sonar-war.properties" token="#sonar.home=" value="sonar.home=${sonarHome}" />
 
     <!-- copy the logback config -->
     <copy todir="build/sonar-server/WEB-INF/classes">
@@ -75,10 +65,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
       * supported web servers are Jetty and Tomcat 5.x/6.x/7.x
       * the web application uses the Sonar home directory. For this reason it must be deployed on this host only.
       * the war file must be rebuilt when :
-      - configuration is updated (files in the directory conf/)
-      - the Sonar home directory is moved to other location
-      - sonar is upgraded to a new version
-      It does not have to be rebuilt when a plugin is removed or installed.
+        - logback configuration is updated (conf/logback.xml)
+        - the Sonar home directory is moved to other location
+        - sonar is upgraded to a new version
       -----------------------------------------------------------------------------------------------------------
     </echo>
   </target>
@@ -87,12 +76,4 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
     <delete dir="build"/>
     <delete file="sonar.war"/>
   </target>
-
-  <target name="append-sonar-home" unless="sonarhome.found">
-    <echo>Setting home to: ${sonarHome}</echo>
-    <echo file="build/sonar-server/WEB-INF/classes/conf/sonar.properties" append="yes">
-      sonar.home=${sonarHome}
-    </echo>
-  </target>
-
 </project>
\ No newline at end of file
index 2461b865064450811f7fa076ffc92800a3657648..70c92d060974967ac68fb2cd8724e2d504432e32 100644 (file)
@@ -30,11 +30,11 @@ public final class Batch {
   private Module bootstrapModule;
 
   /**
-   * @deprecated since 2.9. Replaced by the factory method.
+   * @deprecated since 2.9. Replaced by the factory method. Use by Ant Task 1.1
    */
   @Deprecated
   public Batch(Configuration configuration, Object... bootstrapperComponents) {
-    this.bootstrapModule = new BootstrapModule(extractProjectReactor(bootstrapperComponents), configuration, bootstrapperComponents).init();
+    this.bootstrapModule = new BootstrapModule(extractProjectReactor(bootstrapperComponents), bootstrapperComponents).init();
   }
 
   static ProjectReactor extractProjectReactor(Object[] components) {
@@ -54,12 +54,12 @@ public final class Batch {
     return deprecatedReactor.toProjectReactor();
   }
 
-  private Batch(ProjectReactor reactor, Configuration configuration, Object... bootstrapperComponents) {
-    this.bootstrapModule = new BootstrapModule(reactor, configuration, bootstrapperComponents).init();
+  private Batch(ProjectReactor reactor, Object... bootstrapperComponents) {
+    this.bootstrapModule = new BootstrapModule(reactor, bootstrapperComponents).init();
   }
 
   public static Batch create(ProjectReactor projectReactor, Configuration configuration, Object... bootstrapperComponents) {
-    return new Batch(projectReactor, configuration, bootstrapperComponents);
+    return new Batch(projectReactor, bootstrapperComponents);
   }
 
   /**
index 6659aa5618f590d526ecdd5f1301ea2734963c0f..ed9db7d9e05be772929e8968a4a40c2a93033500 100644 (file)
  */
 package org.sonar.batch;
 
-import org.apache.commons.configuration.*;
+import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.time.DateUtils;
 import org.apache.maven.project.MavenProject;
+import org.sonar.api.BatchComponent;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.ResourceModel;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Java;
 import org.sonar.api.resources.Project;
-import org.sonar.api.utils.SonarException;
 
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 
-public class ProjectConfigurator {
+public class ProjectConfigurator implements BatchComponent {
 
   private DatabaseSession databaseSession;
+  private Settings settings;
 
-  public ProjectConfigurator(DatabaseSession databaseSession) {
+  public ProjectConfigurator(DatabaseSession databaseSession, Settings settings) {
     this.databaseSession = databaseSession;
+    this.settings = settings;
   }
 
   public Project create(ProjectDefinition definition) {
-    Configuration configuration = getStartupConfiguration(definition);
-    Project project = new Project(definition.getKey(), loadProjectBranch(configuration), definition.getName())
-        .setDescription(StringUtils.defaultString(definition.getDescription(), ""))
-        .setPackaging("jar");
+    Project project = new Project(definition.getKey(), loadProjectBranch(), definition.getName());
+
     // For backward compatibility we must set POM and actual packaging
+    project.setDescription(StringUtils.defaultString(definition.getDescription()));
+    project.setPackaging("jar");
+    
     for (Object component : definition.getContainerExtensions()) {
       if (component instanceof MavenProject) {
         MavenProject pom = (MavenProject) component;
@@ -61,39 +61,25 @@ public class ProjectConfigurator {
     return project;
   }
 
-  Configuration getStartupConfiguration(ProjectDefinition project) {
-    CompositeConfiguration configuration = new CompositeConfiguration();
-    configuration.addConfiguration(new SystemConfiguration());
-    configuration.addConfiguration(new EnvironmentConfiguration());
-    configuration.addConfiguration(new MapConfiguration(project.getProperties()));
-    return configuration;
-  }
-
-  String loadProjectBranch(Configuration configuration) {
-    return configuration.getString(CoreProperties.PROJECT_BRANCH_PROPERTY);
-  }
-
-  public void configure(Project project, ProjectDefinition def) {
-    ProjectConfiguration projectConfiguration = new ProjectConfiguration(databaseSession, def);
-    configure(project, projectConfiguration);
+  String loadProjectBranch() {
+    return settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY);
   }
 
-  void configure(Project project, Configuration projectConfiguration) {
-    Date analysisDate = loadAnalysisDate(projectConfiguration);
-    project.setConfiguration(projectConfiguration)
-        .setExclusionPatterns(loadExclusionPatterns(projectConfiguration))
+  public ProjectConfigurator configure(Project project) {
+    Date analysisDate = loadAnalysisDate();
+    project
+        .setConfiguration(new PropertiesConfiguration()) // will be populated by ProjectSettings
+        .setExclusionPatterns(loadExclusionPatterns())
         .setAnalysisDate(analysisDate)
         .setLatestAnalysis(isLatestAnalysis(project.getKey(), analysisDate))
-        .setAnalysisVersion(loadAnalysisVersion(projectConfiguration))
-        .setAnalysisType(loadAnalysisType(projectConfiguration))
-        .setLanguageKey(loadLanguageKey(projectConfiguration));
+        .setAnalysisVersion(loadAnalysisVersion())
+        .setAnalysisType(loadAnalysisType())
+        .setLanguageKey(loadLanguageKey());
+    return this;
   }
 
-  static String[] loadExclusionPatterns(Configuration configuration) {
-    String[] exclusionPatterns = configuration.getStringArray(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY);
-    if (exclusionPatterns == null) {
-      exclusionPatterns = new String[0];
-    }
+  String[] loadExclusionPatterns() {
+    String[] exclusionPatterns = settings.getStringArray(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY);
     for (int i = 0; i < exclusionPatterns.length; i++) {
       exclusionPatterns[i] = StringUtils.trim(exclusionPatterns[i]);
     }
@@ -109,28 +95,18 @@ public class ProjectConfigurator {
     return true;
   }
 
-  Date loadAnalysisDate(Configuration configuration) {
-    String formattedDate = configuration.getString(CoreProperties.PROJECT_DATE_PROPERTY);
-    if (formattedDate == null) {
-      return new Date();
-    }
-
-    DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
-    try {
-      // see SONAR-908 make sure that a time is defined for the date.
-      Date date = DateUtils.setHours(format.parse(formattedDate), 0);
-      return DateUtils.setMinutes(date, 1);
-
-    } catch (ParseException e) {
-      throw new SonarException("The property " + CoreProperties.PROJECT_DATE_PROPERTY
-          + " does not respect the format yyyy-MM-dd (for example 2008-05-23) : " + formattedDate, e);
+  Date loadAnalysisDate() {
+    Date date = settings.getDate(CoreProperties.PROJECT_DATE_PROPERTY);
+    if (date == null) {
+      date = new Date();
     }
+    return date;
   }
 
-  Project.AnalysisType loadAnalysisType(Configuration configuration) {
-    String value = configuration.getString(CoreProperties.DYNAMIC_ANALYSIS_PROPERTY);
+  Project.AnalysisType loadAnalysisType() {
+    String value = settings.getString(CoreProperties.DYNAMIC_ANALYSIS_PROPERTY);
     if (value == null) {
-      return (configuration.getBoolean("sonar.light", false) ? Project.AnalysisType.STATIC : Project.AnalysisType.DYNAMIC);
+      return ("true".equals(settings.getString("sonar.light")) ? Project.AnalysisType.STATIC : Project.AnalysisType.DYNAMIC);
     }
     if ("true".equals(value)) {
       return Project.AnalysisType.DYNAMIC;
@@ -141,11 +117,11 @@ public class ProjectConfigurator {
     return Project.AnalysisType.STATIC;
   }
 
-  String loadAnalysisVersion(Configuration configuration) {
-    return configuration.getString(CoreProperties.PROJECT_VERSION_PROPERTY);
+  String loadAnalysisVersion() {
+    return settings.getString(CoreProperties.PROJECT_VERSION_PROPERTY);
   }
 
-  String loadLanguageKey(Configuration configuration) {
-    return configuration.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY, Java.KEY);
+  String loadLanguageKey() {
+    return StringUtils.defaultIfBlank(settings.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY), Java.KEY);
   }
 }
index 10548b7169edb429fc6eb334ed962ff77d038518..7d9524ca93bc93c78c92d6c86f3911ddb884d0c2 100644 (file)
@@ -21,13 +21,13 @@ package org.sonar.batch;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.LoggerFactory;
 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.database.DatabaseSession;
 import org.sonar.api.resources.Project;
 
 import java.io.IOException;
@@ -42,14 +42,15 @@ public class ProjectTree {
   private Map<ProjectDefinition, Project> projectsByDef;
 
   public ProjectTree(ProjectReactor projectReactor, //NOSONAR the unused parameter 'builders' is used for the startup order of components
-                     DatabaseSession databaseSession,
+                     ProjectConfigurator projectConfigurator,
                      /* Must be executed after ProjectBuilders */ ProjectBuilder[] builders) {
-    this(projectReactor, databaseSession);
+    this(projectReactor, projectConfigurator);
   }
 
-  public ProjectTree(ProjectReactor projectReactor, DatabaseSession databaseSession) {
-    configurator = new ProjectConfigurator(databaseSession);
+  public ProjectTree(ProjectReactor projectReactor, //NOSONAR the unused parameter 'builders' is used for the startup order of components
+                     ProjectConfigurator projectConfigurator) {
     this.projectReactor = projectReactor;
+    this.configurator = projectConfigurator;
   }
 
   ProjectTree(ProjectConfigurator configurator) {
@@ -79,8 +80,8 @@ public class ProjectTree {
     }
 
     // Configure
-    for (Map.Entry<ProjectDefinition, Project> entry : projectsByDef.entrySet()) {
-      configurator.configure(entry.getValue(), entry.getKey());
+    for (Project project : projects) {
+      configurator.configure(project);
     }
 
     applyExclusions();
@@ -91,8 +92,8 @@ public class ProjectTree {
       String[] excludedArtifactIds = project.getConfiguration().getStringArray("sonar.skippedModules");
       String[] includedArtifactIds = project.getConfiguration().getStringArray("sonar.includedModules");
 
-      Set<String> includedModulesIdSet = new HashSet<String>();
-      Set<String> excludedModulesIdSet = new HashSet<String>();
+      Set<String> includedModulesIdSet = Sets.newHashSet();
+      Set<String> excludedModulesIdSet = Sets.newHashSet();
 
       if (includedArtifactIds != null) {
         includedModulesIdSet.addAll(Arrays.asList(includedArtifactIds));
index 97dae9df62f468b5273da12dfe7a6d541615d6b8..fcd0951dd522514125d543b0719699b2ca9cd5c0 100644 (file)
  */
 package org.sonar.batch;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 import org.sonar.api.platform.Server;
 
 import java.text.ParseException;
@@ -31,22 +31,22 @@ import java.util.Date;
 
 public class ServerMetadata extends Server {
 
-  private Configuration conf;
+  private Settings settings;
 
-  public ServerMetadata(Configuration conf) {
-    this.conf = conf;
+  public ServerMetadata(Settings settings) {
+    this.settings = settings;
   }
 
   public String getId() {
-    return conf.getString(CoreProperties.SERVER_ID);
+    return settings.getString(CoreProperties.SERVER_ID);
   }
 
   public String getVersion() {
-    return conf.getString(CoreProperties.SERVER_VERSION);
+    return settings.getString(CoreProperties.SERVER_VERSION);
   }
 
   public Date getStartedAt() {
-    String dateString = conf.getString(CoreProperties.SERVER_STARTTIME);
+    String dateString = settings.getString(CoreProperties.SERVER_STARTTIME);
     if (dateString != null) {
       try {
         return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(dateString);
@@ -59,11 +59,11 @@ public class ServerMetadata extends Server {
   }
 
   public String getURL() {
-    return StringUtils.removeEnd(conf.getString("sonar.host.url", "http://localhost:9000"), "/");
+    return StringUtils.removeEnd(StringUtils.defaultIfBlank(settings.getString("sonar.host.url"), "http://localhost:9000"), "/");
   }
 
   @Override
   public String getPermanentServerId() {
-    return conf.getString(CoreProperties.PERMANENT_SERVER_ID);
+    return settings.getString(CoreProperties.PERMANENT_SERVER_ID);
   }
 }
index 75dec73bac888f15aef6f2216f6b3f817e210b4c..4a690ac1a459e8aeb6cff75d5670445deb6843c5 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
 import org.sonar.api.BatchComponent;
+import org.sonar.api.Extension;
 import org.sonar.api.ExtensionProvider;
 import org.sonar.api.Plugin;
 import org.sonar.api.batch.CoverageExtension;
 import org.sonar.api.batch.InstantiationStrategy;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.measures.Metrics;
+import org.sonar.api.platform.PluginMetadata;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
 
-import java.util.List;
+import java.util.Map;
 
 public final class BatchExtensionInstaller implements BatchComponent {
 
@@ -43,40 +47,63 @@ public final class BatchExtensionInstaller implements BatchComponent {
   }
 
   public void install(Module module) {
-    for (Plugin plugin : pluginRepository.getPlugins()) {
+    ListMultimap<PluginMetadata, Object> installedExtensionsByPlugin = ArrayListMultimap.create();
+    for (Map.Entry<PluginMetadata, Plugin> entry : pluginRepository.getPluginsByMetadata().entrySet()) {
+      PluginMetadata metadata = entry.getKey();
+      Plugin plugin = entry.getValue();
+      
+      module.addExtension(metadata, plugin);
+
       for (Object extension : plugin.getExtensions()) {
-        installExtension(module, extension);
+        if (installExtension(module, metadata, extension)) {
+          installedExtensionsByPlugin.put(metadata, extension);
+        } else {
+          module.declareExtension(metadata, extension);
+        }
+      }
+    }
+    for (Map.Entry<PluginMetadata, Object> entry : installedExtensionsByPlugin.entries()) {
+      PluginMetadata plugin = entry.getKey();
+      Object extension = entry.getValue();
+      if (isExtensionProvider(extension)) {
+        ExtensionProvider provider = (ExtensionProvider) module.getComponentByKey(extension);
+        installProvider(module, plugin, provider);
       }
     }
-    installExtensionProviders(module);
     installMetrics(module);
   }
 
+  static boolean isExtensionProvider(Object extension) {
+    return isType(extension, ExtensionProvider.class) || extension instanceof ExtensionProvider;
+  }
+
+  static boolean isType(Object extension, Class<? extends Extension> extensionClass) {
+    Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass());
+    return extensionClass.isAssignableFrom(clazz);
+  }
+
   private void installMetrics(Module module) {
     for (Metrics metrics : module.getComponents(Metrics.class)) {
       for (Metric metric : metrics.getMetrics()) {
-        module.addComponent(metric.getKey(), metric);
+        module.addCoreSingleton(metric);
       }
     }
   }
 
-  void installExtensionProviders(Module module) {
-    List<ExtensionProvider> providers = module.getComponents(ExtensionProvider.class);
-    for (ExtensionProvider provider : providers) {
-      Object obj = provider.provide();
-      if (obj != null) {
-        if (obj instanceof Iterable) {
-          for (Object extension : (Iterable) obj) {
-            installExtension(module, extension);
-          }
-        } else {
-          installExtension(module, obj);
+  private void installProvider(Module module, PluginMetadata plugin, ExtensionProvider provider) {
+    Object obj = provider.provide();
+    if (obj != null) {
+      if (obj instanceof Iterable) {
+        for (Object ext : (Iterable) obj) {
+          installExtension(module, plugin, ext);
         }
+      } else {
+        installExtension(module, plugin, obj);
       }
     }
   }
 
-  void installExtension(Module module, Object extension) {
+  boolean installExtension(Module module, PluginMetadata plugin, Object extension) {
     if (ExtensionUtils.isBatchExtension(extension) &&
         ExtensionUtils.isSupportedEnvironment(extension, environment) &&
         ExtensionUtils.checkDryRun(extension, dryRun.isEnabled()) &&
@@ -84,7 +111,9 @@ public final class BatchExtensionInstaller implements BatchComponent {
       if (ExtensionUtils.isType(extension, CoverageExtension.class)) {
         throw new IllegalArgumentException("Instantiation strategy " + InstantiationStrategy.PER_BATCH + " is not supported on CoverageExtension components: " + extension);
       }
-      module.addComponent(extension);
+      module.addExtension(plugin, extension);
+      return true;
     }
+    return false;
   }
 }
index 3134c5ec39ffd354fffb004b7c5cd8ad6247a7f5..822d6ca7a8d94ced466c5069b358e44a55648f55 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.measures.Metric;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.ServerHttpClient;
 import org.sonar.batch.DefaultResourceCreationLock;
-import org.sonar.batch.ProjectConfiguration;
+import org.sonar.batch.ProjectConfigurator;
 import org.sonar.batch.ProjectTree;
 import org.sonar.batch.components.*;
 import org.sonar.batch.index.*;
@@ -48,55 +48,55 @@ public class BatchModule extends Module {
 
   @Override
   protected void configure() {
-    addComponent(ProjectConfiguration.class);
-    addComponent(ProjectTree.class);
-    addComponent(DefaultResourceCreationLock.class);
-    addComponent(DefaultIndex.class);
+    addCoreSingleton(ProjectTree.class);
+    addCoreSingleton(ProjectConfigurator.class);
+    addCoreSingleton(DefaultResourceCreationLock.class);
+    addCoreSingleton(DefaultIndex.class);
 
     if (dryRun) {
-      addComponent(ReadOnlyPersistenceManager.class);
+      addCoreSingleton(ReadOnlyPersistenceManager.class);
     } else {
-      addComponent(DefaultPersistenceManager.class);
-      addComponent(DependencyPersister.class);
-      addComponent(EventPersister.class);
-      addComponent(LinkPersister.class);
-      addComponent(MeasurePersister.class);
-      addComponent(MemoryOptimizer.class);
-      addComponent(DefaultResourcePersister.class);
-      addComponent(SourcePersister.class);
+      addCoreSingleton(DefaultPersistenceManager.class);
+      addCoreSingleton(DependencyPersister.class);
+      addCoreSingleton(EventPersister.class);
+      addCoreSingleton(LinkPersister.class);
+      addCoreSingleton(MeasurePersister.class);
+      addCoreSingleton(MemoryOptimizer.class);
+      addCoreSingleton(DefaultResourcePersister.class);
+      addCoreSingleton(SourcePersister.class);
     }
 
-    addComponent(Plugins.class);
-    addComponent(ServerHttpClient.class);
-    addComponent(MeasuresDao.class);
-    addComponent(CacheRuleFinder.class);
-    addComponent(CacheMetricFinder.class);
-    addComponent(PastSnapshotFinderByDate.class);
-    addComponent(PastSnapshotFinderByDays.class);
-    addComponent(PastSnapshotFinderByPreviousAnalysis.class);
-    addComponent(PastSnapshotFinderByVersion.class);
-    addComponent(PastMeasuresLoader.class);
-    addComponent(PastSnapshotFinder.class);
-    addComponent(DefaultNotificationManager.class);
-    addComponent(DefaultUserFinder.class);
+    addCoreSingleton(Plugins.class);
+    addCoreSingleton(ServerHttpClient.class);
+    addCoreSingleton(MeasuresDao.class);
+    addCoreSingleton(CacheRuleFinder.class);
+    addCoreSingleton(CacheMetricFinder.class);
+    addCoreSingleton(PastSnapshotFinderByDate.class);
+    addCoreSingleton(PastSnapshotFinderByDays.class);
+    addCoreSingleton(PastSnapshotFinderByPreviousAnalysis.class);
+    addCoreSingleton(PastSnapshotFinderByVersion.class);
+    addCoreSingleton(PastMeasuresLoader.class);
+    addCoreSingleton(PastSnapshotFinder.class);
+    addCoreSingleton(DefaultNotificationManager.class);
+    addCoreSingleton(DefaultUserFinder.class);
     addCoreMetrics();
     addBatchExtensions();
   }
 
   private void addBatchExtensions() {
-    BatchExtensionInstaller installer = getComponent(BatchExtensionInstaller.class);
+    BatchExtensionInstaller installer = getComponentByType(BatchExtensionInstaller.class);
     installer.install(this);
   }
 
   void addCoreMetrics() {
     for (Metric metric : CoreMetrics.getMetrics()) {
-      addComponent(metric.getKey(), metric);
+      addCoreSingleton(metric);
     }
   }
 
   @Override
   protected void doStart() {
-    ProjectTree projectTree = getComponent(ProjectTree.class);
+    ProjectTree projectTree = getComponentByType(ProjectTree.class);
     analyze(projectTree.getRootProject());
   }
 
@@ -110,7 +110,7 @@ public class BatchModule extends Module {
       projectComponents.start();
     } finally {
       projectComponents.stop();
-      uninstallChild(projectComponents);
+      uninstallChild();
     }
   }
 }
index 249c94b79b7d65278df836baf01e4e05a3a05c12..27061aadc67a9a423054bbe42b37eb81a534e39b 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.batch.bootstrap;
 import com.google.common.base.Joiner;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -30,6 +29,7 @@ import org.sonar.api.CoreProperties;
 import org.sonar.api.Plugin;
 import org.sonar.api.Properties;
 import org.sonar.api.Property;
+import org.sonar.api.config.Settings;
 import org.sonar.api.platform.PluginMetadata;
 import org.sonar.api.platform.PluginRepository;
 import org.sonar.core.plugins.PluginClassloaders;
@@ -51,14 +51,14 @@ public class BatchPluginRepository implements PluginRepository {
   private Set<String> blackList = null;
   private PluginClassloaders classLoaders;
 
-  public BatchPluginRepository(ArtifactDownloader artifactDownloader, Configuration configuration) {
+  public BatchPluginRepository(ArtifactDownloader artifactDownloader, Settings settings) {
     this.artifactDownloader = artifactDownloader;
-    if (configuration.getString(CoreProperties.BATCH_INCLUDE_PLUGINS) != null) {
-      whiteList = Sets.newTreeSet(Arrays.asList(configuration.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS)));
+    if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) {
+      whiteList = Sets.newTreeSet(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS)));
       LOG.info("Include plugins: " + Joiner.on(", ").join(whiteList));
     }
-    if (configuration.getString(CoreProperties.BATCH_EXCLUDE_PLUGINS) != null) {
-      blackList = Sets.newTreeSet(Arrays.asList(configuration.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS)));
+    if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) {
+      blackList = Sets.newTreeSet(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS)));
       LOG.info("Exclude plugins: " + Joiner.on(", ").join(blackList));
     }
     // TODO reactivate somewhere else:  LOG.info("Execution environment: {} {}", environment.getKey(), environment.getVersion());
@@ -133,4 +133,14 @@ public class BatchPluginRepository implements PluginRepository {
     }
     return blackList == null || !blackList.contains(pluginKey);
   }
+
+  public Map<PluginMetadata,Plugin> getPluginsByMetadata() {
+    Map<PluginMetadata, Plugin> result = Maps.newHashMap();
+    for (Map.Entry<String, PluginMetadata> entry : metadataByKey.entrySet()) {
+      String pluginKey = entry.getKey();
+      PluginMetadata metadata = entry.getValue();
+      result.put(metadata, pluginsByKey.get(pluginKey));
+    }
+    return result;
+  }
 }
index 2c925b71674a53cdc35becf3cda7e95a26d16539..ce6985b8c2e75c25a5074e72895644e94ff99268 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
-import org.apache.commons.configuration.Configuration;
-import org.sonar.api.Plugin;
+import org.apache.commons.configuration.PropertiesConfiguration;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.api.config.Settings;
 import org.sonar.api.utils.HttpDownloader;
 import org.sonar.batch.FakeMavenPluginExecutor;
 import org.sonar.batch.MavenPluginExecutor;
 import org.sonar.batch.ServerMetadata;
+import org.sonar.batch.config.BatchSettings;
+import org.sonar.batch.config.BatchSettingsEnhancer;
 import org.sonar.jpa.session.DatabaseSessionProvider;
 import org.sonar.jpa.session.DriverDatabaseConnector;
 import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
@@ -37,52 +39,52 @@ import java.net.URLClassLoader;
  */
 public class BootstrapModule extends Module {
 
-  private Configuration configuration;
   private Object[] boostrapperComponents;
   private ProjectReactor reactor;
 
-  public BootstrapModule(ProjectReactor reactor, Configuration configuration, Object... boostrapperComponents) {
+  public BootstrapModule(ProjectReactor reactor, Object... boostrapperComponents) {
     this.reactor = reactor;
-    this.configuration = configuration;
     this.boostrapperComponents = boostrapperComponents;
   }
 
   @Override
   protected void configure() {
-    addComponent(reactor);
-    addComponent(configuration);// this configuration does not access database
-    addComponent(DryRun.class);
-    addComponent(ServerMetadata.class);// registered here because used by BootstrapClassLoader
-    addComponent(TempDirectories.class);// registered here because used by BootstrapClassLoader
-    addComponent(HttpDownloader.class);// registered here because used by BootstrapClassLoader
-    addComponent(ArtifactDownloader.class);// registered here because used by BootstrapClassLoader
-    addComponent(JdbcDriverHolder.class);
+    addCoreSingleton(reactor);
+    addCoreSingleton(new PropertiesConfiguration());
+    addCoreSingleton(BatchSettings.class);
+    addCoreSingleton(DryRun.class);
+    addCoreSingleton(ServerMetadata.class);// registered here because used by BootstrapClassLoader
+    addCoreSingleton(TempDirectories.class);// registered here because used by BootstrapClassLoader
+    addCoreSingleton(HttpDownloader.class);// registered here because used by BootstrapClassLoader
+    addCoreSingleton(ArtifactDownloader.class);// registered here because used by BootstrapClassLoader
+    addCoreSingleton(JdbcDriverHolder.class);
 
-    URLClassLoader bootstrapClassLoader = getComponent(JdbcDriverHolder.class).getClassLoader();
+    URLClassLoader bootstrapClassLoader = getComponentByType(JdbcDriverHolder.class).getClassLoader();
     // set as the current context classloader for hibernate, else it does not find the JDBC driver.
     Thread.currentThread().setContextClassLoader(bootstrapClassLoader);
 
-    addComponent(new DriverDatabaseConnector(configuration, bootstrapClassLoader));
-    addComponent(ThreadLocalDatabaseSessionFactory.class);
+    addCoreSingleton(new DriverDatabaseConnector(getComponentByType(Settings.class), bootstrapClassLoader));
+    addCoreSingleton(ThreadLocalDatabaseSessionFactory.class);
     addAdapter(new DatabaseSessionProvider());
     for (Object component : boostrapperComponents) {
-      addComponent(component);
+      addCoreSingleton(component);
     }
     if (!isMavenPluginExecutorRegistered()) {
-      addComponent(FakeMavenPluginExecutor.class);
+      addCoreSingleton(FakeMavenPluginExecutor.class);
     }
 
-    // LIMITATION : list of plugins to download is currently loaded from database. It should be loaded from
-    // remote HTTP index.
-    addComponent(BatchPluginRepository.class);
-    addComponent(BatchExtensionInstaller.class);
-    addComponent(ProjectExtensionInstaller.class);
+    addCoreSingleton(BatchPluginRepository.class);
+    addCoreSingleton(BatchExtensionInstaller.class);
+    addCoreSingleton(ProjectExtensionInstaller.class);
+    addCoreSingleton(BatchSettingsEnhancer.class);
   }
 
   boolean isMavenPluginExecutorRegistered() {
-    for (Object component : boostrapperComponents) {
-      if (component instanceof Class && MavenPluginExecutor.class.isAssignableFrom((Class<?>) component)) {
-        return true;
+    if (boostrapperComponents != null) {
+      for (Object component : boostrapperComponents) {
+        if (component instanceof Class && MavenPluginExecutor.class.isAssignableFrom((Class<?>) component)) {
+          return true;
+        }
       }
     }
     return false;
@@ -90,19 +92,8 @@ public class BootstrapModule extends Module {
 
   @Override
   protected void doStart() {
-    addPlugins();
-    boolean dryRun = getComponent(DryRun.class).isEnabled();
+    boolean dryRun = getComponentByType(DryRun.class).isEnabled();
     Module batchComponents = installChild(new BatchModule(dryRun));
     batchComponents.start();
   }
-
-  private void addPlugins() {
-    // Plugins have been loaded during the startup of BatchPluginRepository.
-    // In a perfect world BatchPluginRepository should be a factory which injects new components into container, but
-    // (it seems that) this feature does not exist in PicoContainer.
-    // Limitation: the methods start() and stop() are not called on org.sonar.api.Plugin instances.
-    for (Plugin plugin : getComponent(BatchPluginRepository.class).getPlugins()) {
-      addComponent(plugin);
-    }
-  }
 }
index c269fc6b126e3a7652451e77d6b5dae04b3ea113..c3a96ab63de3de7e2480abc3f860b9d00c4f7184 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
-import org.apache.commons.configuration.Configuration;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.Property;
+import org.sonar.api.config.Settings;
 import org.sonar.api.utils.Logs;
 
-public class DryRun {
+@Property(key="sonar.dryRun", defaultValue = "false", name="Dry Run")
+public class DryRun implements BatchComponent {
   private boolean enabled;
 
-  public DryRun(Configuration conf) {
-    enabled = conf.getBoolean("sonar.dryRun", Boolean.FALSE);
+  public DryRun(Settings settings) {
+    enabled = settings.getBoolean("sonar.dryRun");
     if (enabled) {
       Logs.INFO.info("Dry run");
     }
index df9991e89a50e35ada10b51971d29d18c7a84b4c..bba921ab6de89ca664e2d6ef29138f9d1e1418ae 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
-import org.picocontainer.Characteristics;
 import org.picocontainer.ComponentAdapter;
-import org.picocontainer.MutablePicoContainer;
-import org.sonar.api.utils.IocContainer;
+import org.sonar.api.platform.ComponentContainer;
+import org.sonar.api.platform.PluginMetadata;
 
 import java.util.List;
 
@@ -33,20 +32,19 @@ import java.util.List;
  */
 public abstract class Module {
 
-  private MutablePicoContainer container;
-
+  ComponentContainer container;
 
   /**
    * @return this
    */
   public final Module init() {
-    return init(IocContainer.buildPicoContainer());
+    return init(new ComponentContainer());
   }
 
   /**
    * @return this
    */
-  private Module init(MutablePicoContainer container) {
+  private Module init(ComponentContainer container) {
     this.container = container;
     configure();
     return this;
@@ -68,24 +66,23 @@ public abstract class Module {
    * @return installed module
    */
   public final Module installChild(Module child) {
-    MutablePicoContainer childContainer = container.makeChildContainer();
+    ComponentContainer childContainer = container.createChild();
     // register container as a component, because it used for example in BatchExtensionDictionnary,
     // but in fact this is anti-pattern - http://picocontainer.codehaus.org/container-dependency-antipattern.html
-    childContainer.addComponent(new IocContainer(childContainer));
-    childContainer.setName(child.toString());
+    //childContainer.addComponent(new IocContainer(childContainer));
     child.init(childContainer);
     return child;
   }
 
-  public final void uninstallChild(Module child) {
-    container.removeChildContainer(child.container);
+  public final void uninstallChild() {
+    container.removeChild();
   }
 
   /**
    * @return this
    */
   public final Module start() {
-    container.start();
+    container.startComponents();
     doStart();
     return this;
   }
@@ -100,7 +97,7 @@ public abstract class Module {
   public final Module stop() {
     try {
       doStop();
-      container.stop();
+      container.stopComponents();
     } catch (Exception e) {
       // ignore
     }
@@ -113,39 +110,43 @@ public abstract class Module {
 
   /**
    * Implementation of this method must not contain conditional logic and just should contain several invocations of
-   * {@link #addComponent(Object)}, {@link #addComponent(Object, Object)} or {@link #addAdapter(ComponentAdapter)}.
+   * {@link #addCoreSingleton(Object)}, {@link #addComponent(Object, Object)} or {@link #addAdapter(ComponentAdapter)}.
    */
   protected abstract void configure();
 
-  protected final void addComponent(Object component) {
-    if (component instanceof Class) {
-      container.as(Characteristics.CACHE).addComponent(component);
-    } else {
-      container.as(Characteristics.CACHE).addComponent(component.getClass().getCanonicalName() + "-" + component.toString(), component);
-    }
+  protected final void addCoreSingleton(Object component) {
+    container.addSingleton(component);
   }
 
-  protected final void addComponent(Object componentKey, Object component) {
-    container.as(Characteristics.CACHE).addComponent(componentKey, component);
+  protected final void declareExtension(PluginMetadata plugin, Object extension) {
+    container.declareExtension(plugin, extension);
+  }
+
+  protected final void addExtension(PluginMetadata plugin, Object extension) {
+    container.addExtension(plugin, extension);
   }
 
   protected final void addAdapter(ComponentAdapter<?> componentAdapter) {
-    container.addAdapter(componentAdapter);
+    container.addPicoAdapter(componentAdapter);
   }
 
-  public final <T> T getComponent(Class<T> componentType) {
-    return container.getComponent(componentType);
+  public final <T> T getComponentByType(Class<T> componentType) {
+    return container.getComponentByType(componentType);
   }
 
-  public final <T> List<T> getComponents(Class<T> componentType) {
-    return container.getComponents(componentType);
+  public final Object getComponentByKey(Object key) {
+    return container.getComponentByKey(key);
   }
 
-  /**
-   * TODO should not be used and should be removed
-   */
-  public final MutablePicoContainer getContainer() {
-    return container;
+  public final <T> List<T> getComponents(Class<T> componentType) {
+    return container.getComponentsByType(componentType);
   }
 
+//  /**
+//   * TODO should not be used and should be removed
+//   */
+//  public final MutablePicoContainer getContainer() {
+//    return container;
+//  }
+
 }
index 0ec164f7ca412b7ad82fe86ce0744a9241320f66..145d971387e11a7d95103ca187a8dbe33477bfc1 100644 (file)
@@ -77,7 +77,7 @@ public final class ProjectExtensionInstaller implements BatchComponent {
         ExtensionUtils.checkDryRun(extension, dryRun.isEnabled()) &&
         !isDeactivatedCoverageExtension(extension, project, pluginKey) &&
         !isMavenExtensionOnEmulatedMavenProject(extension, project)) {
-      module.addComponent(extension);
+      module.addCoreSingleton(extension);
       return extension;
     }
     return null;
index c54b8d6d126b669571e13cb7b7256e6c364203bb..5381fc093ed16931432416f14368912d61f4759f 100644 (file)
@@ -29,16 +29,21 @@ import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.ProjectFileSystem;
 import org.sonar.api.rules.DefaultRulesManager;
+import org.sonar.api.utils.IocContainer;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.*;
 import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.config.DeprecatedConfigurationProvider;
+import org.sonar.batch.config.ProjectSettings;
 import org.sonar.batch.events.EventBus;
 import org.sonar.batch.index.DefaultIndex;
 import org.sonar.batch.index.DefaultResourcePersister;
 import org.sonar.batch.phases.Phases;
 import org.sonar.batch.phases.PhasesTimeProfiler;
 import org.sonar.core.components.DefaultModelFinder;
-import org.sonar.jpa.dao.*;
+import org.sonar.jpa.dao.DaoFacade;
+import org.sonar.jpa.dao.ProfilesDao;
+import org.sonar.jpa.dao.RulesDao;
 
 import java.util.Arrays;
 
@@ -62,49 +67,52 @@ public class ProjectModule extends Module {
 
 
   private void addProjectComponents() {
-    ProjectDefinition projectDefinition = getComponent(ProjectTree.class).getProjectDefinition(project);
-    addComponent(projectDefinition);
+    ProjectDefinition projectDefinition = getComponentByType(ProjectTree.class).getProjectDefinition(project);
+    addCoreSingleton(projectDefinition);
+    addCoreSingleton(project);
+    addCoreSingleton(project.getConfiguration());
+    addCoreSingleton(ProjectSettings.class);
+    addAdapter(new DeprecatedConfigurationProvider());
+    addCoreSingleton(IocContainer.class);
+
     for (Object component : projectDefinition.getContainerExtensions()) {
-      addComponent(component);
+      addCoreSingleton(component);
     }
-
-    addComponent(project);
-    addComponent(project.getConfiguration());
-    addComponent(DefaultProjectClasspath.class);
-    addComponent(DefaultProjectFileSystem2.class);
-    addComponent(DaoFacade.class);
-    addComponent(RulesDao.class);
+    addCoreSingleton(DefaultProjectClasspath.class);
+    addCoreSingleton(DefaultProjectFileSystem2.class);
+    addCoreSingleton(DaoFacade.class);
+    addCoreSingleton(RulesDao.class);
 
     if (!dryRun) {
       // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
-      addComponent(getComponent(DefaultResourcePersister.class).getSnapshot(project));
+      addCoreSingleton(getComponentByType(DefaultResourcePersister.class).getSnapshot(project));
     }
-    addComponent(TimeMachineConfiguration.class);
-    addComponent(org.sonar.api.database.daos.MeasuresDao.class);
-    addComponent(ProfilesDao.class);
-    addComponent(DefaultRulesManager.class);
-    addComponent(DefaultSensorContext.class);
-    addComponent(Languages.class);
-    addComponent(BatchExtensionDictionnary.class);
-    addComponent(DefaultTimeMachine.class);
-    addComponent(ViolationFilters.class);
-    addComponent(ResourceFilters.class);
-    addComponent(DefaultModelFinder.class);
-    addComponent(ProfileLoader.class, DefaultProfileLoader.class);
+    addCoreSingleton(TimeMachineConfiguration.class);
+    addCoreSingleton(org.sonar.api.database.daos.MeasuresDao.class);
+    addCoreSingleton(ProfilesDao.class);
+    addCoreSingleton(DefaultRulesManager.class);
+    addCoreSingleton(DefaultSensorContext.class);
+    addCoreSingleton(Languages.class);
+    addCoreSingleton(BatchExtensionDictionnary.class);
+    addCoreSingleton(DefaultTimeMachine.class);
+    addCoreSingleton(ViolationFilters.class);
+    addCoreSingleton(ResourceFilters.class);
+    addCoreSingleton(DefaultModelFinder.class);
+    addCoreSingleton(DefaultProfileLoader.class);
     addAdapter(new ProfileProvider());
   }
 
   private void addCoreComponents() {
-    addComponent(EventBus.class);
-    addComponent(Phases.class);
-    addComponent(PhasesTimeProfiler.class);
+    addCoreSingleton(EventBus.class);
+    addCoreSingleton(Phases.class);
+    addCoreSingleton(PhasesTimeProfiler.class);
     for (Class clazz : Phases.getPhaseClasses(dryRun)) {
-      addComponent(clazz);
+      addCoreSingleton(clazz);
     }
   }
 
   private void addProjectPluginExtensions() {
-    ProjectExtensionInstaller installer = getComponent(ProjectExtensionInstaller.class);
+    ProjectExtensionInstaller installer = getComponentByType(ProjectExtensionInstaller.class);
     installer.install(this, project);
   }
 
@@ -124,22 +132,22 @@ public class ProjectModule extends Module {
    */
   @Override
   protected void doStart() {
-    Language language = getComponent(Languages.class).get(project.getLanguageKey());
+    Language language = getComponentByType(Languages.class).get(project.getLanguageKey());
     if (language == null) {
       throw new SonarException("Language with key '" + project.getLanguageKey() + "' not found");
     }
     project.setLanguage(language);
 
-    DefaultIndex index = getComponent(DefaultIndex.class);
+    DefaultIndex index = getComponentByType(DefaultIndex.class);
     index.setCurrentProject(project,
-        getComponent(ResourceFilters.class),
-        getComponent(ViolationFilters.class),
-        getComponent(RulesProfile.class));
+        getComponentByType(ResourceFilters.class),
+        getComponentByType(ViolationFilters.class),
+        getComponentByType(RulesProfile.class));
 
     // TODO See http://jira.codehaus.org/browse/SONAR-2126
     // previously MavenProjectBuilder was responsible for creation of ProjectFileSystem
-    project.setFileSystem(getComponent(ProjectFileSystem.class));
+    project.setFileSystem(getComponentByType(ProjectFileSystem.class));
 
-    getComponent(Phases.class).execute(project);
+    getComponentByType(Phases.class).execute(project);
   }
 }
diff --git a/sonar-batch/src/main/java/org/sonar/batch/config/BatchSettings.java b/sonar-batch/src/main/java/org/sonar/batch/config/BatchSettings.java
new file mode 100644 (file)
index 0000000..9c86975
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.config;
+
+import org.apache.commons.configuration.Configuration;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.core.config.ConfigurationUtils;
+
+import java.util.Map;
+
+/**
+ * @since 2.12
+ */
+public final class BatchSettings extends Settings {
+  private Configuration deprecatedConfiguration;
+  private ProjectReactor reactor;
+
+  public BatchSettings(PropertyDefinitions propertyDefinitions, ProjectReactor reactor, Configuration deprecatedConfiguration) {
+    super(propertyDefinitions);
+    this.reactor = reactor;
+    this.deprecatedConfiguration = deprecatedConfiguration;
+    load();
+  }
+
+  public BatchSettings load() {
+    clear();
+
+    // order is important -> bottom-up. The last one overrides all the others.
+    addProperties(reactor.getRoot().getProperties());
+    addEnvironmentVariables();
+    addSystemProperties();
+
+    updateDeprecatedCommonsConfiguration();
+
+    return this;
+  }
+
+  public void updateDeprecatedCommonsConfiguration() {
+    ConfigurationUtils.copyToCommonsConfiguration(properties, deprecatedConfiguration);
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/config/BatchSettingsEnhancer.java b/sonar-batch/src/main/java/org/sonar/batch/config/BatchSettingsEnhancer.java
new file mode 100644 (file)
index 0000000..a770fa6
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.config;
+
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.api.database.configuration.Property;
+import org.sonar.core.config.ConfigurationUtils;
+import org.sonar.jpa.session.DatabaseSessionFactory;
+
+import java.util.List;
+
+/**
+ * @since 2.12
+ */
+public final class BatchSettingsEnhancer {
+
+  private DatabaseSessionFactory dbFactory;
+  private BatchSettings settings;
+  private ProjectReactor reactor;
+
+  public BatchSettingsEnhancer(DatabaseSessionFactory dbFactory, BatchSettings settings, ProjectReactor reactor) {
+    this.dbFactory = dbFactory;
+    this.settings = settings;
+    this.reactor = reactor;
+  }
+
+  public void start() {
+    String projectKey = reactor.getRoot().getKey();
+    setIfNotDefined(ConfigurationUtils.getProjectProperties(dbFactory, projectKey));
+    setIfNotDefined(ConfigurationUtils.getGlobalProperties(dbFactory));
+    settings.updateDeprecatedCommonsConfiguration();
+  }
+
+  private void setIfNotDefined(List<Property> dbProperties) {
+    for (Property dbProperty : dbProperties) {
+      if (!settings.hasKey(dbProperty.getKey())) {
+        settings.setProperty(dbProperty.getKey(), dbProperty.getValue());
+      }
+    }
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/config/DeprecatedConfigurationProvider.java b/sonar-batch/src/main/java/org/sonar/batch/config/DeprecatedConfigurationProvider.java
new file mode 100644 (file)
index 0000000..636a5ad
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.config;
+
+import org.apache.commons.configuration.Configuration;
+import org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.resources.Project;
+
+public class DeprecatedConfigurationProvider extends ProviderAdapter {
+
+  public Configuration provide(Project project, ProjectSettings settings) {//NOSONAR the parameter ProjectSettings is declared to be sure that it is initialized
+    // configuration is valid because it has been updated by ProjectSettings
+    return project.getConfiguration();
+  }
+}
+
diff --git a/sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java b/sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java
new file mode 100644 (file)
index 0000000..4fcc837
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.config;
+
+import org.apache.commons.configuration.Configuration;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.database.configuration.Property;
+import org.sonar.api.resources.Project;
+import org.sonar.core.config.ConfigurationUtils;
+import org.sonar.jpa.session.DatabaseSessionFactory;
+
+import java.util.List;
+
+/**
+ * @since 2.12
+ */
+public class ProjectSettings extends Settings {
+
+  private Configuration deprecatedCommonsConf;
+  private ProjectDefinition projectDefinition;
+  private DatabaseSessionFactory dbFactory;
+
+  public ProjectSettings(PropertyDefinitions definitions, ProjectDefinition projectDefinition, DatabaseSessionFactory dbFactory, Project project) {
+    super(definitions);
+    this.deprecatedCommonsConf = project.getConfiguration(); // Configuration is not a parameter to be sure that the project conf is used, not the global one
+    this.projectDefinition = projectDefinition;
+    this.dbFactory = dbFactory;
+    load();
+  }
+
+  public ProjectSettings load() {
+    clear();
+
+    // order is important -> bottom-up. The last one overrides all the others.
+    loadDatabaseGlobalSettings();
+    loadDatabaseProjectSettings(projectDefinition);
+    addProperties(projectDefinition.getProperties());
+    addEnvironmentVariables();
+    addSystemProperties();
+
+    updateDeprecatedCommonsConfiguration();
+
+    return this;
+  }
+
+  private void loadDatabaseProjectSettings(ProjectDefinition projectDef) {
+    if (projectDef.getParent() != null) {
+      loadDatabaseProjectSettings(projectDef.getParent());
+    }
+    List<Property> props = ConfigurationUtils.getProjectProperties(dbFactory, projectDef.getKey());
+    for (Property dbProperty : props) {
+      setProperty(dbProperty.getKey(), dbProperty.getValue());
+    }
+  }
+
+  private void loadDatabaseGlobalSettings() {
+    List<Property> props = ConfigurationUtils.getGlobalProperties(dbFactory);
+    for (Property dbProperty : props) {
+      setProperty(dbProperty.getKey(), dbProperty.getValue());
+    }
+  }
+
+  private void updateDeprecatedCommonsConfiguration() {
+    ConfigurationUtils.copyToCommonsConfiguration(properties, deprecatedCommonsConf);
+  }
+
+}
index 2be1e1fc189802da788b69d7e44e9c94b8ba9f65..044038e17a8539688de4ed1e3d3620da876fbcd0 100644 (file)
@@ -21,12 +21,12 @@ package org.sonar.batch;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.junit.Test;
-import org.picocontainer.containers.TransientPicoContainer;
 import org.sonar.api.batch.BatchExtensionDictionnary;
 import org.sonar.api.batch.Decorator;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependedUpon;
 import org.sonar.api.measures.*;
+import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 
@@ -75,11 +75,9 @@ public class DecoratorsSelectorTest {
   }
 
   private BatchExtensionDictionnary newDictionnary(Object... extensions) {
-    TransientPicoContainer ioc = new TransientPicoContainer();
-    int index = 0;
+    ComponentContainer ioc = new ComponentContainer();
     for (Object extension : extensions) {
-      ioc.addComponent("" + index, extension);
-      index++;
+      ioc.addSingleton(extension);
     }
     return new BatchExtensionDictionnary(ioc);
   }
index 48bdbe1f96d90ac036cd30528f5a2fd2e4be11e1..4d2903e1e0a6051d78aa7423ec3a71749447a9f7 100644 (file)
  */
 package org.sonar.batch;
 
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Java;
 import org.sonar.api.resources.Project;
 import org.sonar.jpa.test.AbstractDbUnitTestCase;
@@ -35,30 +29,27 @@ import org.sonar.jpa.test.AbstractDbUnitTestCase;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
-public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
-
-  private ProjectConfigurator configurator = null;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-  @Before
-  public void before() {
-    configurator = new ProjectConfigurator(getSession());
-  }
+public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
 
   @Test
-  public void noExclusionPatterns() {
+  public void testNoExclusionPatterns() {
     Project project = new Project("key");
-    configurator.configure(project, new PropertiesConfiguration());
-
+    new ProjectConfigurator(getSession(), new Settings()).configure(project);
     assertThat(project.getExclusionPatterns().length, is(0));
   }
 
   @Test
-  public void manyExclusionPatterns() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
-    configuration.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "**/*,foo,*/bar");
+  public void testManyExclusionPatterns() {
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "**/*,foo,*/bar");
 
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), settings).configure(project);
 
     assertThat(project.getExclusionPatterns().length, is(3));
     assertThat(project.getExclusionPatterns()[0], is("**/*"));
@@ -73,11 +64,11 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
    */
   @Test
   public void trimExclusionPatterns() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, " foo ");
 
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
 
     assertThat(project.getExclusionPatterns().length, is(1));
     assertThat(project.getExclusionPatterns()[0], is("foo"));
@@ -85,11 +76,11 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
 
   @Test
   public void getLanguageFromConfiguration() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.PROJECT_LANGUAGE_PROPERTY, "foo");
 
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
 
     assertThat(project.getLanguageKey(), is("foo"));
   }
@@ -97,7 +88,7 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
   @Test
   public void defaultLanguageIsJava() {
     Project project = new Project("key");
-    configurator.configure(project, new PropertiesConfiguration());
+    new ProjectConfigurator(getSession(), new Settings()).configure(project);
 
     assertThat(project.getLanguageKey(), is(Java.KEY));
   }
@@ -105,37 +96,35 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
   @Test
   public void analysisIsTodayByDefault() {
     Project project = new Project("key");
-    configurator.configure(project, new PropertiesConfiguration());
+    new ProjectConfigurator(getSession(), new Settings()).configure(project);
     Date today = new Date();
     assertTrue(today.getTime() - project.getAnalysisDate().getTime() < 1000);
   }
 
   @Test
   public void analysisDateCouldBeExplicitlySet() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
-    configuration.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2005-01-30");
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2005-01-30");
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), settings).configure(project);
 
     assertEquals("30012005", new SimpleDateFormat("ddMMyyyy").format(project.getAnalysisDate()));
   }
 
   @Test(expected = RuntimeException.class)
   public void failIfAnalyisDateIsNotValid() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2005/30/01");
     Project project = new Project("key");
-    configurator.configure(project, configuration);
-
-    project.getAnalysisDate();
+    new ProjectConfigurator(getSession(), configuration).configure(project);
   }
 
   @Test
   public void sonarLightIsDeprecated() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty("sonar.light", "true");
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
 
     assertThat(project.getAnalysisType(), is(Project.AnalysisType.STATIC));
   }
@@ -143,34 +132,34 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
   @Test
   public void defaultAnalysisTypeIsDynamic() {
     Project project = new Project("key");
-    configurator.configure(project, new PropertiesConfiguration());
+    new ProjectConfigurator(getSession(), new Settings()).configure(project);
     assertThat(project.getAnalysisType(), is(Project.AnalysisType.DYNAMIC));
   }
 
   @Test
   public void explicitDynamicAnalysis() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.DYNAMIC_ANALYSIS_PROPERTY, "true");
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
     assertThat(project.getAnalysisType(), is(Project.AnalysisType.DYNAMIC));
   }
 
   @Test
   public void explicitStaticAnalysis() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.DYNAMIC_ANALYSIS_PROPERTY, "false");
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
     assertThat(project.getAnalysisType(), is(Project.AnalysisType.STATIC));
   }
 
   @Test
   public void explicitDynamicAnalysisReusingReports() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.DYNAMIC_ANALYSIS_PROPERTY, "reuseReports");
     Project project = new Project("key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
     assertThat(project.getAnalysisType(), is(Project.AnalysisType.REUSE_REPORTS));
   }
 
@@ -190,11 +179,11 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
   public void isLatestAnalysis() {
     setupData("isLatestAnalysis");
 
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2010-12-25");
 
     Project project = new Project("my:key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
 
     assertThat(project.isLatestAnalysis(), is(true));
   }
@@ -203,11 +192,11 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
   public void isLatestAnalysisIfNeverAnalysed() {
     setupData("isLatestAnalysisIfNeverAnalysed");
 
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2010-12-25");
 
     Project project = new Project("my:key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
 
     assertThat(project.isLatestAnalysis(), is(true));
   }
@@ -216,11 +205,11 @@ public class ProjectConfiguratorTest extends AbstractDbUnitTestCase {
   public void isNotLatestAnalysis() {
     setupData("isNotLatestAnalysis");
 
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
+    Settings configuration = new Settings();
     configuration.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2005-12-25");
 
     Project project = new Project("my:key");
-    configurator.configure(project, configuration);
+    new ProjectConfigurator(getSession(), configuration).configure(project);
 
     assertThat(project.isLatestAnalysis(), is(false));
   }
index 35fbd0c1bfbdc6cb1fc4b7b310f3ced3adc23667..093de7fab3cab6f2954cdd258450b99a2d8e0fb2 100644 (file)
@@ -133,8 +133,4 @@ public class ProjectTreeTest extends AbstractDbUnitTestCase {
     return new Project("org.example:" + artifactId).setPom(pom).setConfiguration(new PropertiesConfiguration());
   }
 
-
-  private ProjectConfigurator newConfigurator() {
-    return new ProjectConfigurator(getSession());
-  }
 }
index a52d5d829c3c5408b61a93ad19f483a7bd6228f7..913c3dc819bf692f44fc67e25810fea5bc96f1b7 100644 (file)
@@ -19,9 +19,9 @@
  */
 package org.sonar.batch;
 
-import org.apache.commons.configuration.PropertiesConfiguration;
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 
 import java.text.ParseException;
 
@@ -32,13 +32,13 @@ public class ServerMetadataTest {
 
   @Test
   public void testLoadProperties() throws ParseException {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty(CoreProperties.SERVER_ID, "123");
-    conf.setProperty(CoreProperties.SERVER_VERSION, "2.2");
-    conf.setProperty(CoreProperties.SERVER_STARTTIME, "2010-05-18T17:59:00+0000");
-    conf.setProperty("sonar.host.url", "http://foo.com");
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.SERVER_ID, "123");
+    settings.setProperty(CoreProperties.SERVER_VERSION, "2.2");
+    settings.setProperty(CoreProperties.SERVER_STARTTIME, "2010-05-18T17:59:00+0000");
+    settings.setProperty("sonar.host.url", "http://foo.com");
 
-    ServerMetadata server = new ServerMetadata(conf);
+    ServerMetadata server = new ServerMetadata(settings);
 
     assertThat(server.getId(), is("123"));
     assertThat(server.getVersion(), is("2.2"));
@@ -52,10 +52,10 @@ public class ServerMetadataTest {
    */
   @Test
   public void urlMustNotEndWithSlash() throws ParseException {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty("sonar.host.url", "http://localhost:80/");
+    Settings settings = new Settings();
+    settings.setProperty("sonar.host.url", "http://localhost:80/");
 
-    ServerMetadata server = new ServerMetadata(conf);
+    ServerMetadata server = new ServerMetadata(settings);
     assertThat(server.getURL(), is("http://localhost:80"));
   }
 }
index 10c19e6d415bfdc78e8c7b7cdef730d7ba0c6172..c4c013d36323102b7adfc6e86840f79ac04f78b2 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
+import com.google.common.collect.Maps;
 import org.junit.Test;
 import org.sonar.api.*;
 import org.sonar.api.batch.CoverageExtension;
 import org.sonar.api.batch.InstantiationStrategy;
+import org.sonar.api.platform.PluginMetadata;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.nullValue;
@@ -36,51 +39,53 @@ import static org.mockito.Mockito.when;
 
 public class BatchExtensionInstallerTest {
 
+  private static final PluginMetadata METADATA = mock(PluginMetadata.class);
+
+  private static Map<PluginMetadata, Plugin> newPlugin(final Class... classes) {
+    Map<PluginMetadata, Plugin> result = Maps.newHashMap();
+    result.put(METADATA,
+        new SonarPlugin() {
+          public List getExtensions() {
+            return Arrays.asList(classes);
+          }
+        }
+    );
+    return result;
+  }
+
   @Test
   public void shouldInstallExtensionsWithBatchInstantiationStrategy() {
     BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
-    when(pluginRepository.getPlugins()).thenReturn(Arrays.asList((Plugin) new SonarPlugin() {
-      public List getExtensions() {
-        return Arrays.asList(BatchService.class, ProjectService.class, ServerService.class);
-      }
-    }));
+    when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(BatchService.class, ProjectService.class, ServerService.class));
     Module module = new FakeModule().init();
     BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
     installer.install(module);
 
-    assertThat(module.getComponent(BatchService.class), not(nullValue()));
-    assertThat(module.getComponent(ProjectService.class), nullValue());
-    assertThat(module.getComponent(ServerService.class), nullValue());
+    assertThat(module.getComponentByType(BatchService.class), not(nullValue()));
+    assertThat(module.getComponentByType(ProjectService.class), nullValue());
+    assertThat(module.getComponentByType(ServerService.class), nullValue());
   }
 
   @Test
   public void shouldInstallProvidersWithBatchInstantiationStrategy() {
     BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
-    when(pluginRepository.getPlugins()).thenReturn(Arrays.asList((Plugin) new SonarPlugin(){
-      public List getExtensions() {
-        return Arrays.asList(BatchServiceProvider.class, ProjectServiceProvider.class);
-      }
-    }));
+    when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(BatchServiceProvider.class, ProjectServiceProvider.class));
     Module module = new FakeModule().init();
     BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
     installer.install(module);
 
-    assertThat(module.getComponent(BatchService.class), not(nullValue()));
-    assertThat(module.getComponent(ProjectService.class), nullValue());
-    assertThat(module.getComponent(ServerService.class), nullValue());
+    assertThat(module.getComponentByType(BatchService.class), not(nullValue()));
+    assertThat(module.getComponentByType(ProjectService.class), nullValue());
+    assertThat(module.getComponentByType(ServerService.class), nullValue());
   }
 
   @Test(expected = IllegalArgumentException.class)
   public void shouldNotSupportCoverageExtensionsWithBatchInstantiationStrategy() {
     // the reason is that CoverageExtensions currently depend on Project
     BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
-    when(pluginRepository.getPlugins()).thenReturn(Arrays.asList((Plugin) new SonarPlugin(){
-      public List getExtensions() {
-        return Arrays.asList(InvalidCoverageExtension.class);
-      }
-    }));
+    when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(InvalidCoverageExtension.class));
     Module module = new FakeModule().init();
     BatchExtensionInstaller installer = new BatchExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), new DryRun(false));
 
index 00b291a22796f31db4a8a820ab4783af3bc524d3..40ed3add328d90d015d9701ab1ac27078ca1d1f5 100644 (file)
@@ -26,6 +26,7 @@ import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 import org.sonar.core.plugins.RemotePlugin;
 
 import java.io.File;
@@ -57,7 +58,7 @@ public class BatchPluginRepositoryTest {
     ArtifactDownloader downloader = mock(ArtifactDownloader.class);
     when(downloader.downloadPlugin(checkstyle)).thenReturn(copyFiles("sonar-checkstyle-plugin-2.8.jar"));
 
-    repository = new BatchPluginRepository(downloader, new PropertiesConfiguration());
+    repository = new BatchPluginRepository(downloader, new Settings());
 
     repository.doStart(Arrays.asList(checkstyle));
 
@@ -77,7 +78,7 @@ public class BatchPluginRepositoryTest {
     when(downloader.downloadPlugin(checkstyle)).thenReturn(copyFiles("sonar-checkstyle-plugin-2.8.jar"));
     when(downloader.downloadPlugin(checkstyleExt)).thenReturn(copyFiles("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar"));
 
-    repository = new BatchPluginRepository(downloader, new PropertiesConfiguration());
+    repository = new BatchPluginRepository(downloader, new Settings());
 
     repository.doStart(Arrays.asList(checkstyle, checkstyleExt));
 
@@ -97,7 +98,7 @@ public class BatchPluginRepositoryTest {
     ArtifactDownloader downloader = mock(ArtifactDownloader.class);
     when(downloader.downloadPlugin(checkstyle)).thenReturn(copyFiles("sonar-checkstyle-plugin-2.8.jar", "checkstyle-ext.xml"));
 
-    repository = new BatchPluginRepository(downloader, new PropertiesConfiguration());
+    repository = new BatchPluginRepository(downloader, new Settings());
 
     repository.doStart(Arrays.asList(checkstyle));
 
@@ -117,9 +118,9 @@ public class BatchPluginRepositoryTest {
     when(downloader.downloadPlugin(checkstyle)).thenReturn(copyFiles("sonar-checkstyle-plugin-2.8.jar"));
     when(downloader.downloadPlugin(checkstyleExt)).thenReturn(copyFiles("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar"));
 
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle");
-    repository = new BatchPluginRepository(downloader, conf);
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle");
+    repository = new BatchPluginRepository(downloader, settings);
 
     repository.doStart(Arrays.asList(checkstyle, checkstyleExt));
 
@@ -142,41 +143,41 @@ public class BatchPluginRepositoryTest {
 
   @Test
   public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() {
-    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), new PropertiesConfiguration());
+    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), new Settings());
     assertThat(repository.isAccepted("pmd"), Matchers.is(true));
   }
 
   @Test
   public void whiteListShouldTakePrecedenceOverBlackList() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
-    conf.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd");
-    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), conf);
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+    settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd");
+    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), settings);
 
     assertThat(repository.isAccepted("pmd"), Matchers.is(true));
   }
 
   @Test
   public void corePluginShouldAlwaysBeInWhiteList() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
-    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), conf);
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), settings);
     assertThat(repository.isAccepted("core"), Matchers.is(true));
   }
 
   @Test
   public void corePluginShouldNeverBeInBlackList() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs");
-    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), conf);
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs");
+    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), settings);
     assertThat(repository.isAccepted("core"), Matchers.is(true));
   }
 
   @Test
   public void shouldCheckWhitelist() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
-    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), conf);
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), settings);
 
     assertThat(repository.isAccepted("checkstyle"), Matchers.is(true));
     assertThat(repository.isAccepted("pmd"), Matchers.is(true));
@@ -185,9 +186,9 @@ public class BatchPluginRepositoryTest {
 
   @Test
   public void shouldCheckBlackListIfNoWhiteList() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
-    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), conf);
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+    repository = new BatchPluginRepository(mock(ArtifactDownloader.class), settings);
 
     assertThat(repository.isAccepted("checkstyle"), Matchers.is(false));
     assertThat(repository.isAccepted("pmd"), Matchers.is(false));
index 5b278b0285dd9d9696e85e7931722b3da0e101c1..a6acd28fd370b03a28a0e14b5f17a303f49fbbde 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
-import org.apache.commons.configuration.PropertiesConfiguration;
 import org.hamcrest.core.Is;
 import org.junit.Test;
+import org.sonar.api.config.Settings;
 
 import static org.junit.Assert.assertThat;
 
 public class DryRunTest {
 
   @Test
-  public void shouldReadConfiguration() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty("sonar.dryRun", "true");
-    assertThat(new DryRun(conf).isEnabled(), Is.is(true));
+  public void shouldReadSettings() {
+    Settings settings = Settings.createForComponent(DryRun.class);
+    settings.setProperty("sonar.dryRun", true);
+    assertThat(new DryRun(settings).isEnabled(), Is.is(true));
 
-    conf.setProperty("sonar.dryRun", "false");
-    assertThat(new DryRun(conf).isEnabled(), Is.is(false));
+    settings.setProperty("sonar.dryRun", false);
+    assertThat(new DryRun(settings).isEnabled(), Is.is(false));
   }
 
   @Test
   public void shouldNotEnableDryRunByDefault() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    assertThat(new DryRun(conf).isEnabled(), Is.is(false));
+    Settings settings = Settings.createForComponent(DryRun.class);
+    assertThat(new DryRun(settings).isEnabled(), Is.is(false));
   }
 }
index 60fc585dd0b0ff336e06583b9e6656632de224d8..5d7accba6cc2633d10c9ed5215f6baefac2338ae 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.batch.bootstrap;
 import org.hamcrest.Matchers;
 import org.junit.Test;
 
+import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.nullValue;
 import static org.hamcrest.core.Is.is;
@@ -33,10 +34,10 @@ public class ModuleTest {
   public void shouldInitModule() {
     Module module = new FakeModule(FakeService.class).init();
 
-    FakeService service = module.getComponent(FakeService.class);
+    FakeService service = module.getComponentByType(FakeService.class);
     assertThat(service, not(nullValue()));
     assertThat(service.started, is(false));
-    assertThat(module.getContainer(), not(nullValue()));
+    assertThat(module.container, notNullValue());
   }
 
   @Test
@@ -44,7 +45,7 @@ public class ModuleTest {
     Module module = new FakeModule(FakeService.class).init();
     module.start();
 
-    FakeService service = module.getComponent(FakeService.class);
+    FakeService service = module.getComponentByType(FakeService.class);
     assertThat(service.started, is(true));
 
     module.stop();
@@ -68,7 +69,7 @@ public class ModuleTest {
   public void componentsShouldBeSingletons() {
     Module module = new FakeModule(FakeService.class).init();
 
-    assertThat(module.getComponent(FakeService.class) == module.getComponent(FakeService.class), is(true));
+    assertThat(module.getComponentByType(FakeService.class) == module.getComponentByType(FakeService.class), is(true));
   }
 
   @Test
@@ -78,16 +79,16 @@ public class ModuleTest {
 
     Module child = parent.installChild(new FakeModule(ChildService.class));
 
-    assertThat(parent.getComponent(ChildService.class), Matchers.nullValue());// child not accessible from parent
-    assertThat(child.getComponent(FakeService.class), not(nullValue()));
-    assertThat(child.getComponent(ChildService.class).started, is(false));
-    assertThat(child.getComponent(ChildService.class).dependency, not(nullValue()));
+    assertThat(parent.getComponentByType(ChildService.class), Matchers.nullValue());// child not accessible from parent
+    assertThat(child.getComponentByType(FakeService.class), not(nullValue()));
+    assertThat(child.getComponentByType(ChildService.class).started, is(false));
+    assertThat(child.getComponentByType(ChildService.class).dependency, not(nullValue()));
 
     child.start();
-    assertThat(child.getComponent(ChildService.class).started, is(true));
+    assertThat(child.getComponentByType(ChildService.class).started, is(true));
 
     child.stop();
-    assertThat(child.getComponent(ChildService.class).started, is(false));
+    assertThat(child.getComponentByType(ChildService.class).started, is(false));
   }
 
   public static class FakeModule extends Module {
@@ -100,7 +101,7 @@ public class ModuleTest {
     @Override
     protected void configure() {
       for (Class component : components) {
-        addComponent(component);
+        addCoreSingleton(component);
       }
     }
 
index 9e9fcd60fa64154bb021b15a883046460547a548..1148116b2e109ba885157eb0efacc3403fd791d4 100644 (file)
@@ -70,9 +70,9 @@ public class ProjectExtensionInstallerTest {
 
     installer.install(module, new Project("foo"));
 
-    assertThat(module.getComponent(BatchService.class), nullValue());
-    assertThat(module.getComponent(ProjectService.class), not(nullValue()));
-    assertThat(module.getComponent(ServerService.class), nullValue());
+    assertThat(module.getComponentByType(BatchService.class), nullValue());
+    assertThat(module.getComponentByType(ProjectService.class), not(nullValue()));
+    assertThat(module.getComponentByType(ServerService.class), nullValue());
   }
 
   @Test
@@ -90,8 +90,8 @@ public class ProjectExtensionInstallerTest {
 
     installer.install(module, new Project("foo"));
 
-    assertThat(module.getComponent(MavenService.class), nullValue());
-    assertThat(module.getComponent(BuildToolService.class), not(nullValue()));
+    assertThat(module.getComponentByType(MavenService.class), nullValue());
+    assertThat(module.getComponentByType(BuildToolService.class), not(nullValue()));
   }
 
 
diff --git a/sonar-core/src/main/java/org/sonar/core/config/ConfigurationUtils.java b/sonar-core/src/main/java/org/sonar/core/config/ConfigurationUtils.java
new file mode 100644 (file)
index 0000000..bf4eda3
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.config;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.database.configuration.Property;
+import org.sonar.api.database.model.ResourceModel;
+import org.sonar.jpa.session.DatabaseSessionFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+
+/**
+ * @since 2.12
+ */
+public final class ConfigurationUtils {
+
+  private ConfigurationUtils() {
+  }
+
+  public static void copyProperties(Properties from, Map<String, String> to) {
+    for (Map.Entry<Object, Object> entry : from.entrySet()) {
+      String key = (String) entry.getKey();
+      to.put(key, entry.getValue().toString());
+    }
+  }
+
+  public static Properties openProperties(File file) throws IOException {
+    FileInputStream input = FileUtils.openInputStream(file);
+    return openInputStream(input);
+  }
+
+  /**
+   * Note that the input stream is closed in this method.
+   */
+  public static Properties openInputStream(InputStream input) throws IOException {
+    try {
+      Properties p = new Properties();
+      p.load(input);
+      return p;
+
+    } finally {
+      IOUtils.closeQuietly(input);
+    }
+  }
+
+  public static Properties interpolateEnvVariables(Properties properties) {
+    return interpolateVariables(properties, System.getenv());
+  }
+
+  public static Properties interpolateVariables(Properties properties, Map<String, String> variables) {
+    Properties result = new Properties();
+    Enumeration keys = properties.keys();
+    while (keys.hasMoreElements()) {
+      String key = (String) keys.nextElement();
+      String value = (String) properties.get(key);
+      String interpolatedValue = StrSubstitutor.replace(value, variables, "${env:", "}");
+      result.setProperty(key, interpolatedValue);
+    }
+    return result;
+  }
+
+  public static List<Property> getProjectProperties(DatabaseSessionFactory dbFactory, String moduleKey) {
+    DatabaseSession session = prepareDbSession(dbFactory);
+    ResourceModel resource = session.getSingleResult(ResourceModel.class, "key", moduleKey);
+    if (resource != null) {
+      return session
+          .createQuery("from " + Property.class.getSimpleName() + " p where p.resourceId=:resourceId and p.userId is null")
+          .setParameter("resourceId", resource.getId())
+          .getResultList();
+
+    }
+    return Collections.emptyList();
+  }
+
+  public static List<Property> getGlobalProperties(DatabaseSessionFactory dbFactory) {
+    DatabaseSession session = prepareDbSession(dbFactory);
+    return session
+        .createQuery("from " + Property.class.getSimpleName() + " p where p.resourceId is null and p.userId is null")
+        .getResultList();
+
+  }
+
+  private static DatabaseSession prepareDbSession(DatabaseSessionFactory dbFactory) {
+    DatabaseSession session = dbFactory.getSession();
+    // Ugly workaround before the move to myBatis
+    // Session is not up-to-date when Ruby on Rails inserts new rows in its own transaction. Seems like
+    // Hibernate keeps a cache...
+    session.commit();
+    return session;
+  }
+
+  public static void copyToCommonsConfiguration(Map<String,String> input, Configuration commonsConfig) {
+    // update deprecated configuration
+    commonsConfig.clear();
+    for (Map.Entry<String, String> entry : input.entrySet()) {
+      String key = entry.getKey();
+      commonsConfig.setProperty(key, entry.getValue());
+    }
+  }
+}
index 866bb056eceb6b47c6230e66eb75dac35165cd1a..687576e5650212b280eeb5b07631f5264f322111 100644 (file)
@@ -17,7 +17,6 @@
  * 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.plugins;
 
 import com.google.common.collect.Lists;
index e543fecc28f76eeed00bc7348e041e2cead8d03f..0b27ec5c55477ee507922950f0e9577cda3084ea 100644 (file)
@@ -24,6 +24,7 @@ import org.apache.commons.lang.StringUtils;
 import org.hibernate.cfg.Environment;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 import org.sonar.api.utils.Logs;
 import org.sonar.jpa.dialect.Dialect;
@@ -36,6 +37,7 @@ import javax.persistence.Persistence;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -43,16 +45,15 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
   protected static final Logger LOG_SQL = LoggerFactory.getLogger("org.hibernate.SQL");
   protected static final Logger LOG = LoggerFactory.getLogger(AbstractDatabaseConnector.class);
 
-  private Configuration configuration = null;
+  protected Settings configuration = null;
   private EntityManagerFactory factory = null;
   private int databaseVersion = SchemaMigration.VERSION_UNKNOWN;
   private boolean operational = false;
   private boolean started = false;
   private boolean startsFailIfSchemaOutdated;
-  private Integer transactionIsolation = null;
   private Dialect dialect = null;
 
-  protected AbstractDatabaseConnector(Configuration configuration, boolean startsFailIfSchemaOutdated) {
+  protected AbstractDatabaseConnector(Settings configuration, boolean startsFailIfSchemaOutdated) {
     this.configuration = configuration;
     this.startsFailIfSchemaOutdated = startsFailIfSchemaOutdated;
   }
@@ -60,14 +61,6 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
   protected AbstractDatabaseConnector() {
   }
 
-  public Configuration getConfiguration() {
-    return configuration;
-  }
-
-  public void setConfiguration(Configuration configuration) {
-    this.configuration = configuration;
-  }
-
   public String getDialectId() {
     return dialect.getId();
   }
@@ -86,18 +79,8 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
     return started;
   }
 
-  /**
-   * Get the JDBC transaction isolation defined by the configuration
-   *
-   * @return JDBC transaction isolation
-   */
-  public final Integer getTransactionIsolation() {
-    return transactionIsolation;
-  }
-
   public void start() {
     if (!started) {
-      transactionIsolation = configuration.getInteger(DatabaseProperties.PROP_ISOLATION, null /* use driver default setting */);
       String jdbcConnectionUrl = testConnection();
       dialect = DialectRepository.find(configuration.getString("sonar.jdbc.dialect"), jdbcConnectionUrl);
       LoggerFactory.getLogger("org.sonar.INFO").info("Database dialect class " + dialect.getClass().getName());
@@ -152,21 +135,15 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
 
   protected Properties getHibernateProperties() {
     Properties props = new Properties();
-    if (transactionIsolation != null) {
-      props.put("hibernate.connection.isolation", Integer.toString(transactionIsolation));
-    }
-    props.put("hibernate.hbm2ddl.auto", getConfiguration().getString(DatabaseProperties.PROP_HIBERNATE_HBM2DLL, "validate"));
+    props.put("hibernate.hbm2ddl.auto", StringUtils.defaultString(configuration.getString(DatabaseProperties.PROP_HIBERNATE_HBM2DLL), "validate"));
     props.put(Environment.DIALECT, getDialectClass());
 
-    props.put("hibernate.generate_statistics", getConfiguration().getBoolean(DatabaseProperties.PROP_HIBERNATE_GENERATE_STATISTICS, false));
+    props.put("hibernate.generate_statistics", configuration.getBoolean(DatabaseProperties.PROP_HIBERNATE_GENERATE_STATISTICS));
     props.put("hibernate.show_sql", Boolean.valueOf(LOG_SQL.isDebugEnabled()).toString());
 
-    Configuration subset = getConfiguration().subset("sonar.hibernate");
-    for (Iterator keys = subset.getKeys(); keys.hasNext();) {
-      String key = (String) keys.next();
-      if (StringUtils.isNotBlank((String) subset.getProperty(key))) {
-        props.put("hibernate." + key, subset.getProperty(key));
-      }
+    List<String> hibernateKeys = configuration.getKeysStartingWith("sonar.hibernate.");
+    for (String hibernateKey : hibernateKeys) {
+      props.put(StringUtils.removeStart(hibernateKey, "sonar."), configuration.getString(hibernateKey));
     }
 
     // custom impl setup
index 00e91fd8f381cb0ad3fcac8972a2289b529fb451..a2d6c619a894c7e4f2435fdb46ea141b6171c089 100644 (file)
@@ -19,8 +19,8 @@
  */
 package org.sonar.jpa.session;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.StringUtils;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 
 import java.sql.Connection;
@@ -35,20 +35,20 @@ public class DriverDatabaseConnector extends AbstractDatabaseConnector {
   private ClassLoader classloader;
   private boolean driverProxyRegistered = false;
 
-  public DriverDatabaseConnector(Configuration configuration) {
+  public DriverDatabaseConnector(Settings configuration) {
     super(configuration, true);
     this.classloader = getClass().getClassLoader();
   }
 
-  public DriverDatabaseConnector(Configuration configuration, ClassLoader classloader) {
+  public DriverDatabaseConnector(Settings configuration, ClassLoader classloader) {
     super(configuration, true);
     this.classloader = classloader;
   }
 
   public String getDriver() {
-    String driver = getConfiguration().getString(DatabaseProperties.PROP_DRIVER);
+    String driver = configuration.getString(DatabaseProperties.PROP_DRIVER);
     if (driver == null) {
-      driver = getConfiguration().getString(DatabaseProperties.PROP_DRIVER_DEPRECATED);
+      driver = configuration.getString(DatabaseProperties.PROP_DRIVER_DEPRECATED);
     }
     if (driver == null) {
       driver = DatabaseProperties.PROP_DRIVER_DEFAULT_VALUE;
@@ -57,13 +57,13 @@ public class DriverDatabaseConnector extends AbstractDatabaseConnector {
   }
 
   public String getUrl() {
-    return getConfiguration().getString(DatabaseProperties.PROP_URL, DatabaseProperties.PROP_URL_DEFAULT_VALUE);
+    return StringUtils.defaultString(configuration.getString(DatabaseProperties.PROP_URL), DatabaseProperties.PROP_URL_DEFAULT_VALUE);
   }
 
   public String getUsername() {
-    String username = getConfiguration().getString(DatabaseProperties.PROP_USER);
+    String username = configuration.getString(DatabaseProperties.PROP_USER);
     if (username == null) {
-      username = getConfiguration().getString(DatabaseProperties.PROP_USER_DEPRECATED);
+      username = configuration.getString(DatabaseProperties.PROP_USER_DEPRECATED);
     }
     if (username == null) {
       username = DatabaseProperties.PROP_USER_DEFAULT_VALUE;
@@ -72,7 +72,7 @@ public class DriverDatabaseConnector extends AbstractDatabaseConnector {
   }
 
   public String getPassword() {
-    return getConfiguration().getString(DatabaseProperties.PROP_PASSWORD, DatabaseProperties.PROP_PASSWORD_DEFAULT_VALUE);
+    return StringUtils.defaultString(configuration.getString(DatabaseProperties.PROP_PASSWORD), DatabaseProperties.PROP_PASSWORD_DEFAULT_VALUE);
   }
 
   public Connection getConnection() throws SQLException {
index 5e9cfa2f09f6ded7cda80cda64ae8f4c7c67c093..863e7ebe7fd891dfa948b385dcff4e1314f557fd 100644 (file)
@@ -19,8 +19,7 @@
  */
 package org.sonar.jpa.session;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.PropertiesConfiguration;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 import org.sonar.jpa.entity.SchemaMigration;
 
@@ -37,7 +36,7 @@ public class MemoryDatabaseConnector extends DriverDatabaseConnector {
 
   private int version;
 
-  public MemoryDatabaseConnector(Configuration config) {
+  public MemoryDatabaseConnector(Settings config) {
     super(config);
     version = SchemaMigration.LAST_VERSION;
   }
@@ -51,8 +50,8 @@ public class MemoryDatabaseConnector extends DriverDatabaseConnector {
     this.version = version;
   }
 
-  protected static Configuration getInMemoryConfiguration(boolean createSchema) {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
+  protected static Settings getInMemoryConfiguration(boolean createSchema) {
+    Settings conf = new Settings();
     conf.setProperty(DatabaseProperties.PROP_URL, URL);
     conf.setProperty(DatabaseProperties.PROP_DRIVER, DRIVER);
     conf.setProperty(DatabaseProperties.PROP_USER, USER);
diff --git a/sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java b/sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java
new file mode 100644 (file)
index 0000000..5528102
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.config;
+
+import com.google.common.collect.Maps;
+import org.junit.Test;
+
+import java.util.Map;
+import java.util.Properties;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ConfigurationUtilsTest {
+  @Test
+  public void shouldInterpolateVariables() {
+    Properties input = new Properties();
+    input.setProperty("hello", "world");
+    input.setProperty("url", "${env:SONAR_JDBC_URL}");
+    input.setProperty("do_not_change", "${SONAR_JDBC_URL}");
+    Map<String, String> variables = Maps.newHashMap();
+    variables.put("SONAR_JDBC_URL", "jdbc:derby:mem");
+
+    Properties output = ConfigurationUtils.interpolateVariables(input, variables);
+
+    assertThat(output.size(), is(3));
+    assertThat(output.getProperty("hello"), is("world"));
+    assertThat(output.getProperty("url"), is("jdbc:derby:mem"));
+    assertThat(output.getProperty("do_not_change"), is("${SONAR_JDBC_URL}"));
+
+    // input is not changed
+    assertThat(input.size(), is(3));
+    assertThat(input.getProperty("hello"), is("world"));
+    assertThat(input.getProperty("url"), is("${env:SONAR_JDBC_URL}"));
+    assertThat(input.getProperty("do_not_change"), is("${SONAR_JDBC_URL}"));
+  }
+
+  @Test
+  public void shouldCopyProperties() {
+    Properties input = new Properties();
+    input.setProperty("hello", "world");
+    input.setProperty("foo", "bar");
+    Map<String,String> output = Maps.newHashMap();
+
+    ConfigurationUtils.copyProperties(input, output);
+
+    assertThat(output.size(), is(2));
+    assertThat(output.get("hello"), is("world"));
+    assertThat(output.get("foo"), is("bar"));
+
+    // input is not changed
+    assertThat(input.size(), is(2));
+    assertThat(input.getProperty("hello"), is("world"));
+    assertThat(input.getProperty("foo"), is("bar"));
+  }
+}
index afc386a9d8e5b266423da683c330ac5f36a5dafd..7d08e633669d61507c4d6d26327e006bfb830c19 100644 (file)
@@ -27,7 +27,6 @@ import org.sonar.api.BatchExtension;
 import org.sonar.api.ExtensionProvider;
 import org.sonar.api.Plugin;
 import org.sonar.api.ServerExtension;
-import org.sonar.api.utils.IocContainer;
 
 import java.util.Arrays;
 import java.util.Collection;
index f584eb4b72b1b96fcc70a6bee894662b7967465a..8ee37d719332d478d86e9fb4d7d6587480a3c419 100644 (file)
@@ -24,6 +24,7 @@ import org.apache.commons.configuration.PropertiesConfiguration;
 import org.hamcrest.Matchers;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 import org.sonar.jpa.dialect.HsqlDb;
 import org.sonar.jpa.dialect.Oracle;
@@ -49,7 +50,7 @@ public class AbstractDatabaseConnectorTest {
 
   @Test
   public void useConfiguredDialectByDefault() {
-    Configuration conf = MemoryDatabaseConnector.getInMemoryConfiguration(false);
+    Settings conf = MemoryDatabaseConnector.getInMemoryConfiguration(false);
     conf.setProperty(DatabaseProperties.PROP_DIALECT, DatabaseProperties.DIALECT_ORACLE);
 
     TestDatabaseConnector connector = new TestDatabaseConnector(conf);
@@ -60,7 +61,7 @@ public class AbstractDatabaseConnectorTest {
 
   @Test
   public void getHibernateProperties() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
+    Settings conf = new Settings();
     conf.setProperty("sonar.foo", "foo value");
 
     // all properties prefixed by sonar.hibernate are propagated to hibernate configuration (the prefix "sonar." is removed)
@@ -84,7 +85,7 @@ public class AbstractDatabaseConnectorTest {
 
   private class TestDatabaseConnector extends AbstractDatabaseConnector {
 
-    public TestDatabaseConnector(Configuration configuration) {
+    public TestDatabaseConnector(Settings configuration) {
       super(configuration, false);
     }
 
index dfc0716eb0df76d1824269430b589a20a15a6507..82fd8c4e41c49f698f966555387f901b5ab4bc86 100644 (file)
@@ -23,6 +23,7 @@ import org.apache.commons.configuration.PropertiesConfiguration;
 import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Test;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 
 import java.sql.SQLException;
@@ -43,11 +44,10 @@ public class DriverDatabaseConnectorTest {
 
   @Test(expected = DatabaseException.class)
   public void failsIfUnvalidConfiguration() throws SQLException {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
+    Settings conf = new Settings();
     conf.setProperty(DatabaseProperties.PROP_URL, "jdbc:foo:bar//xxx");
     conf.setProperty(DatabaseProperties.PROP_DRIVER, MemoryDatabaseConnector.DRIVER);
     conf.setProperty(DatabaseProperties.PROP_USER, "sa");
-    conf.setProperty(DatabaseProperties.PROP_PASSWORD, null);
     connector = new DriverDatabaseConnector(conf);
     try {
       connector.start();
@@ -81,7 +81,7 @@ public class DriverDatabaseConnectorTest {
 
   @Test
   public void deprecatedParametersAreStillValid() {
-    PropertiesConfiguration conf = new PropertiesConfiguration();
+    Settings conf = new Settings();
     conf.setProperty(DatabaseProperties.PROP_DRIVER_DEPRECATED, MemoryDatabaseConnector.DRIVER);
     conf.setProperty(DatabaseProperties.PROP_USER_DEPRECATED, "freddy");
     connector = new DriverDatabaseConnector(conf);
index 75673c63b06685ec5f4ae7aca1f75ca3ac257beb..6b78f9b463dee9884782d2c54228e63ba99b2c66 100644 (file)
@@ -147,7 +147,7 @@ public final class SonarMojo extends AbstractMojo {
     ProjectDefinition def = MavenProjectConverter.convert(session.getSortedProjects(), project);
     ProjectReactor reactor = new ProjectReactor(def);
 
-    Batch batch = Batch.create(reactor, getInitialConfiguration(),
+    Batch batch = Batch.create(reactor, null,
         session, getLog(), lifecycleExecutor, pluginManager, artifactFactory,
         localRepository, artifactMetadataSource, artifactCollector, dependencyTreeBuilder,
         projectBuilder, getEnvironmentInformation(), Maven2PluginExecutor.class);
index f4173290c11825a2d5c5456fe40c170fc1f76fe0..001378c7bb7ed542996d91c14afcc080d5aa4471 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.maven3;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
 import ch.qos.logback.core.joran.spi.JoranException;
-import org.apache.commons.configuration.*;
 import org.apache.commons.io.IOUtils;
 import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
@@ -43,6 +42,7 @@ import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.batch.Batch;
 import org.sonar.batch.MavenProjectConverter;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
+
 import java.io.InputStream;
 
 /**
@@ -140,7 +140,7 @@ public final class SonarMojo extends AbstractMojo {
     ProjectDefinition def = MavenProjectConverter.convert(session.getSortedProjects(), project);
     ProjectReactor reactor = new ProjectReactor(def);
 
-    Batch batch = Batch.create(reactor, getInitialConfiguration(),
+    Batch batch = Batch.create(reactor, null,
         session, getLog(), lifecycleExecutor, artifactFactory,
         localRepository, artifactMetadataSource, artifactCollector, dependencyTreeBuilder,
         projectBuilder, getEnvironmentInformation(), Maven3PluginExecutor.class);
@@ -170,11 +170,4 @@ public final class SonarMojo extends AbstractMojo {
     }
   }
 
-  private Configuration getInitialConfiguration() {
-    CompositeConfiguration configuration = new CompositeConfiguration();
-    configuration.addConfiguration(new SystemConfiguration());
-    configuration.addConfiguration(new EnvironmentConfiguration());
-    configuration.addConfiguration(new MapConfiguration(project.getModel().getProperties()));
-    return configuration;
-  }
 }
index dddea1ccc0b08a2ab75647d37b4bc1942b0e95d0..e7b62cf8dde443102867741c572136a695c9934f 100644 (file)
@@ -23,14 +23,12 @@ import com.google.common.base.Predicates;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Lists;
 import org.apache.commons.lang.ClassUtils;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.PicoContainer;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.batch.maven.DependsUponMavenPlugin;
 import org.sonar.api.batch.maven.MavenPluginHandler;
+import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.AnnotationUtils;
-import org.sonar.api.utils.IocContainer;
 import org.sonar.api.utils.dag.DirectAcyclicGraph;
 
 import java.lang.annotation.Annotation;
@@ -45,14 +43,10 @@ import java.util.List;
  */
 public class BatchExtensionDictionnary {
 
-  private MutablePicoContainer picoContainer;
+  private ComponentContainer componentContainer;
 
-  public BatchExtensionDictionnary(IocContainer iocContainer) {
-    this.picoContainer = iocContainer.getPicoContainer();
-  }
-
-  public BatchExtensionDictionnary(MutablePicoContainer picoContainer) {
-    this.picoContainer = picoContainer;
+  public BatchExtensionDictionnary(ComponentContainer componentContainer) {
+    this.componentContainer = componentContainer;
   }
 
   public <T> Collection<T> select(Class<T> type) {
@@ -88,14 +82,14 @@ public class BatchExtensionDictionnary {
 
   private List<BatchExtension> getExtensions() {
     List<BatchExtension> extensions = Lists.newArrayList();
-    completeBatchExtensions(picoContainer, extensions);
+    completeBatchExtensions(componentContainer, extensions);
     return extensions;
   }
 
-  private void completeBatchExtensions(PicoContainer picoContainer, List<BatchExtension> extensions) {
-    if (picoContainer!=null) {
-      extensions.addAll(picoContainer.getComponents(BatchExtension.class));
-      completeBatchExtensions(picoContainer.getParent(), extensions);
+  private static void completeBatchExtensions(ComponentContainer container, List<BatchExtension> extensions) {
+    if (container != null) {
+      extensions.addAll(container.getComponentsByType(BatchExtension.class));
+      completeBatchExtensions(container.getParent(), extensions);
     }
   }
 
@@ -212,7 +206,7 @@ public class BatchExtensionDictionnary {
       if (result != null) {
         //TODO add arrays/collections of objects/classes
         if (result instanceof Class) {
-          results.addAll(picoContainer.getComponents((Class) result));
+          results.addAll(componentContainer.getComponentsByType((Class) result));
 
         } else if (result instanceof Collection) {
           results.addAll((Collection) result);
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java
new file mode 100644 (file)
index 0000000..8190e15
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.api.config;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.utils.AnnotationUtils;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Metadata of all the properties declared by plugins
+ *
+ * @since 2.12
+ */
+public final class PropertyDefinitions implements BatchComponent, ServerComponent {
+
+  private Map<String, Property> properties = Maps.newHashMap();
+  private Map<String, String> categories = Maps.newHashMap();
+
+  public PropertyDefinitions(Object... components) {
+    if (components != null) {
+      addComponents(Arrays.asList(components));
+    }
+  }
+
+  public PropertyDefinitions addComponents(Collection components) {
+    return addComponents(components, "");
+  }
+
+  public PropertyDefinitions addComponents(Collection components, String defaultCategory) {
+    for (Object component : components) {
+      addComponent(component, defaultCategory);
+    }
+    return this;
+  }
+
+  public PropertyDefinitions addComponent(Object object) {
+    return addComponent(object, "");
+  }
+
+  public PropertyDefinitions addComponent(Object component, String defaultCategory) {
+    Properties annotations = AnnotationUtils.getClassAnnotation(component, Properties.class);
+    if (annotations != null) {
+      for (Property property : annotations.value()) {
+        addProperty(property, defaultCategory);
+      }
+    }
+    Property annotation = AnnotationUtils.getClassAnnotation(component, Property.class);
+    if (annotation != null) {
+      addProperty(annotation, defaultCategory);
+    }
+    return this;
+  }
+
+  PropertyDefinitions addProperty(Property property) {
+    return addProperty(property, "");
+  }
+
+  PropertyDefinitions addProperty(Property property, String defaultCategory) {
+    if (!properties.containsKey(property.key())) {
+      properties.put(property.key(), property);
+      categories.put(property.key(), StringUtils.defaultIfBlank(property.category(), defaultCategory));
+    }
+    return this;
+  }
+
+  public Property getProperty(String key) {
+    return properties.get(key);
+  }
+
+  public Collection<Property> getProperties() {
+    return properties.values();
+  }
+
+  public String getDefaultValue(String key) {
+    Property prop = getProperty(key);
+    if (prop != null) {
+      return StringUtils.defaultIfEmpty(prop.defaultValue(), null);
+    }
+    return null;
+  }
+
+  public String getCategory(String key) {
+    return categories.get(key);
+  }
+
+  public String getCategory(Property prop) {
+    return getCategory(prop.key());
+  }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
new file mode 100644 (file)
index 0000000..fc626bb
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.api.config;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.utils.DateUtils;
+
+import java.util.*;
+
+/**
+ * Project Settings on batch side, Global Settings on server side.
+ * <p/>
+ * Replace the deprecated component org.apache.commons.configuration.Configuration
+ *
+ * @since 2.12
+ */
+public class Settings implements BatchComponent, ServerComponent {
+
+  protected Map<String, String> properties = Maps.newHashMap();
+  protected PropertyDefinitions definitions;
+
+  public Settings() {
+    this(new PropertyDefinitions());
+  }
+
+  public Settings(PropertyDefinitions definitions) {
+    this.definitions = definitions;
+  }
+
+  public final String getDefaultValue(String key) {
+    return definitions.getDefaultValue(key);
+  }
+
+  public final boolean hasKey(String key) {
+    return properties.containsKey(key);
+  }
+
+  public final boolean hasDefaultValue(String key) {
+    return StringUtils.isNotEmpty(getDefaultValue(key));
+  }
+
+  public final String getString(String key) {
+    String value = properties.get(key);
+    if (value==null) {
+      value = getDefaultValue(key);
+    }
+    return value;
+  }
+
+  public final boolean getBoolean(String key) {
+    String value = getString(key);
+    return StringUtils.isNotEmpty(value) && Boolean.parseBoolean(value);
+  }
+
+  public final int getInt(String key) {
+    String value = getString(key);
+    if (StringUtils.isNotEmpty(value)) {
+      return Integer.parseInt(value);
+    }
+    return 0;
+  }
+
+  public final long getLong(String key) {
+    String value = getString(key);
+    if (StringUtils.isNotEmpty(value)) {
+      return Long.parseLong(value);
+    }
+    return 0L;
+  }
+
+  public final Date getDate(String key) {
+    String value = getString(key);
+    if (StringUtils.isNotEmpty(value)) {
+      return DateUtils.parseDate(value);
+    }
+    return null;
+  }
+
+  public final Date getDateTime(String key) {
+    String value = getString(key);
+    if (StringUtils.isNotEmpty(value)) {
+      return DateUtils.parseDateTime(value);
+    }
+    return null;
+  }
+
+  public final String[] getStringArray(String key) {
+    return getStringArrayBySeparator(key, ",");
+  }
+
+  public final String[] getStringArrayBySeparator(String key, String separator) {
+    String value = getString(key);
+    if (value != null) {
+      return StringUtils.splitByWholeSeparator(value, separator);
+    }
+    return ArrayUtils.EMPTY_STRING_ARRAY;
+  }
+
+  public List<String> getKeysStartingWith(String prefix) {
+    List<String> result = Lists.newArrayList();
+    for (String key : properties.keySet()) {
+      if (StringUtils.startsWith(key, prefix)) {
+        result.add(key);
+      }
+    }
+    return result;
+  }
+
+
+
+  public final Settings appendProperty(String key, String value) {
+    String newValue = properties.get(key);
+    if (StringUtils.isEmpty(newValue)) {
+      newValue = value;
+    } else {
+      newValue += "," + value;
+    }
+    properties.put(key, newValue);
+    return this;
+  }
+
+  public final Settings setProperty(String key, String value) {
+    if (!clearIfNullValue(key, value)) {
+      properties.put(key, value);
+    }
+    return this;
+  }
+
+  public final Settings setProperty(String key, Boolean value) {
+    if (!clearIfNullValue(key, value)) {
+      properties.put(key, String.valueOf(value));
+    }
+    return this;
+  }
+
+  public final Settings setProperty(String key, Integer value) {
+    if (!clearIfNullValue(key, value)) {
+      properties.put(key, String.valueOf(value));
+    }
+    return this;
+  }
+
+  public final Settings setProperty(String key, Long value) {
+    if (!clearIfNullValue(key, value)) {
+      properties.put(key, String.valueOf(value));
+    }
+    return this;
+  }
+
+  public final Settings setProperty(String key, Double value) {
+    if (!clearIfNullValue(key, value)) {
+      properties.put(key, String.valueOf(value));
+    }
+    return this;
+  }
+
+  public final Settings setProperty(String key, Date date) {
+    return setProperty(key, date, false);
+  }
+
+  public final Settings addProperties(Map<String, String> props) {
+    properties.putAll(props);
+    return this;
+  }
+
+  public final Settings addProperties(Properties props) {
+    for (Map.Entry<Object, Object> entry : props.entrySet()) {
+      properties.put(entry.getKey().toString(), entry.getValue().toString());
+    }
+    return this;
+  }
+
+  public final Settings addSystemProperties() {
+    return addProperties(System.getProperties());
+  }
+
+  public final Settings addEnvironmentVariables() {
+    return addProperties(System.getenv());
+  }
+
+  public final Settings setProperties(Map<String, String> props) {
+    properties = Maps.newHashMap(props);
+    return this;
+  }
+
+  public final Settings setProperty(String key, Date date, boolean includeTime) {
+    if (!clearIfNullValue(key, date)) {
+      properties.put(key, includeTime ? DateUtils.formatDateTime(date) : DateUtils.formatDate(date));
+    }
+    return this;
+  }
+
+  public final Settings removeProperty(String key) {
+    properties.remove(key);
+    return this;
+  }
+
+  public final Settings clear() {
+    properties.clear();
+    return this;
+  }
+
+  /**
+   * @return unmodifiable properties
+   */
+  public final Map<String, String> getProperties() {
+    return Collections.unmodifiableMap(properties);
+  }
+
+  public final PropertyDefinitions getDefinitions() {
+    return definitions;
+  }
+
+  private boolean clearIfNullValue(String key, Object value) {
+    if (value == null) {
+      properties.remove(key);
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Create empty settings. Definition of available properties is loaded from the given annotated class.
+   * This method is usually used by unit tests.
+   */
+  public static Settings createForComponent(Object component) {
+    return new Settings(new PropertyDefinitions(component));
+  }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java
new file mode 100644 (file)
index 0000000..5373422
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.api.platform;
+
+import org.picocontainer.Characteristics;
+import org.picocontainer.ComponentAdapter;
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.behaviors.OptInCaching;
+import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
+import org.picocontainer.monitors.NullComponentMonitor;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.config.PropertyDefinitions;
+
+/**
+ * @since 2.12
+ */
+public class ComponentContainer implements BatchComponent, ServerComponent {
+
+  ComponentContainer parent, child; // no need for multiple children
+  MutablePicoContainer pico;
+  PropertyDefinitions propertyDefinitions;
+
+  /**
+   * Create root container
+   */
+  public ComponentContainer() {
+    this.parent = null;
+    this.child = null;
+    this.pico = createPicoContainer();
+    propertyDefinitions = new PropertyDefinitions();
+    addSingleton(propertyDefinitions);
+    addSingleton(this);
+  }
+
+  /**
+   * Create child container
+   */
+  private ComponentContainer(ComponentContainer parent) {
+    this.parent = parent;
+    this.pico = parent.pico.makeChildContainer();
+    this.parent.child = this;
+    this.propertyDefinitions = parent.propertyDefinitions;
+    addSingleton(this);
+  }
+
+  /**
+   * This method MUST NOT be renamed start() because the container is registered itself in picocontainer. Starting
+   * a component twice is not authorized.
+   */
+  public final ComponentContainer startComponents() {
+    pico.start();
+    return this;
+  }
+
+  /**
+   * This method MUST NOT be renamed stop() because the container is registered itself in picocontainer. Starting
+   * a component twice is not authorized.
+   */
+  public final ComponentContainer stopComponents() {
+    pico.stop();
+    return this;
+  }
+
+  public final ComponentContainer addSingleton(Object component) {
+    return addComponent(component, true);
+  }
+
+  /**
+   * @param singleton return always the same instance if true, else a new instance
+   *                  is returned each time the component is requested
+   */
+  public final ComponentContainer addComponent(Object component, boolean singleton) {
+    pico.as(singleton ? Characteristics.CACHE : Characteristics.NO_CACHE).addComponent(getComponentKey(component), component);
+    propertyDefinitions.addComponent(component);
+    return this;
+  }
+
+  public final ComponentContainer addExtension(PluginMetadata plugin, Object extension) {
+    pico.as(Characteristics.CACHE).addComponent(getComponentKey(extension), extension);
+    declareExtension(plugin, extension);
+    return this;
+  }
+
+  public final void declareExtension(PluginMetadata plugin, Object extension) {
+    propertyDefinitions.addComponent(extension, plugin.getName());
+  }
+
+  public final ComponentContainer addPicoAdapter(ComponentAdapter adapter) {
+    pico.addAdapter(adapter);
+    return this;
+  }
+
+  public final <T> T getComponentByType(Class<T> tClass) {
+    return pico.getComponent(tClass);
+  }
+
+  public final Object getComponentByKey(Object key) {
+    return pico.getComponent(key);
+  }
+
+  public final <T> java.util.List<T> getComponentsByType(java.lang.Class<T> tClass) {
+    return pico.getComponents(tClass);
+  }
+
+  public final ComponentContainer removeChild() {
+    if (child != null) {
+      pico.removeChildContainer(child.pico);
+      child = null;
+    }
+    return this;
+  }
+
+  public final ComponentContainer createChild() {
+    return new ComponentContainer(this);
+  }
+
+  static MutablePicoContainer createPicoContainer() {
+    ReflectionLifecycleStrategy lifecycleStrategy = new ReflectionLifecycleStrategy(new NullComponentMonitor(), "start", "stop", "dispose");
+    return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, null);
+  }
+
+  static Object getComponentKey(Object component) {
+    if (component instanceof Class) {
+      return component;
+    }
+    return new StringBuilder().append(component.getClass().getCanonicalName()).append("-").append(component.toString()).toString();
+  }
+
+  public ComponentContainer getParent() {
+    return parent;
+  }
+
+  public ComponentContainer getChild() {
+    return child;
+  }
+
+  /**
+   * Warning - do not use. This method exists only for the backward-compatibility due to the suppression
+   * of {@link org.sonar.api.utils.IocContainer}
+   * @return
+   */
+  public MutablePicoContainer getPicoContainer() {
+    return pico;
+  }
+}
index 03062e94de3d41352fa8831859903bae2a5b5d0b..ab9d26fef38a45bd21fb33f2f2454ddc5c8cf097 100644 (file)
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import com.google.common.collect.Maps;
 import org.apache.commons.lang.ArrayUtils;
 import org.sonar.api.BatchComponent;
 import org.sonar.api.ServerComponent;
@@ -36,7 +37,7 @@ import org.sonar.api.ServerComponent;
  */
 public class Languages implements BatchComponent, ServerComponent {
 
-  private final Map<String, Language> map = new HashMap<String, Language>();
+  private final Map<String, Language> map = Maps.newHashMap();
 
   /**
    * Creates a list of languages
index dda4c228c5283adc86c4112349c7c58975fd4977..99432b0313f9b2c505305c9316c1b3b51b50dbdb 100644 (file)
@@ -420,7 +420,9 @@ public class Project extends Resource {
 
   /**
    * @return the project configuration
+   * @deprecated since 2.12. The component org.sonar.api.config.Settings must be used.
    */
+  @Deprecated
   public Configuration getConfiguration() {
     return configuration;
   }
index 097fa7a2ba9bba226dad56aa84b066ed4da2d91a..1893f02e5dee9fba819d587f152be4a6a35d8c4c 100644 (file)
@@ -21,13 +21,12 @@ package org.sonar.api.utils;
 
 import com.google.common.base.Joiner;
 import com.google.common.collect.Lists;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.BatchComponent;
 import org.sonar.api.ServerComponent;
+import org.sonar.api.config.Settings;
 import org.sonar.api.platform.Server;
 
 import java.io.File;
@@ -39,7 +38,7 @@ import java.util.List;
 
 /**
  * This component downloads HTTP files
- * 
+ *
  * @since 2.2
  */
 public class HttpDownloader implements BatchComponent, ServerComponent {
@@ -48,30 +47,23 @@ public class HttpDownloader implements BatchComponent, ServerComponent {
 
   private String userAgent;
 
-  public HttpDownloader(Server server, Configuration configuration) {
-    this(configuration, server.getVersion());
-  }
-
-  public HttpDownloader(Configuration configuration) {
-    this(configuration, null);
+  public HttpDownloader(Server server, Settings settings) {
+    this(settings, server.getVersion());
   }
 
-  /**
-   * Should be package protected for unit tests only, but public is still required for jacoco 0.2.
-   */
-  public HttpDownloader() {
-    this(new PropertiesConfiguration(), null);
+  public HttpDownloader(Settings settings) {
+    this(settings, null);
   }
 
-  private HttpDownloader(Configuration configuration, String userAgent) {
-    initProxy(configuration);
+  private HttpDownloader(Settings settings, String userAgent) {
+    initProxy(settings);
     initUserAgent(userAgent);
   }
 
-  private void initProxy(Configuration configuration) {
-    propagateProxySystemProperties(configuration);
-    if (requiresProxyAuthentication(configuration)) {
-      registerProxyCredentials(configuration);
+  private void initProxy(Settings settings) {
+    propagateProxySystemProperties(settings);
+    if (requiresProxyAuthentication(settings)) {
+      registerProxyCredentials(settings);
     }
   }
 
@@ -99,27 +91,27 @@ public class HttpDownloader implements BatchComponent, ServerComponent {
     return Joiner.on(", ").join(descriptions);
   }
 
-  private void registerProxyCredentials(Configuration configuration) {
-    Authenticator.setDefault(new ProxyAuthenticator(configuration.getString("http.proxyUser"), configuration
+  private void registerProxyCredentials(Settings settings) {
+    Authenticator.setDefault(new ProxyAuthenticator(settings.getString("http.proxyUser"), settings
         .getString("http.proxyPassword")));
   }
 
-  private boolean requiresProxyAuthentication(Configuration configuration) {
-    return configuration.getString("http.proxyUser") != null;
+  private boolean requiresProxyAuthentication(Settings settings) {
+    return settings.getString("http.proxyUser") != null;
   }
 
-  private void propagateProxySystemProperties(Configuration configuration) {
-    propagateSystemProperty(configuration, "http.proxyHost");
-    propagateSystemProperty(configuration, "http.proxyPort");
-    propagateSystemProperty(configuration, "http.nonProxyHosts");
-    propagateSystemProperty(configuration, "http.auth.ntlm.domain");
-    propagateSystemProperty(configuration, "socksProxyHost");
-    propagateSystemProperty(configuration, "socksProxyPort");
+  private void propagateProxySystemProperties(Settings settings) {
+    propagateSystemProperty(settings, "http.proxyHost");
+    propagateSystemProperty(settings, "http.proxyPort");
+    propagateSystemProperty(settings, "http.nonProxyHosts");
+    propagateSystemProperty(settings, "http.auth.ntlm.domain");
+    propagateSystemProperty(settings, "socksProxyHost");
+    propagateSystemProperty(settings, "socksProxyPort");
   }
 
-  private void propagateSystemProperty(Configuration configuration, String key) {
-    if (configuration.getString(key) != null) {
-      System.setProperty(key, configuration.getString(key));
+  private void propagateSystemProperty(Settings settings, String key) {
+    if (settings.getString(key) != null) {
+      System.setProperty(key, settings.getString(key));
     }
   }
 
index 7791d04fd49151fc9eaa1995fd400ae475e27088..9d348f248c9544bb646207527cf09dcefcf354cb 100644 (file)
@@ -25,12 +25,14 @@ import org.picocontainer.MutablePicoContainer;
 import org.picocontainer.behaviors.OptInCaching;
 import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
 import org.picocontainer.monitors.NullComponentMonitor;
+import org.sonar.api.platform.ComponentContainer;
 
 
 /**
  * Proxy to inject the container as a component$
  *
  * @since 1.10
+ * @deprecated since 2.12. To be replaced by {@link org.sonar.api.platform.ComponentContainer}
  */
 public class IocContainer {
   private final MutablePicoContainer pico;
@@ -39,6 +41,10 @@ public class IocContainer {
     this.pico = pico;
   }
 
+  public IocContainer(ComponentContainer container) {
+    this.pico = container.getPicoContainer();
+  }
+
   public MutablePicoContainer getPicoContainer() {
     return pico;
   }
index 37e6e644c49a30d6f6087e51e1ac99f6abc38f34..bda9de6d1bcd162263bcd77c854582ff2f2501e5 100644 (file)
@@ -21,16 +21,12 @@ package org.sonar.api.batch;
 
 import com.google.common.collect.Lists;
 import org.junit.Test;
-import org.picocontainer.Characteristics;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.PicoContainer;
-import org.picocontainer.containers.TransientPicoContainer;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
+import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
@@ -44,10 +40,9 @@ import static org.mockito.Mockito.mock;
 public class BatchExtensionDictionnaryTest {
 
   private BatchExtensionDictionnary newSelector(BatchExtension... extensions) {
-    TransientPicoContainer iocContainer = new TransientPicoContainer();
-    int key = 0;
+    ComponentContainer iocContainer = new ComponentContainer();
     for (BatchExtension extension : extensions) {
-      iocContainer.addComponent(key++, extension);
+      iocContainer.addSingleton(extension);
     }
     return new BatchExtensionDictionnary(iocContainer);
   }
@@ -67,14 +62,14 @@ public class BatchExtensionDictionnaryTest {
 
   @Test
   public void shouldSearchInParentContainers() {
-    TransientPicoContainer grandParent = new TransientPicoContainer();
-    grandParent.as(Characteristics.CACHE).addComponent("ncloc", CoreMetrics.NCLOC);
+    ComponentContainer grandParent = new ComponentContainer();
+    grandParent.addSingleton(CoreMetrics.NCLOC);
 
-    DefaultPicoContainer parent = (DefaultPicoContainer)grandParent.makeChildContainer();
-    parent.as(Characteristics.CACHE).addComponent("coverage", CoreMetrics.COVERAGE);
+    ComponentContainer parent = grandParent.createChild();
+    parent.addSingleton(CoreMetrics.COVERAGE);
 
-    DefaultPicoContainer child = (DefaultPicoContainer)parent.makeChildContainer();
-    child.as(Characteristics.CACHE).addComponent("complexity", CoreMetrics.COMPLEXITY);
+    ComponentContainer child = parent.createChild();
+    child.addSingleton(CoreMetrics.COMPLEXITY);
 
     BatchExtensionDictionnary dictionnary = new BatchExtensionDictionnary(child);
     assertThat(dictionnary.select(Metric.class).size(), is(3));
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionsTest.java
new file mode 100644 (file)
index 0000000..857dbb8
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.api.config;
+
+import org.junit.Test;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
+
+import java.util.Arrays;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class PropertyDefinitionsTest {
+
+  @Test
+  public void shouldInspectPluginObjects() {
+    PropertyDefinitions def = new PropertyDefinitions(new PluginWithProperty(), new PluginWithProperties());
+
+    assertProperties(def);
+  }
+
+  @Test
+  public void shouldInspectPluginClasses() {
+    PropertyDefinitions def = new PropertyDefinitions(PluginWithProperty.class, PluginWithProperties.class);
+
+    assertProperties(def);
+  }
+
+  private void assertProperties(PropertyDefinitions def) {
+    assertThat(def.getProperty("foo").name(), is("Foo"));
+    assertThat(def.getProperty("one").name(), is("One"));
+    assertThat(def.getProperty("two").name(), is("Two"));
+    assertThat(def.getProperty("unknown"), nullValue());
+
+    assertThat(def.getDefaultValue("foo"), nullValue());
+    assertThat(def.getDefaultValue("two"), is("2"));
+
+    assertThat(def.getProperties().size(), is(3));
+  }
+
+  @Property(key = "foo", name = "Foo")
+  static final class PluginWithProperty {
+  }
+
+  @Properties({
+      @Property(key = "one", name = "One"),
+      @Property(key = "two", name = "Two", defaultValue = "2")
+  })
+  static final class PluginWithProperties {
+  }
+
+
+  @Test
+  public void testCategories() {
+    PropertyDefinitions def = new PropertyDefinitions(Categories.class);
+    assertThat(def.getCategory("inCateg"), is("categ"));
+    assertThat(def.getCategory("noCateg"), is(""));
+  }
+
+  @Test
+  public void testDefaultCategory() {
+    PropertyDefinitions def = new PropertyDefinitions();
+    def.addComponent(Categories.class, "default");
+    assertThat(def.getCategory("inCateg"), is("categ"));
+    assertThat(def.getCategory("noCateg"), is("default"));
+  }
+
+  @Properties({
+      @Property(key = "inCateg", name="In Categ", category = "categ"),
+      @Property(key = "noCateg", name="No categ")
+  })
+  static final class Categories {
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/SettingsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/SettingsTest.java
new file mode 100644 (file)
index 0000000..c34f127
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.api.config;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.Property;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SettingsTest {
+
+  private PropertyDefinitions definitions;
+
+  @Before
+  public void initDefinitions() {
+    definitions = new PropertyDefinitions();
+    definitions.addProperty(newProperty("hello", "world"));
+    definitions.addProperty(newProperty("date", "2010-05-18"));
+    definitions.addProperty(newProperty("boolean", "true"));
+    definitions.addProperty(newProperty("falseboolean", "false"));
+    definitions.addProperty(newProperty("integer", "12345"));
+    definitions.addProperty(newProperty("array", "one,two,three"));
+  }
+
+  private Property newProperty(String key, String defaultValue) {
+    Property prop = mock(Property.class);
+    when(prop.key()).thenReturn(key);
+    when(prop.defaultValue()).thenReturn(defaultValue);
+    return prop;
+  }
+
+  @Test
+  public void defaultValuesShouldBeLoadedFromDefinitions() {
+    Settings settings = new Settings(definitions);
+    assertThat(settings.getDefaultValue("hello"), is("world"));
+  }
+
+  @Test
+  public void testGetDefaultValue() {
+    Settings settings = new Settings(definitions);
+    assertThat(settings.getDefaultValue("unknown"), nullValue());
+  }
+
+  @Test
+  public void testGetString() {
+    Settings settings = new Settings(definitions);
+    settings.setProperty("hello", "Russia");
+    assertThat(settings.getString("hello"), is("Russia"));
+  }
+
+  @Test
+  public void testGetDate() {
+    Settings settings = new Settings(definitions);
+    assertThat(settings.getDate("date").getDate(), is(18));
+    assertThat(settings.getDate("date").getMonth(), is(4));
+  }
+
+  @Test
+  public void testGetDateNotFound() {
+    Settings settings = new Settings(definitions);
+    assertThat(settings.getDate("unknown"), CoreMatchers.<Object>nullValue());
+  }
+
+  @Test
+  public void testGetArray() {
+    Settings settings = new Settings(definitions);
+    String[] array = settings.getStringArray("array");
+    assertThat(array.length, is(3));
+    assertThat(array[0], is("one"));
+    assertThat(array[1], is("two"));
+    assertThat(array[2], is("three"));
+  }
+
+  @Test
+  public void testDefaultValueOfGetString() {
+    Settings settings = new Settings(definitions);
+    assertThat(settings.getString("hello"), is("world"));
+  }
+
+  @Test
+  public void testGetBoolean() {
+    Settings settings = new Settings(definitions);
+    assertThat(settings.getBoolean("boolean"), is(true));
+    assertThat(settings.getBoolean("falseboolean"), is(false));
+    assertThat(settings.getBoolean("unknown"), is(false));
+    assertThat(settings.getBoolean("hello"), is(false));
+  }
+
+  @Test
+  public void shouldCreateByIntrospectingComponent() {
+    Settings settings = Settings.createForComponent(MyComponent.class);
+
+    // property definition has been loaded, ie for default value
+    assertThat(settings.getDefaultValue("foo"), is("bar"));
+  }
+
+  @Property(key="foo", name="Foo", defaultValue = "bar")
+  public static class MyComponent {
+
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentContainerTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentContainerTest.java
new file mode 100644 (file)
index 0000000..f5a1735
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.api.platform;
+
+import org.junit.Test;
+import org.sonar.api.Property;
+import org.sonar.api.config.PropertyDefinitions;
+
+import static junit.framework.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class ComponentContainerTest {
+
+  @Test
+  public void shouldRegisterItself() {
+    ComponentContainer container = new ComponentContainer();
+    assertTrue(container.getComponentByType(ComponentContainer.class) == container);
+  }
+
+  @Test
+  public void testStartAndStop() {
+    ComponentContainer container = new ComponentContainer();
+    container.addSingleton(StartableComponent.class);
+    container.startComponents();
+
+    assertThat(container.getComponentByType(StartableComponent.class).started, is(true));
+    assertThat(container.getComponentByType(StartableComponent.class).stopped, is(false));
+
+    container.stopComponents();
+    assertThat(container.getComponentByType(StartableComponent.class).stopped, is(true));
+  }
+
+  @Test
+  public void testChild() {
+    ComponentContainer parent = new ComponentContainer();
+    parent.startComponents();
+
+    ComponentContainer child = parent.createChild();
+    child.addSingleton(StartableComponent.class);
+    child.startComponents();
+
+    assertTrue(child.getParent() == parent);
+    assertTrue(parent.getChild() == child);
+    assertTrue(child.getComponentByType(ComponentContainer.class) == child);
+    assertTrue(parent.getComponentByType(ComponentContainer.class) == parent);
+    assertThat(child.getComponentByType(StartableComponent.class), notNullValue());
+    assertThat(parent.getComponentByType(StartableComponent.class), nullValue());
+
+    parent.stopComponents();
+  }
+
+  @Test
+  public void testRemoveChild() {
+    ComponentContainer parent = new ComponentContainer();
+    parent.startComponents();
+
+    ComponentContainer child = parent.createChild();
+    assertTrue(parent.getChild() == child);
+
+    parent.removeChild();
+    assertThat(parent.getChild(), nullValue());
+  }
+
+  @Test
+  public void shouldForwardStartAndStopToDescendants() {
+    ComponentContainer grandParent = new ComponentContainer();
+    ComponentContainer parent = grandParent.createChild();
+    ComponentContainer child = parent.createChild();
+    child.addSingleton(StartableComponent.class);
+
+    grandParent.startComponents();
+
+    StartableComponent component = child.getComponentByType(StartableComponent.class);
+    assertTrue(component.started);
+
+    parent.stopComponents();
+    assertTrue(component.stopped);
+  }
+
+  @Test
+  public void shouldDeclareComponentProperties() {
+    ComponentContainer container = new ComponentContainer();
+    container.addSingleton(ComponentWithProperty.class);
+
+    PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
+    assertThat(propertyDefinitions.getProperty("foo"), notNullValue());
+    assertThat(propertyDefinitions.getProperty("foo").defaultValue(), is("bar"));
+  }
+
+  @Test
+  public void shouldDeclareExtensionWithoutAddingIt() {
+    ComponentContainer container = new ComponentContainer();
+    PluginMetadata plugin = mock(PluginMetadata.class);
+    container.declareExtension(plugin, ComponentWithProperty.class);
+
+    PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
+    assertThat(propertyDefinitions.getProperty("foo"), notNullValue());
+    assertThat(container.getComponentByType(ComponentWithProperty.class), nullValue());
+  }
+
+  @Test
+  public void shouldDeclareExtensionWhenAdding() {
+    ComponentContainer container = new ComponentContainer();
+    PluginMetadata plugin = mock(PluginMetadata.class);
+    container.addExtension(plugin, ComponentWithProperty.class);
+
+    PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
+    assertThat(propertyDefinitions.getProperty("foo"), notNullValue());
+    assertThat(container.getComponentByType(ComponentWithProperty.class), notNullValue());
+  }
+
+  public static class StartableComponent {
+    public boolean started = false, stopped = false;
+
+    public void start() {
+      started = true;
+    }
+
+    public void stop() {
+      stopped = true;
+    }
+  }
+
+  @Property(key = "foo", defaultValue = "bar", name = "Foo")
+  public static class ComponentWithProperty {
+
+  }
+}
index e40cffe871beb8f7b569570ad27b0cd1bebac01d..257b52b90ab27e0edce6b503c342df25abc66504 100644 (file)
  */
 package org.sonar.api.utils;
 
-import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.SystemUtils;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.mortbay.jetty.testing.ServletTester;
+import org.sonar.api.config.Settings;
 import org.sonar.api.platform.Server;
 
 import java.io.File;
@@ -37,10 +36,8 @@ import java.util.Arrays;
 import java.util.Properties;
 
 import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.not;
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertThat;
-import static org.junit.Assume.assumeThat;
 import static org.junit.internal.matchers.StringContains.containsString;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Mockito.mock;
@@ -161,20 +158,20 @@ public class HttpDownloaderTest {
 
   @Test
   public void downloadBytes() throws URISyntaxException {
-    byte[] bytes = new HttpDownloader().download(new URI(baseUrl));
+    byte[] bytes = new HttpDownloader(new Settings()).download(new URI(baseUrl));
     assertThat(bytes.length, greaterThan(10));
   }
 
   @Test
   public void downloadPlainText() throws URISyntaxException {
-    String text = new HttpDownloader().downloadPlainText(new URI(baseUrl), "UTF-8");
+    String text = new HttpDownloader(new Settings()).downloadPlainText(new URI(baseUrl), "UTF-8");
     assertThat(text.length(), greaterThan(10));
   }
 
   @Test(expected = SonarException.class)
   public void failIfServerDown() throws URISyntaxException {
     // I hope that the port 1 is not used !
-    new HttpDownloader().download(new URI("http://localhost:1/unknown"));
+    new HttpDownloader(new Settings()).download(new URI("http://localhost:1/unknown"));
   }
 
   @Test
@@ -184,7 +181,7 @@ public class HttpDownloaderTest {
     FileUtils.cleanDirectory(toDir);
     File toFile = new File(toDir, "downloadToFile.txt");
 
-    new HttpDownloader().download(new URI(baseUrl), toFile);
+    new HttpDownloader(new Settings()).download(new URI(baseUrl), toFile);
     assertThat(toFile.exists(), is(true));
     assertThat(toFile.length(), greaterThan(10l));
   }
@@ -198,7 +195,7 @@ public class HttpDownloaderTest {
 
     try {
       // I hope that the port 1 is not used !
-      new HttpDownloader().download(new URI("http://localhost:1/unknown"), toFile);
+      new HttpDownloader(new Settings()).download(new URI("http://localhost:1/unknown"), toFile);
     } catch (SonarException e) {
       assertThat(toFile.exists(), is(false));
     }
@@ -209,7 +206,7 @@ public class HttpDownloaderTest {
     Server server = mock(Server.class);
     when(server.getVersion()).thenReturn("2.2");
 
-    byte[] bytes = new HttpDownloader(server, new PropertiesConfiguration()).download(new URI(baseUrl));
+    byte[] bytes = new HttpDownloader(server, new Settings()).download(new URI(baseUrl));
     Properties props = new Properties();
     props.load(IOUtils.toInputStream(new String(bytes)));
     assertThat(props.getProperty("agent"), is("Sonar 2.2"));
@@ -217,7 +214,7 @@ public class HttpDownloaderTest {
 
   @Test
   public void followRedirect() throws URISyntaxException {
-    byte[] bytes = new HttpDownloader().download(new URI(baseUrl + "/redirect/"));
+    byte[] bytes = new HttpDownloader(new Settings()).download(new URI(baseUrl + "/redirect/"));
     assertThat(new String(bytes), containsString("count"));
   }
 
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/IocContainerTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/IocContainerTest.java
deleted file mode 100644 (file)
index abe3578..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.api.utils;
-
-import static junit.framework.Assert.assertTrue;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.core.IsNot.not;
-import static org.junit.Assert.assertThat;
-import org.junit.Test;
-import org.picocontainer.MutablePicoContainer;
-
-public class IocContainerTest {
-
-  @Test
-  public void injectContainerAsComponent() {
-    MutablePicoContainer container = IocContainer.buildPicoContainer();
-    assertThat(container.getComponent(IocContainer.class), not(nullValue()));
-
-    // only one instance
-    assertTrue(container.getComponent(IocContainer.class) == container.getComponent(IocContainer.class));
-  }
-}
index f54967ee5a7eb5d71f43a6c558c12bc37c4f0791..c4e2fda39bb80dcf9d5bae100d41b29f43752efb 100644 (file)
@@ -50,7 +50,7 @@ public class ChartsServlet extends HttpServlet {
       deprecatedDoGet(request, response);
 
     } else {
-      ChartFactory chartFactory = Platform.getInstance().getContainer().getComponent(ChartFactory.class);
+      ChartFactory chartFactory = Platform.getInstance().getContainer().getComponentByType(ChartFactory.class);
       Chart chart = chartFactory.getChart(request.getParameter("ck"));
       if (chart != null) {
         BufferedImage image = chart.generateImage(getParams(request));
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationException.java b/sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationException.java
deleted file mode 100644 (file)
index 827f77c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.server.configuration;
-
-public class ConfigurationException extends RuntimeException {
-  public ConfigurationException() {
-  }
-
-  public ConfigurationException(String s) {
-    super(s);
-  }
-
-  public ConfigurationException(String s, Throwable throwable) {
-    super(s, throwable);
-  }
-
-  public ConfigurationException(Throwable throwable) {
-    super(throwable);
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationFactory.java b/sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationFactory.java
deleted file mode 100644 (file)
index bc7f086..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.server.configuration;
-
-import org.apache.commons.configuration.*;
-import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
-import org.apache.commons.lang.text.StrLookup;
-
-import javax.servlet.ServletContextEvent;
-import java.io.File;
-import java.util.HashMap;
-
-public final class ConfigurationFactory {
-
-  public ConfigurationFactory() {
-    allowUsingEnvironmentVariables();
-  }
-
-  public Configuration getConfiguration(ServletContextEvent sce) {
-    CoreConfiguration configuration = new CoreConfiguration();
-    configuration.addConfiguration(getConfigurationFromPropertiesFile());
-    configuration.addConfiguration(new SystemConfiguration());
-    configuration.addConfiguration(new EnvironmentConfiguration());
-    configuration.addConfiguration(getDirectoriesConfiguration(sce));
-    return configuration;
-  }
-
-  private void allowUsingEnvironmentVariables() {
-    ConfigurationInterpolator.registerGlobalLookup("env", new StrLookup() {
-      @Override
-      public String lookup(String varName) {
-        return System.getenv(varName);
-      }
-    });
-  }
-
-  private Configuration getDirectoriesConfiguration(ServletContextEvent sce) {
-    MapConfiguration result = new MapConfiguration(new HashMap());
-    String webAppDir =  autodetectWebappDeployDirectory(sce);
-    result.setProperty(CoreConfiguration.DEPLOY_DIR, webAppDir);
-    return result;
-  }
-
-  protected PropertiesConfiguration getConfigurationFromPropertiesFile(String filename) {
-    try {
-      return new PropertiesConfiguration(ConfigurationFactory.class.getResource(filename));
-
-    } catch (org.apache.commons.configuration.ConfigurationException e) {
-      throw new ConfigurationException("can not load the file " + filename + " from classpath", e);
-    }
-  }
-
-  public PropertiesConfiguration getConfigurationFromPropertiesFile() {
-    return getConfigurationFromPropertiesFile("/conf/sonar.properties");
-  }
-
-  protected String autodetectWebappDeployDirectory(ServletContextEvent sce) {
-    String webAppPublicDirPath = sce.getServletContext().getRealPath("/deploy/");
-    if (webAppPublicDirPath == null) {
-      throw new ConfigurationException("Web app directory not found : /deploy/");
-    }
-    File file = new File(webAppPublicDirPath);
-    if (!file.exists()) {
-      throw new ConfigurationException("Web app directory not found : " + file);
-    }
-    return file.toString();
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationLogger.java b/sonar-server/src/main/java/org/sonar/server/configuration/ConfigurationLogger.java
deleted file mode 100644 (file)
index b63d156..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.server.configuration;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Iterator;
-
-public final class ConfigurationLogger {
-
-  private ConfigurationLogger() {
-    // only static methods
-  }
-
-  public static void log(Configuration configuration) {
-    Logger log = LoggerFactory.getLogger(ConfigurationLogger.class);
-    if (log.isDebugEnabled()) {
-      Iterator<String> keys = configuration.getKeys();
-      while (keys.hasNext()) {
-        String key = keys.next();
-        String property = getTruncatedProperty(configuration, key);
-        log.debug("Property: " + key + " is: '" + property + "'");
-      }
-    }
-  }
-
-  static String getTruncatedProperty(Configuration configuration, String key) {
-    String property = StringUtils.join(configuration.getStringArray(key), ",");
-    return StringUtils.abbreviate(property, 100);
-  }
-
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/CoreConfiguration.java b/sonar-server/src/main/java/org/sonar/server/configuration/CoreConfiguration.java
deleted file mode 100644 (file)
index 8e018e5..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.server.configuration;
-
-import org.apache.commons.configuration.CompositeConfiguration;
-import org.sonar.api.database.configuration.DatabaseConfiguration;
-
-public class CoreConfiguration extends CompositeConfiguration {
-  public static final String DEPLOY_DIR = "sonar.web.deployDir";
-
-  public DatabaseConfiguration getDatabaseConfiguration() {
-    int total = getNumberOfConfigurations();
-    for (int i = 0; i < total; i++) {
-      if (getConfiguration(i) instanceof DatabaseConfiguration) {
-        return (DatabaseConfiguration) getConfiguration(i);
-      }
-    }
-    return null;
-  }
-
-  public void reload() {
-    DatabaseConfiguration dbConfig = getDatabaseConfiguration();
-    if (dbConfig != null) {
-      dbConfig.load();
-    }
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ServerSettings.java b/sonar-server/src/main/java/org/sonar/server/configuration/ServerSettings.java
new file mode 100644 (file)
index 0000000..72b0afb
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.server.configuration;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.database.configuration.Property;
+import org.sonar.core.config.ConfigurationUtils;
+import org.sonar.jpa.session.DatabaseSessionFactory;
+
+import javax.servlet.ServletContext;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Load settings from environment, conf/sonar.properties and database
+ *
+ * @since 2.12
+ */
+public class ServerSettings extends Settings {
+
+  public static final String DEPLOY_DIR = "sonar.web.deployDir";
+
+  private DatabaseSessionFactory sessionFactory;
+  private Configuration deprecatedConfiguration;
+  private File sonarHome;
+  private File deployDir;
+
+  public ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, ServletContext servletContext) {
+    super(definitions);
+    this.deprecatedConfiguration = deprecatedConfiguration;
+    this.sonarHome = getSonarHome();
+    this.deployDir = getDeployDir(servletContext);
+    load();
+  }
+
+  public ServerSettings setSessionFactory(DatabaseSessionFactory sessionFactory) {
+    this.sessionFactory = sessionFactory;
+    return this;
+  }
+
+  public ServerSettings load() {
+    clear();
+    setProperty(CoreProperties.SONAR_HOME, sonarHome.getAbsolutePath());
+    setProperty(DEPLOY_DIR, deployDir.getAbsolutePath());
+
+    // order is important
+    loadDatabaseSettings();
+    addEnvironmentVariables();
+    addSystemProperties();
+    loadPropertiesFile();
+
+    // update deprecated configuration
+    ConfigurationUtils.copyToCommonsConfiguration(properties, deprecatedConfiguration);
+
+    return this;
+  }
+
+  private void loadDatabaseSettings() {
+    if (sessionFactory != null) {
+      DatabaseSession session = sessionFactory.getSession();
+
+      // Ugly workaround before the move to myBatis
+      // Session is not up-to-date when Ruby on Rails inserts new rows in its own transaction. Seems like
+      // Hibernate keeps a cache...
+      session.commit();
+      List<Property> properties = session.createQuery("from " + Property.class.getSimpleName() + " p where p.resourceId is null and p.userId is null").getResultList();
+
+      for (Property property : properties) {
+        setProperty(property.getKey(), property.getValue());
+      }
+    }
+  }
+
+  private void loadPropertiesFile() {
+    File propertiesFile = new File(sonarHome, "conf/sonar.properties");
+    if (!propertiesFile.isFile() || !propertiesFile.exists()) {
+      throw new IllegalStateException("Properties file does not exist: " + propertiesFile);
+    }
+
+    try {
+      Properties p = ConfigurationUtils.openProperties(propertiesFile);
+      p = ConfigurationUtils.interpolateEnvVariables(p);
+      addProperties(p);
+
+    } catch (Exception e) {
+      throw new IllegalStateException("Fail to load configuration file: " + propertiesFile, e);
+    }
+  }
+
+  static File getDeployDir(ServletContext servletContext) {
+    String dirname = servletContext.getRealPath("/deploy/");
+    if (dirname == null) {
+      throw new IllegalArgumentException("Web app directory not found : /deploy/");
+    }
+    File dir = new File(dirname);
+    if (!dir.exists()) {
+      throw new IllegalArgumentException("Web app directory does not exist: " + dir);
+    }
+    return dir;
+  }
+
+  static File getSonarHome() {
+    String home = System.getProperty("sonar.home");
+    if (StringUtils.isBlank(home)) {
+      home = System.getenv("SONAR_HOME");
+      if (StringUtils.isBlank(home)) {
+        Properties warProps = openWarProperties();
+        home = warProps.getProperty("sonar.home");
+      }
+    }
+
+    if (StringUtils.isBlank(home)) {
+      throw new IllegalStateException("Please set location to SONAR_HOME");
+    }
+
+    File dir = new File(home);
+    if (!dir.isDirectory() || !dir.exists()) {
+      throw new IllegalStateException("SONAR_HOME is not valid: " + home);
+    }
+    return dir;
+  }
+
+  private static Properties openWarProperties() {
+    try {
+      InputStream input = ServerSettings.class.getResourceAsStream("/sonar-war.properties");
+      return ConfigurationUtils.openInputStream(input);
+    } catch (IOException e) {
+      throw new IllegalStateException("Fail to load the file sonar-war.properties", e);
+    }
+  }
+}
index 0543528de6bf5dce72db4b18d2b1b23713e167f5..cf08eb2378650d028edb71d5de153e6dfe6f0d88 100644 (file)
  */
 package org.sonar.server.database;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
 import org.apache.derby.drda.NetworkServerControl;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 import org.sonar.api.utils.Logs;
 import org.sonar.api.utils.SonarException;
@@ -33,6 +34,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.InetAddress;
+import java.sql.SQLOutput;
 import java.util.Properties;
 
 public class EmbeddedDatabase {
@@ -46,9 +48,9 @@ public class EmbeddedDatabase {
   private Properties dbProps;
   private PrintWriter dbLog;
 
-  public EmbeddedDatabase(Configuration configuration) {
-    this.dbHome = autodetectDataDirectory(configuration);
-    this.dbProps = getDefaultProperties(configuration);
+  public EmbeddedDatabase(Settings settings) {
+    this.dbHome = getDataDirectory(settings);
+    this.dbProps = getDefaultProperties(settings);
   }
 
   public EmbeddedDatabase(File dbHome, Properties dbProps) {
@@ -60,10 +62,10 @@ public class EmbeddedDatabase {
     return dbHome;
   }
 
-  protected File autodetectDataDirectory(Configuration configuration) {
-    String dirName = configuration.getString(DatabaseProperties.PROP_EMBEDDED_DATA_DIR);
-    if (dirName == null) {
-      File sonarHome = new File(configuration.getString(CoreProperties.SONAR_HOME));
+  protected File getDataDirectory(Settings settings) {
+    String dirName = settings.getString(DatabaseProperties.PROP_EMBEDDED_DATA_DIR);
+    if (StringUtils.isBlank(dirName)) {
+      File sonarHome = new File(settings.getString(CoreProperties.SONAR_HOME));
       if (!sonarHome.isDirectory() || !sonarHome.exists()) {
         throw new ServerStartException("Sonar home directory does not exist");
       }
@@ -171,15 +173,15 @@ public class EmbeddedDatabase {
     }
   }
 
-  public static Properties getDefaultProperties(Configuration configuration) {
+  public static Properties getDefaultProperties(Settings settings) {
     Properties props = new Properties();
     props.setProperty("derby.drda.startNetworkServer", "true");
-    props.setProperty("derby.drda.host", configuration.getString("sonar.derby.drda.host", "localhost"));
-    props.setProperty("derby.drda.portNumber", configuration.getString("sonar.derby.drda.portNumber", "1527"));
-    props.setProperty("derby.drda.maxThreads", configuration.getString("sonar.derby.drda.maxThreads", "20"));
-    props.setProperty("derby.drda.minThreads", configuration.getString("sonar.derby.drda.minThreads", "2"));
-    props.setProperty("derby.drda.logConnections", configuration.getString("sonar.derby.drda.logConnections", "false"));
-    props.setProperty("derby.stream.error.logSeverityLevel", configuration.getString("sonar.derby.stream.error.logSeverityLevel", "20000"));
+    props.setProperty("derby.drda.host", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.host"), "localhost"));
+    props.setProperty("derby.drda.portNumber", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.portNumber"), "1527"));
+    props.setProperty("derby.drda.maxThreads", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.maxThreads"), "20"));
+    props.setProperty("derby.drda.minThreads", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.minThreads"), "2"));
+    props.setProperty("derby.drda.logConnections", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.logConnections"), "false"));
+    props.setProperty("derby.stream.error.logSeverityLevel", StringUtils.defaultIfBlank(settings.getString("sonar.derby.stream.error.logSeverityLevel"), "20000"));
     props.setProperty("derby.connection.requireAuthentication", "true");
     props.setProperty("derby.user." + DEFAULT_USER, DEFAULT_PWD);
     return props;
index 92787dee792b8d756dbae697f617a1f0b758a8d1..b60dd4f7b099dcf24c39a0fc74ac2e07a94d1d92 100644 (file)
  */
 package org.sonar.server.database;
 
-import org.apache.commons.configuration.Configuration;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 
 public class EmbeddedDatabaseFactory {
-  private Configuration configuration;
+  private Settings settings;
   private EmbeddedDatabase embeddedDatabase;
 
-  public EmbeddedDatabaseFactory(Configuration configuration) {
-    this.configuration = configuration;
+  public EmbeddedDatabaseFactory(Settings settings) {
+    this.settings = settings;
   }
 
   public void start() {
-    String jdbcUrl = configuration.getString(DatabaseProperties.PROP_URL);
-    if ((jdbcUrl!=null) && jdbcUrl.startsWith("jdbc:derby://") && jdbcUrl.contains("create=true") && embeddedDatabase==null) {
-      embeddedDatabase = new EmbeddedDatabase(configuration);
+    String jdbcUrl = settings.getString(DatabaseProperties.PROP_URL);
+    if (jdbcUrl != null && jdbcUrl.startsWith("jdbc:derby://") && jdbcUrl.contains("create=true") && embeddedDatabase == null) {
+      embeddedDatabase = new EmbeddedDatabase(settings);
       embeddedDatabase.start();
     }
   }
index abcb18f9a4cf67da54526546da265686fddb3f60..52d016c0b0eb7192e1e221eee73b3c229b436be0 100644 (file)
@@ -21,7 +21,9 @@ package org.sonar.server.database;
 
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.dbcp.BasicDataSourceFactory;
+import org.apache.commons.lang.StringUtils;
 import org.hibernate.cfg.Environment;
+import org.sonar.api.config.Settings;
 import org.sonar.api.utils.Logs;
 import org.sonar.api.utils.SonarException;
 import org.sonar.jpa.entity.SchemaMigration;
@@ -31,13 +33,14 @@ import javax.sql.DataSource;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Properties;
 
 public class JndiDatabaseConnector extends AbstractDatabaseConnector {
 
   private DataSource datasource = null;
 
-  public JndiDatabaseConnector(Configuration configuration) {
+  public JndiDatabaseConnector(Settings configuration) {
     super(configuration, false);
   }
 
@@ -72,10 +75,9 @@ public class JndiDatabaseConnector extends AbstractDatabaseConnector {
     try {
       Logs.INFO.info("Creating JDBC datasource");
       Properties properties = new Properties();
-      Configuration dsConfig = getConfiguration().subset("sonar.jdbc");
-      for (Iterator<String> it = dsConfig.getKeys(); it.hasNext(); ) {
-        String key = it.next();
-        properties.setProperty(key, dsConfig.getString(key));
+      List<String> jdbcKeys = configuration.getKeysStartingWith("sonar.jdbc.");
+      for (String jdbcKey : jdbcKeys) {
+        properties.setProperty(StringUtils.removeStart(jdbcKey, "sonar.jdbc."), configuration.getString(jdbcKey));
       }
 
       // This property is required by the Ruby Oracle enhanced adapter.
@@ -92,9 +94,6 @@ public class JndiDatabaseConnector extends AbstractDatabaseConnector {
   public Connection getConnection() throws SQLException {
     if (datasource != null) {
       Connection connection = datasource.getConnection();
-      if (getTransactionIsolation() != null) {
-        connection.setTransactionIsolation(getTransactionIsolation());
-      }
       return connection;
     }
     return null;
index 22455c1a0575c04bd5e0e64711d342f2586ea3d0..bf956a5949e49a951e58f33ef0261473b8a5b8c6 100644 (file)
  */
 package org.sonar.server.mavendeployer;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.io.FileUtils;
+import org.sonar.api.config.Settings;
 import org.sonar.api.platform.Server;
-import org.sonar.server.configuration.CoreConfiguration;
+import org.sonar.server.configuration.ServerSettings;
 import org.sonar.server.platform.DefaultServerFileSystem;
 
 import java.io.File;
@@ -34,10 +34,10 @@ public class MavenRepository {
   private final String serverId;
   private File rootDir;
 
-  public MavenRepository(Configuration configuration, DefaultServerFileSystem fileSystem, Server server) throws IOException {
+  public MavenRepository(Settings settings, DefaultServerFileSystem fileSystem, Server server) throws IOException {
     this.installation = fileSystem;
     this.serverId = server.getId();
-    initRootDir(configuration);
+    initRootDir(settings);
   }
 
   /**
@@ -60,8 +60,8 @@ public class MavenRepository {
   }
 
 
-  private void initRootDir(Configuration configuration) throws IOException {
-    this.rootDir = new File(configuration.getString(CoreConfiguration.DEPLOY_DIR), "maven");
+  private void initRootDir(Settings settings) throws IOException {
+    this.rootDir = new File(settings.getString(ServerSettings.DEPLOY_DIR), "maven");
     File orgDir = new File(rootDir, "/org/");
     if (orgDir.exists()) {
       FileUtils.forceDelete(orgDir);
index ae4f45f507a392650aa704bf22f81da663b16672..523ec15aa44640a3c920bc0e5a35b678238823fa 100644 (file)
  */
 package org.sonar.server.notifications;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.commons.configuration.Configuration;
-import org.sonar.api.ServerComponent;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
+import org.sonar.api.*;
+import org.sonar.api.config.Settings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.notifications.NotificationChannel;
 import org.sonar.api.notifications.NotificationDispatcher;
@@ -38,22 +32,30 @@ import org.sonar.api.utils.TimeProfiler;
 import org.sonar.core.notifications.DefaultNotificationManager;
 import org.sonar.jpa.entity.NotificationQueueElement;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @since 2.10
  */
+@org.sonar.api.Properties({
+    @Property(
+        key = NotificationService.PROPERTY_DELAY,
+        defaultValue = "60",
+        name = "Delay of notifications, in seconds",
+        project = false,
+        global = false)
+})
 public class NotificationService implements ServerComponent {
 
   private static final TimeProfiler TIME_PROFILER = new TimeProfiler(Logs.INFO).setLevelToDebug();
 
-  private static final String DELAY = "sonar.notifications.delay";
-  private static final long DELAY_DEFAULT = 60;
+  public static final String PROPERTY_DELAY = "sonar.notifications.delay";
 
   private ScheduledExecutorService executorService;
-  private long delay;
+  private long delayInSeconds;
 
   private DefaultNotificationManager manager;
   private NotificationChannel[] channels;
@@ -64,13 +66,13 @@ public class NotificationService implements ServerComponent {
   /**
    * Default constructor when no channels.
    */
-  public NotificationService(Configuration configuration, DefaultNotificationManager manager, NotificationDispatcher[] dispatchers) {
-    this(configuration, manager, dispatchers, new NotificationChannel[0]);
+  public NotificationService(Settings settings, DefaultNotificationManager manager, NotificationDispatcher[] dispatchers) {
+    this(settings, manager, dispatchers, new NotificationChannel[0]);
     Logs.INFO.warn("There is no channels - all notifications would be ignored!");
   }
 
-  public NotificationService(Configuration configuration, DefaultNotificationManager manager, NotificationDispatcher[] dispatchers, NotificationChannel[] channels) {
-    delay = configuration.getLong(DELAY, DELAY_DEFAULT);
+  public NotificationService(Settings settings, DefaultNotificationManager manager, NotificationDispatcher[] dispatchers, NotificationChannel[] channels) {
+    delayInSeconds = settings.getLong(PROPERTY_DELAY);
     this.manager = manager;
     this.channels = channels;
     this.dispatchers = dispatchers;
@@ -82,8 +84,8 @@ public class NotificationService implements ServerComponent {
       public void run() {
         processQueue();
       }
-    }, 0, delay, TimeUnit.SECONDS);
-    Logs.INFO.info("Notification service started (delay {} sec.)", delay);
+    }, 0, delayInSeconds, TimeUnit.SECONDS);
+    Logs.INFO.info("Notification service started (delay {} sec.)", delayInSeconds);
   }
 
   public void stop() {
index 919217b72e0f969fd31b481c6ba245fd14705715..a3ea2935404215757c47e6cab04f731dd2207c1e 100644 (file)
  */
 package org.sonar.server.platform;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 import org.sonar.api.platform.ServerFileSystem;
 import org.sonar.api.utils.Logs;
 import org.sonar.jpa.session.DatabaseConnector;
-import org.sonar.server.configuration.CoreConfiguration;
+import org.sonar.server.configuration.ServerSettings;
 
 import java.io.File;
 import java.io.IOException;
@@ -45,11 +45,11 @@ public class DefaultServerFileSystem implements ServerFileSystem {
   private File deployDir;
   private File homeDir;
 
-  public DefaultServerFileSystem(DatabaseConnector databaseConnector, Configuration configuration) {
+  public DefaultServerFileSystem(DatabaseConnector databaseConnector, Settings settings) {
     this.databaseConnector = databaseConnector;
-    this.homeDir = new File(configuration.getString(CoreProperties.SONAR_HOME));
+    this.homeDir = new File(settings.getString(CoreProperties.SONAR_HOME));
 
-    String deployPath = configuration.getString(CoreConfiguration.DEPLOY_DIR);
+    String deployPath = settings.getString(ServerSettings.DEPLOY_DIR);
     if (StringUtils.isNotBlank(deployPath)) {
       this.deployDir = new File(deployPath);
     }
index c733a99158848e42830eff39c0baa13c2eb21d80..8f65905de3e1d04cbe4a97927ba7523624dfe92f 100644 (file)
  */
 package org.sonar.server.platform;
 
-import org.apache.commons.configuration.CompositeConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.picocontainer.Characteristics;
-import org.picocontainer.MutablePicoContainer;
+import org.apache.commons.configuration.BaseConfiguration;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.Plugins;
-import org.sonar.api.database.configuration.DatabaseConfiguration;
+import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.platform.Server;
 import org.sonar.api.profiles.AnnotationProfileParser;
 import org.sonar.api.profiles.XMLProfileParser;
@@ -53,8 +50,8 @@ import org.sonar.jpa.session.DatabaseSessionFactory;
 import org.sonar.jpa.session.DatabaseSessionProvider;
 import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
 import org.sonar.server.charts.ChartFactory;
+import org.sonar.server.configuration.ServerSettings;
 import org.sonar.server.configuration.Backup;
-import org.sonar.server.configuration.ConfigurationLogger;
 import org.sonar.server.configuration.ProfilesManager;
 import org.sonar.server.database.EmbeddedDatabaseFactory;
 import org.sonar.server.database.JndiDatabaseConnector;
@@ -72,6 +69,8 @@ import org.sonar.server.ui.CodeColorizers;
 import org.sonar.server.ui.JRubyI18n;
 import org.sonar.server.ui.Views;
 
+import javax.servlet.ServletContext;
+
 /**
  * @since 2.2
  */
@@ -79,9 +78,9 @@ public final class Platform {
 
   private static final Platform INSTANCE = new Platform();
 
-  private MutablePicoContainer rootContainer;// level 1 : only database connectors
-  private MutablePicoContainer coreContainer;// level 2 : level 1 + core components
-  private MutablePicoContainer servicesContainer;// level 3 : level 2 + plugin extensions + core components that depend on plugin extensions
+  private ComponentContainer rootContainer;// level 1 : only database connectors
+  private ComponentContainer coreContainer;// level 2 : level 1 + core components
+  private ComponentContainer servicesContainer;// level 3 : level 2 + plugin extensions + core components that depend on plugin extensions
 
   private boolean connected = false;
   private boolean started = false;
@@ -93,10 +92,10 @@ public final class Platform {
   private Platform() {
   }
 
-  public void init(Configuration conf) {
+  public void init(ServletContext servletContext) {
     if (!connected) {
       try {
-        startDatabaseConnectors(conf);
+        startDatabaseConnectors(servletContext);
         connected = true;
 
       } catch (Exception e) {
@@ -116,117 +115,117 @@ public final class Platform {
     }
   }
 
-  private void startDatabaseConnectors(Configuration configuration) {
-    rootContainer = IocContainer.buildPicoContainer();
-    ConfigurationLogger.log(configuration);
-
-    rootContainer.as(Characteristics.CACHE).addComponent(configuration);
-    rootContainer.as(Characteristics.CACHE).addComponent(EmbeddedDatabaseFactory.class);
-    rootContainer.as(Characteristics.CACHE).addComponent(JndiDatabaseConnector.class);
-    rootContainer.as(Characteristics.CACHE).addComponent(DefaultServerUpgradeStatus.class);
-    rootContainer.start();
-
-    // Platform is already starting, so it's registered after the container startup
+  private void startDatabaseConnectors(ServletContext servletContext) {
+    rootContainer = new ComponentContainer();
+    rootContainer.addSingleton(servletContext);
+    rootContainer.addSingleton(IocContainer.class); // for backward compatibility
+    rootContainer.addSingleton(new BaseConfiguration());
+    rootContainer.addSingleton(ServerSettings.class);
+    rootContainer.addSingleton(EmbeddedDatabaseFactory.class);
+    rootContainer.addSingleton(JndiDatabaseConnector.class);
+    rootContainer.addSingleton(DefaultServerUpgradeStatus.class);
+    rootContainer.startComponents();
   }
 
   private boolean isUpToDateDatabase() {
-    JndiDatabaseConnector databaseConnector = getContainer().getComponent(JndiDatabaseConnector.class);
+    JndiDatabaseConnector databaseConnector = getContainer().getComponentByType(JndiDatabaseConnector.class);
     return databaseConnector.isOperational();
   }
 
   private void startCoreComponents() {
-    coreContainer = rootContainer.makeChildContainer();
-    coreContainer.as(Characteristics.CACHE).addComponent(PluginDeployer.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(DefaultServerPluginRepository.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(DefaultServerFileSystem.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(ThreadLocalDatabaseSessionFactory.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(HttpDownloader.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(UpdateCenterClient.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(UpdateCenterMatrixFactory.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(PluginDownloader.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(ServerIdGenerator.class);
-    coreContainer.as(Characteristics.CACHE).addComponent(ServerImpl.class);
-    coreContainer.as(Characteristics.NO_CACHE).addComponent(FilterExecutor.class);
-    coreContainer.as(Characteristics.NO_CACHE).addAdapter(new DatabaseSessionProvider());
-    coreContainer.start();
+    coreContainer = rootContainer.createChild();
+    coreContainer.addSingleton(PluginDeployer.class);
+    coreContainer.addSingleton(DefaultServerPluginRepository.class);
+    coreContainer.addSingleton(ServerExtensionInstaller.class);
+    coreContainer.addSingleton(DefaultServerFileSystem.class);
+    coreContainer.addSingleton(ThreadLocalDatabaseSessionFactory.class);
+    coreContainer.addPicoAdapter(new DatabaseSessionProvider());
+    coreContainer.startComponents();
 
-    DatabaseConfiguration dbConfiguration = new DatabaseConfiguration(coreContainer.getComponent(DatabaseSessionFactory.class));
-    coreContainer.getComponent(CompositeConfiguration.class).addConfiguration(dbConfiguration);
+    DatabaseSessionFactory sessionFactory = coreContainer.getComponentByType(DatabaseSessionFactory.class);
+    ServerSettings serverSettings = coreContainer.getComponentByType(ServerSettings.class);
+    serverSettings.setSessionFactory(sessionFactory);
+    serverSettings.load();
   }
 
   /**
    * plugin extensions + all the components that depend on plugin extensions
    */
   private void startServiceComponents() {
-    servicesContainer = coreContainer.makeChildContainer();
-
-    DefaultServerPluginRepository pluginRepository = servicesContainer.getComponent(DefaultServerPluginRepository.class);
-    pluginRepository.registerExtensions(servicesContainer);
+    servicesContainer = coreContainer.createChild();
+    ServerExtensionInstaller extensionRegistrar = servicesContainer.getComponentByType(ServerExtensionInstaller.class);
+    extensionRegistrar.registerExtensions(servicesContainer);
 
-    servicesContainer.as(Characteristics.CACHE).addComponent(DefaultModelFinder.class); // depends on plugins
-    servicesContainer.as(Characteristics.CACHE).addComponent(DefaultModelManager.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(Plugins.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(ChartFactory.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(Languages.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(Views.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(CodeColorizers.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(RulesDao.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(MeasuresDao.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(org.sonar.api.database.daos.MeasuresDao.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(ProfilesDao.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(DaoFacade.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(DefaultRulesManager.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(ProfilesManager.class);
-    servicesContainer.as(Characteristics.NO_CACHE).addComponent(Backup.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(AuthenticatorFactory.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(ServerLifecycleNotifier.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(AnnotationProfileParser.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(XMLProfileParser.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(XMLProfileSerializer.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(AnnotationRuleParser.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(XMLRuleParser.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(DefaultRuleFinder.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(DefaultMetricFinder.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(ProfilesConsole.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(RulesConsole.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(JRubyI18n.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(DefaultUserFinder.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(I18nManager.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(RuleI18nManager.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(GwtI18n.class);
+    servicesContainer.addSingleton(HttpDownloader.class);
+    servicesContainer.addSingleton(UpdateCenterClient.class);
+    servicesContainer.addSingleton(UpdateCenterMatrixFactory.class);
+    servicesContainer.addSingleton(PluginDownloader.class);
+    servicesContainer.addSingleton(ServerIdGenerator.class);
+    servicesContainer.addSingleton(ServerImpl.class);
+    servicesContainer.addComponent(FilterExecutor.class, false);
+    servicesContainer.addSingleton(DefaultModelFinder.class); // depends on plugins
+    servicesContainer.addSingleton(DefaultModelManager.class);
+    servicesContainer.addSingleton(Plugins.class);
+    servicesContainer.addSingleton(ChartFactory.class);
+    servicesContainer.addSingleton(Languages.class);
+    servicesContainer.addSingleton(Views.class);
+    servicesContainer.addSingleton(CodeColorizers.class);
+    servicesContainer.addComponent(RulesDao.class, false);
+    servicesContainer.addComponent(MeasuresDao.class, false);
+    servicesContainer.addComponent(org.sonar.api.database.daos.MeasuresDao.class, false);
+    servicesContainer.addComponent(ProfilesDao.class, false);
+    servicesContainer.addComponent(DaoFacade.class, false);
+    servicesContainer.addComponent(DefaultRulesManager.class, false);
+    servicesContainer.addComponent(ProfilesManager.class, false);
+    servicesContainer.addComponent(Backup.class, false);
+    servicesContainer.addSingleton(AuthenticatorFactory.class);
+    servicesContainer.addSingleton(ServerLifecycleNotifier.class);
+    servicesContainer.addSingleton(AnnotationProfileParser.class);
+    servicesContainer.addSingleton(XMLProfileParser.class);
+    servicesContainer.addSingleton(XMLProfileSerializer.class);
+    servicesContainer.addSingleton(AnnotationRuleParser.class);
+    servicesContainer.addSingleton(XMLRuleParser.class);
+    servicesContainer.addSingleton(DefaultRuleFinder.class);
+    servicesContainer.addSingleton(DefaultMetricFinder.class);
+    servicesContainer.addSingleton(ProfilesConsole.class);
+    servicesContainer.addSingleton(RulesConsole.class);
+    servicesContainer.addSingleton(JRubyI18n.class);
+    servicesContainer.addSingleton(DefaultUserFinder.class);
+    servicesContainer.addSingleton(I18nManager.class);
+    servicesContainer.addSingleton(RuleI18nManager.class);
+    servicesContainer.addSingleton(GwtI18n.class);
 
     // Notifications
-    servicesContainer.as(Characteristics.CACHE).addComponent(NotificationService.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(DefaultNotificationManager.class);
-    servicesContainer.as(Characteristics.CACHE).addComponent(ReviewsNotificationManager.class);
+    servicesContainer.addSingleton(NotificationService.class);
+    servicesContainer.addSingleton(DefaultNotificationManager.class);
+    servicesContainer.addSingleton(ReviewsNotificationManager.class);
 
-    servicesContainer.start();
+    servicesContainer.startComponents();
   }
 
   private void executeStartupTasks() {
-    MutablePicoContainer startupContainer = servicesContainer.makeChildContainer();
+    ComponentContainer startupContainer = servicesContainer.createChild();
     try {
-      startupContainer.as(Characteristics.CACHE).addComponent(MavenRepository.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(GwtPublisher.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(RegisterMetrics.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(RegisterRules.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(RegisterProvidedProfiles.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(EnableProfiles.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(ActivateDefaultProfiles.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(JdbcDriverDeployer.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(ServerMetadataPersister.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(RegisterQualityModels.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(DeleteDeprecatedMeasures.class);
-      startupContainer.as(Characteristics.CACHE).addComponent(GeneratePluginIndex.class);
-      startupContainer.start();
+      startupContainer.addSingleton(MavenRepository.class);
+      startupContainer.addSingleton(GwtPublisher.class);
+      startupContainer.addSingleton(RegisterMetrics.class);
+      startupContainer.addSingleton(RegisterRules.class);
+      startupContainer.addSingleton(RegisterProvidedProfiles.class);
+      startupContainer.addSingleton(EnableProfiles.class);
+      startupContainer.addSingleton(ActivateDefaultProfiles.class);
+      startupContainer.addSingleton(JdbcDriverDeployer.class);
+      startupContainer.addSingleton(ServerMetadataPersister.class);
+      startupContainer.addSingleton(RegisterQualityModels.class);
+      startupContainer.addSingleton(DeleteDeprecatedMeasures.class);
+      startupContainer.addSingleton(GeneratePluginIndex.class);
+      startupContainer.startComponents();
 
-      startupContainer.getComponent(ServerLifecycleNotifier.class).notifyStart();
+      startupContainer.getComponentByType(ServerLifecycleNotifier.class).notifyStart();
 
     } finally {
-      startupContainer.stop();
-      servicesContainer.removeChildContainer(startupContainer);
-      startupContainer = null;
-      servicesContainer.getComponent(DatabaseSessionFactory.class).clear();
+      startupContainer.stopComponents();
+      servicesContainer.removeChild();
+      servicesContainer.getComponentByType(DatabaseSessionFactory.class).clear();
     }
   }
 
@@ -234,7 +233,7 @@ public final class Platform {
     if (rootContainer != null) {
       try {
         TimeProfiler profiler = new TimeProfiler().start("Stop sonar");
-        rootContainer.stop();
+        rootContainer.stopComponents();
         rootContainer = null;
         connected = false;
         started = false;
@@ -245,7 +244,7 @@ public final class Platform {
     }
   }
 
-  public MutablePicoContainer getContainer() {
+  public ComponentContainer getContainer() {
     if (servicesContainer != null) {
       return servicesContainer;
     }
@@ -256,7 +255,7 @@ public final class Platform {
   }
 
   public Object getComponent(Object key) {
-    return getContainer().getComponent(key);
+    return getContainer().getComponentByKey(key);
   }
 
   /**
index 22d798048c1a83c529f09ba0c76e40e972cd534d..526e4f6823964becc8dcb5733c513478280c189c 100644 (file)
  */
 package org.sonar.server.platform;
 
-import org.apache.commons.configuration.Configuration;
-import org.sonar.server.configuration.ConfigurationFactory;
-
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
 
 public final class PlatformLifecycleListener implements ServletContextListener {
 
   public void contextInitialized(ServletContextEvent event) {
-    Configuration configuration = new ConfigurationFactory().getConfiguration(event);
-    Platform.getInstance().init(configuration);
+    Platform.getInstance().init(event.getServletContext());
     Platform.getInstance().start();
   }
 
index 73defaa30d4423b0d6d0dcd7322eeb06a42f5aae..864b8a06a0bcb42a4eb0d4cece94bfadfcdf1326 100644 (file)
 package org.sonar.server.plugins;
 
 import com.google.common.collect.Sets;
-import org.picocontainer.Characteristics;
-import org.picocontainer.MutablePicoContainer;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.*;
+import org.sonar.api.Plugin;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
 import org.sonar.api.platform.PluginMetadata;
 import org.sonar.api.platform.ServerPluginRepository;
 import org.sonar.core.plugins.PluginClassloaders;
 
 import java.util.Collection;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -49,7 +48,8 @@ public class DefaultServerPluginRepository implements ServerPluginRepository {
   }
 
   public void start() {
-    pluginsByKey = classloaders.init(deployer.getMetadata());
+    Collection<PluginMetadata> metadata = deployer.getMetadata();
+    pluginsByKey = classloaders.init(metadata);
   }
 
   public void stop() {
@@ -117,55 +117,4 @@ public class DefaultServerPluginRepository implements ServerPluginRepository {
     return deployer.getMetadata(pluginKey);
   }
 
-  public void registerExtensions(MutablePicoContainer container) {
-    registerExtensions(container, getPlugins());
-  }
-
-  void registerExtensions(MutablePicoContainer container, Collection<Plugin> plugins) {
-    for (Plugin plugin : plugins) {
-      container.as(Characteristics.CACHE).addComponent(plugin);
-      for (Object extension : plugin.getExtensions()) {
-        installExtension(container, extension, true);
-      }
-    }
-    installExtensionProviders(container);
-  }
-
-  void installExtensionProviders(MutablePicoContainer container) {
-    List<ExtensionProvider> providers = container.getComponents(ExtensionProvider.class);
-    for (ExtensionProvider provider : providers) {
-      Object obj = provider.provide();
-      if (obj != null) {
-        if (obj instanceof Iterable) {
-          for (Object extension : (Iterable) obj) {
-            installExtension(container, extension, false);
-          }
-        } else {
-          installExtension(container, obj, false);
-        }
-      }
-    }
-  }
-
-  void installExtension(MutablePicoContainer container, Object extension, boolean acceptProvider) {
-    if (isType(extension, ServerExtension.class)) {
-      if (!acceptProvider && (isType(extension, ExtensionProvider.class) || extension instanceof ExtensionProvider)) {
-        LoggerFactory.getLogger(getClass()).error("ExtensionProvider can not include providers itself: " + extension);
-      } else {
-        container.as(Characteristics.CACHE).addComponent(getExtensionKey(extension), extension);
-      }
-    }
-  }
-
-  static boolean isType(Object extension, Class<? extends Extension> extensionClass) {
-    Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass());
-    return extensionClass.isAssignableFrom(clazz);
-  }
-
-  static Object getExtensionKey(Object component) {
-    if (component instanceof Class) {
-      return component;
-    }
-    return component.getClass().getCanonicalName() + "-" + component.toString();
-  }
 }
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java b/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java
new file mode 100644 (file)
index 0000000..cf672d0
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.server.plugins;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Maps;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.Extension;
+import org.sonar.api.ExtensionProvider;
+import org.sonar.api.Plugin;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.platform.ComponentContainer;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+
+import java.util.Map;
+
+public class ServerExtensionInstaller {
+  private PluginRepository pluginRepository;
+
+  public ServerExtensionInstaller(PluginRepository pluginRepository) {
+    this.pluginRepository = pluginRepository;
+  }
+
+  public void registerExtensions(ComponentContainer container) {
+    ListMultimap<PluginMetadata, Object> installedExtensionsByPlugin = ArrayListMultimap.create();
+
+    for (PluginMetadata pluginMetadata : pluginRepository.getMetadata()) {
+      Plugin plugin = pluginRepository.getPlugin(pluginMetadata.getKey());
+      container.addExtension(pluginMetadata, plugin);
+
+      for (Object extension : plugin.getExtensions()) {
+        if (installExtension(container, pluginMetadata, extension, true) != null) {
+          installedExtensionsByPlugin.put(pluginMetadata, extension);
+        } else {
+          container.declareExtension(pluginMetadata, extension);
+        }
+      }
+    }
+    for (Map.Entry<PluginMetadata, Object> entry : installedExtensionsByPlugin.entries()) {
+      PluginMetadata plugin = entry.getKey();
+      Object extension = entry.getValue();
+      if (isExtensionProvider(extension)) {
+        ExtensionProvider provider = (ExtensionProvider) container.getComponentByKey(extension);
+        installProvider(container, plugin, provider);
+      }
+    }
+  }
+
+  private void installProvider(ComponentContainer container, PluginMetadata plugin, ExtensionProvider provider) {
+    Object obj = provider.provide();
+    if (obj != null) {
+      if (obj instanceof Iterable) {
+        for (Object ext : (Iterable) obj) {
+          installExtension(container, plugin, ext, false);
+        }
+      } else {
+        installExtension(container, plugin, obj, false);
+      }
+    }
+  }
+
+  Object installExtension(ComponentContainer container, PluginMetadata pluginMetadata, Object extension, boolean acceptProvider) {
+    if (isType(extension, ServerExtension.class)) {
+      if (!acceptProvider && isExtensionProvider(extension)) {
+        LoggerFactory.getLogger(getClass()).error("ExtensionProvider can not include providers itself: " + extension);
+      } else {
+        container.addExtension(pluginMetadata, extension);
+        return extension;
+      }
+    }
+    return null;
+  }
+
+  static boolean isExtensionProvider(Object extension) {
+    return isType(extension, ExtensionProvider.class) || extension instanceof ExtensionProvider;
+  }
+
+  static boolean isType(Object extension, Class<? extends Extension> extensionClass) {
+    Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass());
+    return extensionClass.isAssignableFrom(clazz);
+  }
+}
index 1dca1b380eac0edf2f6a60a1f14d559e2f0e6c8a..83068721c6c35d0af3ac002eaf1188a0d6aa539a 100644 (file)
@@ -44,7 +44,7 @@ public class StaticResourcesServlet extends HttpServlet {
     String pluginKey = getPluginKey(request);
     String resource = getResourcePath(request);
 
-    DefaultServerPluginRepository pluginRepository = Platform.getInstance().getContainer().getComponent(DefaultServerPluginRepository.class);
+    DefaultServerPluginRepository pluginRepository = Platform.getInstance().getContainer().getComponentByType(DefaultServerPluginRepository.class);
     ClassLoader classLoader = pluginRepository.getClassloader(pluginKey);
     if (classLoader == null) {
       LOG.error("Plugin not found: " + pluginKey);
index 7dbcc8543d175e32585f265d06db32656adf1668..32a7ae076b342be0da7552706f52ae9c377f215e 100644 (file)
  */
 package org.sonar.server.plugins;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.io.IOUtils;
 import org.slf4j.LoggerFactory;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
 import org.sonar.api.ServerComponent;
+import org.sonar.api.config.Settings;
 import org.sonar.api.utils.HttpDownloader;
 import org.sonar.api.utils.Logs;
 import org.sonar.updatecenter.common.UpdateCenter;
@@ -32,17 +34,32 @@ import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Date;
-import java.util.Properties;
+
 
 /**
  * HTTP client to load data from the remote update center hosted at http://update.sonarsource.org.
  *
  * @since 2.4
  */
+@Properties({
+    @Property(
+        key = "sonar.updatecenter.activate",
+        defaultValue = "true",
+        name = "Enable Update Center",
+        project = false,
+        global = false, // hidden from UI
+        category = "Update Center"),
+    @Property(
+        key = UpdateCenterClient.URL_PROPERTY,
+        defaultValue = "http://update.sonarsource.org/update-center.properties",
+        name = "Update Center URL",
+        project = false,
+        global = false, // hidden from UI
+        category = "Update Center")
+})
 public class UpdateCenterClient implements ServerComponent {
 
   public static final String URL_PROPERTY = "sonar.updatecenter.url";
-  public static final String DEFAULT_URL = "http://update.sonarsource.org/update-center.properties";
   public static final int PERIOD_IN_MILLISECONDS = 60 * 60 * 1000;
 
   private URI uri;
@@ -59,8 +76,8 @@ public class UpdateCenterClient implements ServerComponent {
     Logs.INFO.info("Update center: " + uri + " (" + downloader.getProxySynthesis(uri) + ")");
   }
 
-  public UpdateCenterClient(HttpDownloader downloader, Configuration configuration) throws URISyntaxException {
-    this(downloader, new URI(configuration.getString(URL_PROPERTY, DEFAULT_URL)));
+  public UpdateCenterClient(HttpDownloader downloader, Settings configuration) throws URISyntaxException {
+    this(downloader, new URI(configuration.getString(URL_PROPERTY)));
   }
 
   public UpdateCenter getCenter() {
@@ -88,7 +105,7 @@ public class UpdateCenterClient implements ServerComponent {
     try {
       input = downloader.openStream(uri);
       if (input != null) {
-        Properties properties = new Properties();
+        java.util.Properties properties = new java.util.Properties();
         properties.load(input);
         return UpdateCenterDeserializer.fromProperties(properties);
       }
index fd7fb4a501da167e4283fef37562fe56543c1278..f61f2bc1b735c5617d4d74a3ab2ac6fd2e8a2f4c 100644 (file)
  */
 package org.sonar.server.startup;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
 import org.sonar.api.utils.Logs;
 import org.sonar.api.utils.SonarException;
 import org.sonar.api.utils.TimeProfiler;
 import org.sonar.api.utils.ZipUtils;
 import org.sonar.api.web.GwtExtension;
-import org.sonar.server.configuration.CoreConfiguration;
+import org.sonar.server.configuration.ServerSettings;
 
 import java.io.File;
 import java.io.IOException;
@@ -41,13 +41,13 @@ import java.util.zip.ZipEntry;
 public class GwtPublisher {
   private static final Logger LOG = LoggerFactory.getLogger(GwtPublisher.class);
 
-  private Configuration configuration;
+  private Settings settings;
   private GwtExtension[] extensions = null;
   private File outputDir = null;
 
-  public GwtPublisher(GwtExtension[] extensions, Configuration configuration) {
+  public GwtPublisher(GwtExtension[] extensions, Settings settings) {
     this.extensions = extensions;
-    this.configuration = configuration;
+    this.settings = settings;
   }
 
   protected GwtPublisher(GwtExtension[] extensions, File outputDir) {
@@ -62,7 +62,7 @@ public class GwtPublisher {
     TimeProfiler profiler = new TimeProfiler().start("Deploy GWT plugins");
     try {
       cleanDirectory();
-      this.outputDir = new File(configuration.getString(CoreConfiguration.DEPLOY_DIR), "gwt");
+      this.outputDir = new File(settings.getString(ServerSettings.DEPLOY_DIR), "gwt");
       Logs.INFO.debug("publish {} GWT extensions to {}", extensions.length, outputDir);
       publish();
 
index ed42799fd97e4d4a3ad67b9326ff5798401c0d17..17038c0975687825b5c27babca696db77ebb3ffe 100644 (file)
  */
 package org.sonar.server.ui;
 
-import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.ServerComponent;
+import org.sonar.api.config.Settings;
 import org.sonar.api.security.LoginPasswordAuthenticator;
 
 public class AuthenticatorFactory implements ServerComponent {
@@ -37,17 +37,17 @@ public class AuthenticatorFactory implements ServerComponent {
   private boolean ignoreStartupFailure;
   private LoginPasswordAuthenticator[] authenticators;
 
-  public AuthenticatorFactory(Configuration configuration, LoginPasswordAuthenticator[] authenticators) {
-    classname = configuration.getString(CoreProperties.CORE_AUTHENTICATOR_CLASS);
-    ignoreStartupFailure = configuration.getBoolean(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE, false);
+  public AuthenticatorFactory(Settings settings, LoginPasswordAuthenticator[] authenticators) {
+    classname = settings.getString(CoreProperties.CORE_AUTHENTICATOR_CLASS);
+    ignoreStartupFailure = settings.getBoolean(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE);
     this.authenticators = authenticators;
   }
 
   /**
    * This constructor is used when there aren't any authentication plugins.
    */
-  public AuthenticatorFactory(Configuration configuration) {
-    this(configuration, null);
+  public AuthenticatorFactory(Settings settings) {
+    this(settings, null);
   }
 
   /**
index 1c7d6f43123c7bacbe19b52b1711baf5b25dfaa9..7b8db246bce665958941ed28dc32cb4a66dcad2f 100644 (file)
@@ -33,7 +33,7 @@ public class DatabaseSessionFilter implements Filter {
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
     chain.doFilter(request, response);
 
-    DatabaseSessionFactory sessionFactory = Platform.getInstance().getContainer().getComponent(DatabaseSessionFactory.class);
+    DatabaseSessionFactory sessionFactory = Platform.getInstance().getContainer().getComponentByType(DatabaseSessionFactory.class);
     if (sessionFactory != null) {
       sessionFactory.clear();
     }
index bb8d0d3b99b2cfcd99843718600341bde4339199..59598488060843e0951b73a273ca04ed373a268c 100644 (file)
 package org.sonar.server.ui;
 
 import org.apache.commons.configuration.Configuration;
-import org.picocontainer.PicoContainer;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.Property;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.platform.PluginMetadata;
 import org.sonar.api.platform.PluginRepository;
 import org.sonar.api.profiles.ProfileExporter;
@@ -36,8 +37,8 @@ import org.sonar.core.i18n.RuleI18nManager;
 import org.sonar.jpa.dialect.Dialect;
 import org.sonar.jpa.session.DatabaseConnector;
 import org.sonar.markdown.Markdown;
+import org.sonar.server.configuration.ServerSettings;
 import org.sonar.server.configuration.Backup;
-import org.sonar.server.configuration.CoreConfiguration;
 import org.sonar.server.configuration.ProfilesManager;
 import org.sonar.server.filters.Filter;
 import org.sonar.server.filters.FilterExecutor;
@@ -66,52 +67,51 @@ public final class JRubyFacade {
   }
 
   public FilterResult executeFilter(Filter filter) {
-    return getContainer().getComponent(FilterExecutor.class).execute(filter);
+    return getContainer().getComponentByType(FilterExecutor.class).execute(filter);
   }
 
   // UPDATE CENTER ------------------------------------------------------------
 
   public void downloadPlugin(String pluginKey, String pluginVersion) {
-    getContainer().getComponent(PluginDownloader.class).download(pluginKey, Version.create(pluginVersion));
+    getContainer().getComponentByType(PluginDownloader.class).download(pluginKey, Version.create(pluginVersion));
   }
 
   public void cancelPluginDownloads() {
-    getContainer().getComponent(PluginDownloader.class).cancelDownloads();
+    getContainer().getComponentByType(PluginDownloader.class).cancelDownloads();
   }
 
   public List<String> getPluginDownloads() {
-    return getContainer().getComponent(PluginDownloader.class).getDownloads();
+    return getContainer().getComponentByType(PluginDownloader.class).getDownloads();
   }
 
   public void uninstallPlugin(String pluginKey) {
-    getContainer().getComponent(PluginDeployer.class).uninstall(pluginKey);
+    getContainer().getComponentByType(PluginDeployer.class).uninstall(pluginKey);
   }
 
   public void cancelPluginUninstalls() {
-    getContainer().getComponent(PluginDeployer.class).cancelUninstalls();
+    getContainer().getComponentByType(PluginDeployer.class).cancelUninstalls();
   }
 
   public List<String> getPluginUninstalls() {
-    return getContainer().getComponent(PluginDeployer.class).getUninstalls();
+    return getContainer().getComponentByType(PluginDeployer.class).getUninstalls();
   }
 
   public UpdateCenterMatrix getUpdateCenterMatrix(boolean forceReload) {
-    return getContainer().getComponent(UpdateCenterMatrixFactory.class).getMatrix(forceReload);
+    return getContainer().getComponentByType(UpdateCenterMatrixFactory.class).getMatrix(forceReload);
   }
 
   // PLUGINS ------------------------------------------------------------------
 
-  public Property[] getPluginProperties(PluginMetadata metadata) {
-    PluginRepository repository = getContainer().getComponent(PluginRepository.class);
-    return repository.getProperties(repository.getPlugin(metadata.getKey()));
+  public PropertyDefinitions getPropertyDefinitions() {
+    return getContainer().getComponentByType(PropertyDefinitions.class);
   }
 
   public boolean hasPlugin(String key) {
-    return getContainer().getComponent(PluginRepository.class).getPlugin(key) != null;
+    return getContainer().getComponentByType(PluginRepository.class).getPlugin(key) != null;
   }
 
   public Collection<PluginMetadata> getPluginsMetadata() {
-    return getContainer().getComponent(PluginRepository.class).getMetadata();
+    return getContainer().getComponentByType(PluginRepository.class).getMetadata();
   }
 
 
@@ -119,7 +119,7 @@ public final class JRubyFacade {
 
   public String colorizeCode(String code, String language) {
     try {
-      return getContainer().getComponent(CodeColorizers.class).toHtml(code, language);
+      return getContainer().getComponentByType(CodeColorizers.class).toHtml(code, language);
 
     } catch (Exception e) {
       LoggerFactory.getLogger(getClass()).error("Can not highlight the code, language= " + language, e);
@@ -133,89 +133,89 @@ public final class JRubyFacade {
 
 
   public List<ViewProxy<Widget>> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage) {
-    return getContainer().getComponent(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage);
+    return getContainer().getComponentByType(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage);
   }
 
   public List<ViewProxy<Widget>> getWidgets() {
-    return getContainer().getComponent(Views.class).getWidgets();
+    return getContainer().getComponentByType(Views.class).getWidgets();
   }
 
   public ViewProxy<Widget> getWidget(String id) {
-    return getContainer().getComponent(Views.class).getWidget(id);
+    return getContainer().getComponentByType(Views.class).getWidget(id);
   }
 
   public List<ViewProxy<Page>> getPages(String section, String resourceScope, String resourceQualifier, String resourceLanguage) {
-    return getContainer().getComponent(Views.class).getPages(section, resourceScope, resourceQualifier, resourceLanguage);
+    return getContainer().getComponentByType(Views.class).getPages(section, resourceScope, resourceQualifier, resourceLanguage);
   }
 
   public List<ViewProxy<Page>> getResourceTabs() {
-    return getContainer().getComponent(Views.class).getPages(NavigationSection.RESOURCE_TAB, null, null, null);
+    return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, null, null, null);
   }
 
   public List<ViewProxy<Page>> getResourceTabs(String scope, String qualifier, String language) {
-    return getContainer().getComponent(Views.class).getPages(NavigationSection.RESOURCE_TAB, scope, qualifier, language);
+    return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, scope, qualifier, language);
   }
 
   public List<ViewProxy<Page>> getResourceTabsForMetric(String scope, String qualifier, String language, String metric) {
-    return getContainer().getComponent(Views.class).getPagesForMetric(NavigationSection.RESOURCE_TAB, scope, qualifier, language, metric);
+    return getContainer().getComponentByType(Views.class).getPagesForMetric(NavigationSection.RESOURCE_TAB, scope, qualifier, language, metric);
   }
 
   public ViewProxy<Page> getPage(String id) {
-    return getContainer().getComponent(Views.class).getPage(id);
+    return getContainer().getComponentByType(Views.class).getPage(id);
   }
 
   public Collection<RubyRailsWebservice> getRubyRailsWebservices() {
-    return getContainer().getComponents(RubyRailsWebservice.class);
+    return getContainer().getComponentsByType(RubyRailsWebservice.class);
   }
 
   public Collection<Language> getLanguages() {
-    return getContainer().getComponents(Language.class);
+    return getContainer().getComponentsByType(Language.class);
   }
 
   public Dialect getDialect() {
-    return getContainer().getComponent(DatabaseConnector.class).getDialect();
+    return getContainer().getComponentByType(DatabaseConnector.class).getDialect();
   }
 
   /* PROFILES CONSOLE : RULES AND METRIC THRESHOLDS */
 
   public List<RuleRepository> getRuleRepositories() {
-    return getContainer().getComponent(RulesConsole.class).getRepositories();
+    return getContainer().getComponentByType(RulesConsole.class).getRepositories();
   }
 
   public RuleRepository getRuleRepository(String repositoryKey) {
-    return getContainer().getComponent(RulesConsole.class).getRepository(repositoryKey);
+    return getContainer().getComponentByType(RulesConsole.class).getRepository(repositoryKey);
   }
 
   public Set<RuleRepository> getRuleRepositoriesByLanguage(String languageKey) {
-    return getContainer().getComponent(RulesConsole.class).getRepositoriesByLanguage(languageKey);
+    return getContainer().getComponentByType(RulesConsole.class).getRepositoriesByLanguage(languageKey);
   }
 
   public String backupProfile(int profileId) {
-    return getContainer().getComponent(ProfilesConsole.class).backupProfile(profileId);
+    return getContainer().getComponentByType(ProfilesConsole.class).backupProfile(profileId);
   }
 
   public ValidationMessages restoreProfile(String xmlBackup) {
-    return getContainer().getComponent(ProfilesConsole.class).restoreProfile(xmlBackup);
+    return getContainer().getComponentByType(ProfilesConsole.class).restoreProfile(xmlBackup);
   }
 
   public List<ProfileExporter> getProfileExportersForLanguage(String language) {
-    return getContainer().getComponent(ProfilesConsole.class).getProfileExportersForLanguage(language);
+    return getContainer().getComponentByType(ProfilesConsole.class).getProfileExportersForLanguage(language);
   }
 
   public List<ProfileImporter> getProfileImportersForLanguage(String language) {
-    return getContainer().getComponent(ProfilesConsole.class).getProfileImportersForLanguage(language);
+    return getContainer().getComponentByType(ProfilesConsole.class).getProfileImportersForLanguage(language);
   }
 
   public String exportProfile(int profileId, String exporterKey) {
-    return getContainer().getComponent(ProfilesConsole.class).exportProfile(profileId, exporterKey);
+    return getContainer().getComponentByType(ProfilesConsole.class).exportProfile(profileId, exporterKey);
   }
 
   public ValidationMessages importProfile(String profileName, String language, String importerKey, String fileContent) {
-    return getContainer().getComponent(ProfilesConsole.class).importProfile(profileName, language, importerKey, fileContent);
+    return getContainer().getComponentByType(ProfilesConsole.class).importProfile(profileName, language, importerKey, fileContent);
   }
 
   public String getProfileExporterMimeType(String exporterKey) {
-    return getContainer().getComponent(ProfilesConsole.class).getProfileExporter(exporterKey).getMimeType();
+    return getContainer().getComponentByType(ProfilesConsole.class).getProfileExporter(exporterKey).getMimeType();
   }
 
   public void renameProfile(int profileId, String newProfileName) {
@@ -256,36 +256,40 @@ public final class JRubyFacade {
   }
 
   public List<Footer> getWebFooters() {
-    return getContainer().getComponents(Footer.class);
+    return getContainer().getComponentsByType(Footer.class);
   }
 
   public Backup getBackup() {
-    return getContainer().getComponent(Backup.class);
+    return getContainer().getComponentByType(Backup.class);
   }
 
   private ProfilesManager getProfilesManager() {
-    return getContainer().getComponent(ProfilesManager.class);
+    return getContainer().getComponentByType(ProfilesManager.class);
   }
 
   public void reloadConfiguration() {
-    getContainer().getComponent(CoreConfiguration.class).reload();
+    getContainer().getComponentByType(ServerSettings.class).load();
+  }
+
+  public Settings getSettings() {
+    return getContainer().getComponentByType(Settings.class);
   }
 
   public String getConfigurationValue(String key) {
-    return getContainer().getComponent(Configuration.class).getString(key, null);
+    return getContainer().getComponentByType(Configuration.class).getString(key, null);
   }
 
   public List<InetAddress> getValidInetAddressesForServerId() {
-    return getContainer().getComponent(ServerIdGenerator.class).getAvailableAddresses();
+    return getContainer().getComponentByType(ServerIdGenerator.class).getAvailableAddresses();
   }
 
   public String generateServerId(String organisation, String ipAddress) {
-    return getContainer().getComponent(ServerIdGenerator.class).generate(organisation, ipAddress);
+    return getContainer().getComponentByType(ServerIdGenerator.class).generate(organisation, ipAddress);
   }
 
   public Connection getConnection() {
     try {
-      return getContainer().getComponent(DatabaseConnector.class).getConnection();
+      return getContainer().getComponentByType(DatabaseConnector.class).getConnection();
     } catch (Exception e) {
       /* activerecord does not correctly manage exceptions when connection can not be opened. */
       return null;
@@ -299,7 +303,7 @@ public final class JRubyFacade {
 
     try {
       Class aClass = Class.forName(className);
-      return getContainer().getComponent(aClass);
+      return getContainer().getComponentByType(aClass);
 
     } catch (ClassNotFoundException e) {
       LoggerFactory.getLogger(getClass()).error("Component not found: " + className, e);
@@ -309,61 +313,61 @@ public final class JRubyFacade {
 
   public Object getComponentByClassname(String pluginKey, String className) {
     Object component = null;
-    PicoContainer container = getContainer();
-    Class componentClass = container.getComponent(DefaultServerPluginRepository.class).getClass(pluginKey, className);
+    ComponentContainer container = getContainer();
+    Class componentClass = container.getComponentByType(DefaultServerPluginRepository.class).getClass(pluginKey, className);
     if (componentClass != null) {
-      component = container.getComponent(componentClass);
+      component = container.getComponentByType(componentClass);
     }
     return component;
   }
 
   public String getMessage(String rubyLocale, String key, String defaultValue, Object... parameters) {
     if (i18n == null) {
-      i18n = getContainer().getComponent(JRubyI18n.class);
+      i18n = getContainer().getComponentByType(JRubyI18n.class);
     }
     return i18n.message(rubyLocale, key, defaultValue, parameters);
   }
 
   public String getRuleName(String rubyLocale, String repositoryKey, String key) {
     if (i18n == null) {
-      i18n = getContainer().getComponent(JRubyI18n.class);
+      i18n = getContainer().getComponentByType(JRubyI18n.class);
     }
     return i18n.getRuleName(rubyLocale, repositoryKey, key);
   }
 
   public String getRuleDescription(String rubyLocale, String repositoryKey, String key) {
     if (i18n == null) {
-      i18n = getContainer().getComponent(JRubyI18n.class);
+      i18n = getContainer().getComponentByType(JRubyI18n.class);
     }
     return i18n.getRuleDescription(rubyLocale, repositoryKey, key);
   }
 
   public String getRuleParamDescription(String rubyLocale, String repositoryKey, String key, String paramKey) {
     if (i18n == null) {
-      i18n = getContainer().getComponent(JRubyI18n.class);
+      i18n = getContainer().getComponentByType(JRubyI18n.class);
     }
     return i18n.getRuleParamDescription(rubyLocale, repositoryKey, key, paramKey);
   }
 
   public List<RuleI18nManager.RuleKey> searchRuleName(String rubyLocale, String searchText) {
     if (i18n == null) {
-      i18n = getContainer().getComponent(JRubyI18n.class);
+      i18n = getContainer().getComponentByType(JRubyI18n.class);
     }
     return i18n.searchRuleName(rubyLocale, searchText);
   }
 
   public String getJsL10nDictionnary(String rubyLocale) {
     if (i18n == null) {
-      i18n = getContainer().getComponent(JRubyI18n.class);
+      i18n = getContainer().getComponentByType(JRubyI18n.class);
     }
     return i18n.getJsDictionnary(rubyLocale);
   }
 
   public ReviewsNotificationManager getReviewsNotificationManager() {
-    return getContainer().getComponent(ReviewsNotificationManager.class);
+    return getContainer().getComponentByType(ReviewsNotificationManager.class);
   }
 
-  public PicoContainer getContainer() {
+  public ComponentContainer getContainer() {
     return Platform.getInstance().getContainer();
   }
 }
diff --git a/sonar-server/src/main/resources/sonar-war.properties b/sonar-server/src/main/resources/sonar-war.properties
new file mode 100644 (file)
index 0000000..f078733
--- /dev/null
@@ -0,0 +1,9 @@
+# This file is used only when deploying the webapp to an application server.
+# It is ignored when using the standalone mode shipped by default.
+
+# The path to the Sonar home directory must be defined :
+# - by setting the environment variable SONAR_HOME in the app server
+# - or by setting the system property sonar.home in the app server
+# - or by uncommenting and setting the following property before deploying the webapp
+
+#sonar.home=
\ No newline at end of file
index c9097ef560d6dddf1aa7f2f87e88c0f74bd5bdb3..f62514c0a9ec288cf2a8a220a0c3facea72f92de 100644 (file)
@@ -121,15 +121,12 @@ class ProjectController < ApplicationController
 
     @category=params[:category] ||= 'general'
     @properties_per_category={}
-    java_facade.getPluginsMetadata().each do |plugin|
-      properties=java_facade.getPluginProperties(plugin).select { |property|
-        (@project.module? && property.module()) || (@project.project? && property.project())
-      }
-      properties.each do |property|
-        category = (property.category().present? ? property.category() : plugin.name())
-        @properties_per_category[category]||=[]
-        @properties_per_category[category]<<property
-      end
+    definitions = java_facade.getPropertyDefinitions()
+    properties = definitions.getProperties().select {|property| (@project.module? && property.module()) || (@project.project? && property.project())}
+    properties.each do |property|
+      category = definitions.getCategory(property.key())
+      @properties_per_category[category]||=[]
+      @properties_per_category[category]<<property
     end
   end
 
index d3d27285c9ed66ff90da04a5bd16f3ba49e7b558..76a404306d6479f4282bf3fc24f64305951244aa 100644 (file)
@@ -75,13 +75,13 @@ class SettingsController < ApplicationController
   def load_properties(all=true)
     @category=params[:category]
     @properties_per_category={}
-    java_facade.getPluginsMetadata().each do |plugin|
-      java_facade.getPluginProperties(plugin).select { |property| all || property.global }.each do |property|
-        category = (property.category().present? ? property.category() : plugin.name())
-        @properties_per_category[category]||=[]
-        @properties_per_category[category]<<property
-      end
+    definitions = java_facade.getPropertyDefinitions()
+    definitions.getProperties().select {|property| property.global}.each do |property|
+      category = definitions.getCategory(property.key())
+      @properties_per_category[category]||=[]
+      @properties_per_category[category]<<property
     end
+
     SPECIAL_CATEGORIES.each do |category|
       @properties_per_category[category]=[]
     end
index e74eb71b56d8cf042f1231613ea075059ba3d78e..c6deb1c0f867cb3f3838d7939ecc30a93cac7d2e 100644 (file)
@@ -137,8 +137,8 @@ class UpdatecenterController < ApplicationController
   end
 
   def updatecenter_activated
-    update_center_activated = java_facade.getConfigurationValue('sonar.updatecenter.activate') || 'true';
-    if update_center_activated!='true'
+    update_center_activated = java_facade.getSettings().getBoolean('sonar.updatecenter.activate')
+    unless update_center_activated
       redirect_to home_url
     end
   end
index d39d7fda380ecda1cccdbe001251489ef50e8bd2..7c54458f96cb4f9dde1ec7ce179b85ed65e77b4b 100644 (file)
@@ -143,7 +143,7 @@ class UsersController < ApplicationController
 
   def prepare_user
     user = User.new(params[:user])
-    default_group_name=java_facade.getConfigurationValue('sonar.defaultGroup') || 'sonar-users';
+    default_group_name=java_facade.getSettings().getString('sonar.defaultGroup')
     default_group=Group.find_by_name(default_group_name)
     user.groups<<default_group if default_group
     user
index 81df96f48951c07f0cf14154dda61cbb0715ab7d..659920e9c2e06d1889b5e581887c052b165ce8f3 100644 (file)
@@ -154,7 +154,7 @@ module ApplicationHelper
   end
 
   def configuration(key, default = nil)
-    prop_value = Java::OrgSonarServerUi::JRubyFacade.getInstance().getContainer().getComponent(Java::OrgApacheCommonsConfiguration::Configuration.java_class).getProperty(key)
+    prop_value = Java::OrgSonarServerUi::JRubyFacade.getInstance().getContainer().getComponentByType(Java::OrgApacheCommonsConfiguration::Configuration.java_class).getProperty(key)
     prop_value.nil? ? default : prop_value
   end
 
index 0e2aaad99bbceb2008b97a670950aecb9029dbbe..0e620caf9b2aa06dd677d32b318898436d210883 100644 (file)
@@ -123,7 +123,7 @@ class Server
   end
   
   def sonar_property(key)
-    Java::OrgSonarServerUi::JRubyFacade.getInstance().getContainer().getComponent(Java::OrgApacheCommonsConfiguration::Configuration.java_class).getProperty(key)
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().getContainer().getComponentByType(Java::OrgApacheCommonsConfiguration::Configuration.java_class).getProperty(key)
   end
   
   def jdbc_metadata
index 8832d05aec2b35aab6a3dbc0ff7c8b331c9c2edf..d60a9f3719fb746c7d450248a2214eaecd7697b5 100644 (file)
@@ -94,8 +94,8 @@
               <li class="<%= 'selected' if request.request_uri.include?('/settings') -%>"><a href="<%= ApplicationController.root_context -%>/settings/index"><%= message('settings.page') -%></a></li>
               <li class="<%= 'selected' if controller.controller_path=='backup' -%>"><a href="<%= ApplicationController.root_context -%>/backup"><%= message('backup.page') -%></a></li>
               <li class="<%= 'selected' if controller.controller_path=='system' -%>"><a href="<%= ApplicationController.root_context -%>/system"><%= message('system_info.page') -%></a></li>
-              <% update_center_activated = controller.java_facade.getConfigurationValue('sonar.updatecenter.activate') || 'true';
-              if update_center_activated=='true' %>
+              <% update_center_activated = controller.java_facade.getSettings().getBoolean('sonar.updatecenter.activate')
+              if update_center_activated %>
                 <li class="<%= 'selected' if controller.controller_path=='updatecenter' -%>"><a href="<%= ApplicationController.root_context -%>/updatecenter"><%= message('update_center.page') -%></a></li>
               <% end %>
             <% end %>
index b4f518ec9c45b83b30d54f7b66774751228514f7..03d54ac198a320f0bb6535887ea8f253160e6412 100644 (file)
@@ -119,8 +119,10 @@ class DatabaseVersion
   end
 
   def self.use_structure_dump?
-    # default value is true
-    ::Java::OrgSonarServerUi::JRubyFacade.getInstance().getConfigurationValue('sonar.useStructureDump')!='false'
+    # Important : default value is not loaded at this time by org.sonar.api.config.PropertyDefinitions.
+    # That's why the Settings component does not return the default value (true) when
+    # the property is not set.
+    ::Java::OrgSonarServerUi::JRubyFacade.getInstance().getSettings().getString('sonar.useStructureDump')!='false'
   end
 
   def self.production?
index 8df6024d53fcc63416051af74cfc6932f5decfc2..52ccec511e0c17c0b53ca2623b35f82651617d12 100644 (file)
@@ -92,8 +92,8 @@ module NeedAuthentication
 
         # Downcase login (typically for Active Directory)
         # Note that login in Sonar DB is case-sensitive, however in this case authentication and automatic user creation will always happen with downcase login
-        downcase = java_facade.getConfigurationValue('sonar.authenticator.downcase')
-        if downcase == 'true'
+        downcase = java_facade.getSettings().getBoolean('sonar.authenticator.downcase')
+        if downcase
           login = login.downcase
         end
 
@@ -101,12 +101,12 @@ module NeedAuthentication
         user = User.find_by_login(login)
 
         # Automatically create a user in the sonar db if authentication has been successfully done
-        create_user = java_facade.getConfigurationValue('sonar.authenticator.createUsers')
-        if !user && create_user=='true'
+        create_user = java_facade.getSettings().getBoolean('sonar.authenticator.createUsers')
+        if !user && create_user
           user=User.new(:login => login, :name => login, :email => '', :password => password, :password_confirmation => password)
           user.save!
 
-          default_group_name = java_facade.getConfigurationValue('sonar.defaultGroup') || 'sonar-users'
+          default_group_name = java_facade.getSettings().getString('sonar.defaultGroup')
           default_group=Group.find_by_name(default_group_name)
           if default_group
             user.groups<<default_group
diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/ConfigurationFactoryTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/ConfigurationFactoryTest.java
deleted file mode 100644 (file)
index 4c7e2aa..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.server.configuration;
-
-import org.apache.commons.configuration.Configuration;
-import org.junit.Test;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-
-public class ConfigurationFactoryTest {
-
-  @Test
-  public void checkExistentFile() {
-    Configuration configuration = new ConfigurationFactory().getConfigurationFromPropertiesFile("/org/sonar/server/configuration/ConfigurationFactoryTest/checkExistentFile.properties");
-    assertNotNull(configuration);
-    assertThat(configuration.getString("this"), is("is a test"));
-  }
-
-  @Test(expected = ConfigurationException.class)
-  public void failsWhenFileNotFound() {
-    new ConfigurationFactory().getConfigurationFromPropertiesFile("unknown.properties");
-  }
-
-  @Test
-  public void shouldReadEnvironmentVariables() {
-    Configuration configuration = new ConfigurationFactory().getConfigurationFromPropertiesFile("/org/sonar/server/configuration/ConfigurationFactoryTest/shouldReadEnvironmentVariables.properties");
-    assertNotNull(configuration);
-    assertThat(configuration.getString("my.param.one"), is("foo"));
-    assertThat(configuration.getString("my.param.two"), is(System.getenv("PATH")));
-  }
-
-}
index a75dd1fca4085987637d9d96dc4994d1fd83e3b5..8f995e3bfea46dba120b669e1d6ab4ad5d80e0d7 100644 (file)
  */
 package org.sonar.server.database;
 
-import org.apache.commons.configuration.CompositeConfiguration;
 import org.apache.commons.io.FileUtils;
 import org.apache.derby.jdbc.ClientDriver;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.config.Settings;
 
 import java.io.File;
 import java.io.IOException;
@@ -52,7 +52,7 @@ public class EmbeddedDatabaseTest {
     if (testPort == null) {
       testPort = Integer.toString(findFreeServerPort());
     }
-    defaultProps = EmbeddedDatabase.getDefaultProperties(new CompositeConfiguration());
+    defaultProps = EmbeddedDatabase.getDefaultProperties(new Settings());
     defaultProps.put("derby.drda.portNumber", testPort); // changing the defaut port
     driverUrl = "jdbc:derby://localhost:" + testPort + "/sonar;create=true;user=sonar;password=sonar";
   }
index e3874c385af635fc3bca8b57f307e6ebefb13864..aa2e30497a7a761b8ff3a1d6718f7242f0bd6434 100644 (file)
@@ -24,8 +24,10 @@ import org.apache.commons.configuration.PropertiesConfiguration;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.config.Settings;
 import org.sonar.api.database.DatabaseProperties;
 import org.sonar.jpa.entity.SchemaMigration;
+import org.sonar.server.configuration.ServerSettings;
 
 import javax.naming.Context;
 import javax.persistence.EntityManagerFactory;
@@ -41,7 +43,7 @@ public class JndiDatabaseConnectorTest {
 
   @Before
   public void setup() {
-    Configuration conf = new PropertiesConfiguration();
+    Settings conf = new Settings();
     conf.setProperty(DatabaseProperties.PROP_DIALECT, DatabaseProperties.DIALECT_HSQLDB);
     conf.setProperty(DatabaseProperties.PROP_URL, "jdbc:hsqldb:mem:sonar");
     conf.setProperty(DatabaseProperties.PROP_DRIVER, "org.hsqldb.jdbcDriver");
@@ -69,7 +71,7 @@ public class JndiDatabaseConnectorTest {
     assertEquals(2, emfCreationCounter);
   }
 
-  private JndiDatabaseConnector getTestJndiConnector(Configuration conf) {
+  private JndiDatabaseConnector getTestJndiConnector(Settings conf) {
     JndiDatabaseConnector connector = new JndiDatabaseConnector(conf) {
       @Override
       protected int loadVersion() {
index c75a702b3cf9f4d98c7999fab309aff42a9afc17..38a089538ca59a8a967553fb43b6f1560ac6cbd7 100644 (file)
  */
 package org.sonar.server.notifications;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import org.apache.commons.configuration.BaseConfiguration;
-import org.apache.commons.configuration.Configuration;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.notifications.NotificationChannel;
 import org.sonar.api.notifications.NotificationDispatcher;
 import org.sonar.core.notifications.DefaultNotificationManager;
 import org.sonar.jpa.entity.NotificationQueueElement;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
 public class NotificationServiceTest {
 
   private static String USER_SIMON = "simon";
@@ -51,9 +42,7 @@ public class NotificationServiceTest {
   private NotificationChannel emailChannel;
   private NotificationChannel gtalkChannel;
 
-  private NotificationDispatcher commentOnReviewAssignedToMe;
   private String assignee;
-  private NotificationDispatcher commentOnReviewCreatedByMe;
   private String creator;
 
   private DefaultNotificationManager manager;
@@ -67,7 +56,7 @@ public class NotificationServiceTest {
     gtalkChannel = mock(NotificationChannel.class);
     when(gtalkChannel.getKey()).thenReturn("gtalk");
 
-    commentOnReviewAssignedToMe = mock(NotificationDispatcher.class);
+    NotificationDispatcher commentOnReviewAssignedToMe = mock(NotificationDispatcher.class);
     when(commentOnReviewAssignedToMe.getKey()).thenReturn("comment on review assigned to me");
     doAnswer(new Answer<Object>() {
       public Object answer(InvocationOnMock invocation) throws Throwable {
@@ -76,7 +65,7 @@ public class NotificationServiceTest {
       }
     }).when(commentOnReviewAssignedToMe).dispatch(any(Notification.class), any(NotificationDispatcher.Context.class));
 
-    commentOnReviewCreatedByMe = mock(NotificationDispatcher.class);
+    NotificationDispatcher commentOnReviewCreatedByMe = mock(NotificationDispatcher.class);
     when(commentOnReviewCreatedByMe.getKey()).thenReturn("comment on review created by me");
     doAnswer(new Answer<Object>() {
       public Object answer(InvocationOnMock invocation) throws Throwable {
@@ -85,12 +74,12 @@ public class NotificationServiceTest {
       }
     }).when(commentOnReviewCreatedByMe).dispatch(any(Notification.class), any(NotificationDispatcher.Context.class));
 
-    NotificationDispatcher[] dispatchers = new NotificationDispatcher[] { commentOnReviewAssignedToMe, commentOnReviewCreatedByMe };
+    NotificationDispatcher[] dispatchers = new NotificationDispatcher[] {commentOnReviewAssignedToMe, commentOnReviewCreatedByMe};
     NotificationChannel[] channels = new NotificationChannel[] { emailChannel, gtalkChannel };
     manager = mock(DefaultNotificationManager.class);
-    Configuration configuration = new BaseConfiguration();
-    configuration.setProperty("sonar.notifications.delay", "1"); // delay 1 second
-    service = spy(new NotificationService(configuration, manager, dispatchers, channels));
+    Settings settings = new Settings(new PropertyDefinitions(NotificationService.class));
+    settings.setProperty("sonar.notifications.delay", 1L); // delay 1 second
+    service = spy(new NotificationService(settings, manager, dispatchers, channels));
     doReturn(false).when(manager).isEnabled(any(String.class), any(String.class), any(String.class));
   }
 
index afe742b18874896c40ebeac07bc2a9fb5e4387cf..f9cfcc862fc8bd85c707dff586debb4973086d1d 100644 (file)
@@ -23,10 +23,11 @@ import org.apache.commons.io.FileUtils;
 import org.hamcrest.core.Is;
 import org.junit.After;
 import org.junit.Test;
-import org.picocontainer.containers.TransientPicoContainer;
-import org.sonar.api.*;
+import org.sonar.api.BatchExtension;
+import org.sonar.api.ExtensionProvider;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.SonarPlugin;
 import org.sonar.api.platform.PluginMetadata;
-import org.sonar.batch.Batch;
 import org.sonar.core.plugins.DefaultPluginMetadata;
 
 import java.io.File;
@@ -34,7 +35,6 @@ import java.util.Arrays;
 import java.util.List;
 
 import static junit.framework.Assert.assertFalse;
-import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.core.IsNot.not;
 import static org.junit.Assert.assertThat;
@@ -74,41 +74,6 @@ public class DefaultServerPluginRepositoryTest {
     assertThat(repository.getClass("other", "org.sonar.plugins.artifactsize.ArtifactSizeMetrics"), nullValue());
   }
 
-  @Test
-  public void shouldRegisterServerExtensions() {
-    DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class));
-
-    TransientPicoContainer container = new TransientPicoContainer();
-    repository.registerExtensions(container, Arrays.<Plugin>asList(new FakePlugin(Arrays.<Class>asList(FakeBatchExtension.class, FakeServerExtension.class))));
-
-    assertThat(container.getComponents(Extension.class).size(), is(1));
-    assertThat(container.getComponents(FakeServerExtension.class).size(), is(1));
-    assertThat(container.getComponents(FakeBatchExtension.class).size(), is(0));
-  }
-
-  @Test
-  public void shouldInvokeServerExtensionProviders() {
-    DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class));
-
-    TransientPicoContainer container = new TransientPicoContainer();
-    repository.registerExtensions(container, Arrays.<Plugin>asList(new FakePlugin(Arrays.<Class>asList(FakeExtensionProvider.class))));
-
-    assertThat(container.getComponents(Extension.class).size(), is(2));// provider + FakeServerExtension
-    assertThat(container.getComponents(FakeServerExtension.class).size(), is(1));
-    assertThat(container.getComponents(FakeBatchExtension.class).size(), is(0));
-  }
-
-  @Test
-  public void shouldNotSupportProvidersOfProviders() {
-    DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class));
-
-    TransientPicoContainer container = new TransientPicoContainer();
-    repository.registerExtensions(container, Arrays.<Plugin>asList(new FakePlugin(Arrays.<Class>asList(SuperExtensionProvider.class))));
-
-    assertThat(container.getComponents(FakeBatchExtension.class).size(), is(0));
-    assertThat(container.getComponents(FakeServerExtension.class).size(), is(0));
-  }
-
   @Test
   public void shouldDisablePlugin() {
     DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class));
diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/ServerExtensionInstallerTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/ServerExtensionInstallerTest.java
new file mode 100644 (file)
index 0000000..f584a73
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.server.plugins;
+
+import org.junit.Test;
+import org.sonar.api.BatchExtension;
+import org.sonar.api.ExtensionProvider;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.SonarPlugin;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ServerExtensionInstallerTest {
+  @Test
+  public void shouldRegisterServerExtensions() {
+//    ExtensionRegistrar repository = new ExtensionRegistrar(mock(PluginRepository.class));
+//
+//    ComponentContainer container = new ComponentContainer();
+//    repository.registerExtensions(container, Arrays.<Plugin>asList(new FakePlugin(Arrays.<Class>asList(FakeBatchExtension.class, FakeServerExtension.class))));
+//
+//    assertThat(container.getComponentsByType(Extension.class).size(), is(1));
+//    assertThat(container.getComponentsByType(FakeServerExtension.class).size(), is(1));
+//    assertThat(container.getComponentsByType(FakeBatchExtension.class).size(), is(0));
+  }
+
+  @Test
+  public void shouldInvokeServerExtensionProviders() {
+//    DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class));
+//
+//    ComponentContainer container = new ComponentContainer();
+//    repository.registerExtensions(container, Arrays.<Plugin>asList(new FakePlugin(Arrays.<Class>asList(FakeExtensionProvider.class))));
+//
+//    assertThat(container.getComponentsByType(Extension.class).size(), is(2));// provider + FakeServerExtension
+//    assertThat(container.getComponentsByType(FakeServerExtension.class).size(), is(1));
+//    assertThat(container.getComponentsByType(FakeBatchExtension.class).size(), is(0));
+  }
+
+  @Test
+  public void shouldNotSupportProvidersOfProviders() {
+//    DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class));
+//
+//    ComponentContainer container = new ComponentContainer();
+//    repository.registerExtensions(container, Arrays.<Plugin>asList(new FakePlugin(Arrays.<Class>asList(SuperExtensionProvider.class))));
+//
+//    assertThat(container.getComponentsByType(FakeBatchExtension.class).size(), is(0));
+//    assertThat(container.getComponentsByType(FakeServerExtension.class).size(), is(0));
+  }
+
+  public static class FakePlugin extends SonarPlugin {
+    private List<Class> extensions;
+
+    public FakePlugin(List<Class> extensions) {
+      this.extensions = extensions;
+    }
+
+    public List getExtensions() {
+      return extensions;
+    }
+  }
+
+  public static class FakeBatchExtension implements BatchExtension {
+
+  }
+
+  public static class FakeServerExtension implements ServerExtension {
+
+  }
+
+  public static class FakeExtensionProvider extends ExtensionProvider implements ServerExtension {
+
+    @Override
+    public Object provide() {
+      return Arrays.asList(FakeBatchExtension.class, FakeServerExtension.class);
+    }
+  }
+
+  public static class SuperExtensionProvider extends ExtensionProvider implements ServerExtension {
+
+    @Override
+    public Object provide() {
+      return FakeExtensionProvider.class;
+    }
+  }
+}
index 81fc553cdfb1f578f78a19eb7e897c18967b1d6b..0943141b0f49a6eae3db572476d9eb15aff11323 100644 (file)
@@ -19,9 +19,9 @@
  */
 package org.sonar.server.ui;
 
-import org.apache.commons.configuration.PropertiesConfiguration;
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 import org.sonar.api.security.LoginPasswordAuthenticator;
 
 import static org.hamcrest.Matchers.is;
@@ -33,48 +33,48 @@ public class AuthenticatorFactoryTest {
 
   @Test
   public void doNotFailIfNoAuthenticationPlugins() {
-    AuthenticatorFactory factory = new AuthenticatorFactory(new PropertiesConfiguration());
+    AuthenticatorFactory factory = new AuthenticatorFactory(new Settings());
     assertThat(factory.getAuthenticator(), nullValue());
   }
 
   @Test
   public void startSelectedAuthenticator() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
-    configuration.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName());
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName());
 
     LoginPasswordAuthenticator authenticator = new FakeAuthenticator();
-    AuthenticatorFactory factory = new AuthenticatorFactory(configuration, new LoginPasswordAuthenticator[]{authenticator});
+    AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{authenticator});
     factory.start();
     assertThat(factory.getAuthenticator(), is(authenticator));
   }
 
   @Test(expected = ConnectionException.class)
   public void authenticatorDoesNotStart() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
-    configuration.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FailAuthenticator.class.getName());
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FailAuthenticator.class.getName());
 
-    AuthenticatorFactory factory = new AuthenticatorFactory(configuration, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
+    AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
     factory.start();
     factory.getAuthenticator();
   }
 
   @Test(expected = AuthenticatorNotFoundException.class)
   public void authenticatorNotFound() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
-    configuration.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "foo");
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "foo");
 
-    AuthenticatorFactory factory = new AuthenticatorFactory(configuration, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
+    AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
     factory.start();
     factory.getAuthenticator();
   }
 
   @Test
   public void ignoreStartupFailure() {
-    PropertiesConfiguration configuration = new PropertiesConfiguration();
-    configuration.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FailAuthenticator.class.getName());
-    configuration.setProperty(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE, Boolean.TRUE.toString());
+    Settings settings = new Settings();
+    settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FailAuthenticator.class.getName());
+    settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE, Boolean.TRUE);
 
-    AuthenticatorFactory factory = new AuthenticatorFactory(configuration, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
+    AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
     factory.start();
     assertThat(factory.getAuthenticator(), not(nullValue()));
   }