*/
package org.sonar.batch;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+
import org.apache.commons.configuration.Configuration;
-import org.picocontainer.Characteristics;
-import org.picocontainer.MutablePicoContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.Plugins;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.HttpDownloader;
-import org.sonar.api.utils.IocContainer;
import org.sonar.api.utils.ServerHttpClient;
import org.sonar.batch.bootstrap.BatchPluginRepository;
import org.sonar.batch.bootstrap.BootstrapClassLoader;
import org.sonar.jpa.session.DriverDatabaseConnector;
import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
-import java.net.URLClassLoader;
-import java.util.Arrays;
-
public class Batch {
private static final Logger LOG = LoggerFactory.getLogger(Batch.class);
}
public void execute() {
- MutablePicoContainer container = null;
+ Module bootstrapComponents = null;
try {
- container = buildPicoContainer();
- container.start();
- analyzeModules(container);
-
+ bootstrapComponents = new BootstrapComponents().init().start();
+ analyzeModules(bootstrapComponents);
} finally {
- if (container != null) {
- container.stop();
+ if (bootstrapComponents != null) {
+ bootstrapComponents.stop();
}
}
}
- private void analyzeModules(MutablePicoContainer container) {
- // a child container is built to ensure database connector is up
- MutablePicoContainer batchContainer = container.makeChildContainer();
- batchContainer.as(Characteristics.CACHE).addComponent(ProjectTree.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultResourceCreationLock.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultIndex.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultPersistenceManager.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DependencyPersister.class);
- batchContainer.as(Characteristics.CACHE).addComponent(EventPersister.class);
- batchContainer.as(Characteristics.CACHE).addComponent(LinkPersister.class);
- batchContainer.as(Characteristics.CACHE).addComponent(MeasurePersister.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultResourcePersister.class);
- batchContainer.as(Characteristics.CACHE).addComponent(SourcePersister.class);
- batchContainer.as(Characteristics.CACHE).addComponent(ViolationPersister.class);
- batchContainer.as(Characteristics.CACHE).addComponent(JpaPluginDao.class);
- batchContainer.as(Characteristics.CACHE).addComponent(BatchPluginRepository.class);
- batchContainer.as(Characteristics.CACHE).addComponent(Plugins.class);
- batchContainer.as(Characteristics.CACHE).addComponent(ServerHttpClient.class);
- batchContainer.as(Characteristics.CACHE).addComponent(MeasuresDao.class);
- batchContainer.as(Characteristics.CACHE).addComponent(CacheRuleFinder.class);
- batchContainer.as(Characteristics.CACHE).addComponent(CacheMetricFinder.class);
- batchContainer.as(Characteristics.CACHE).addComponent(PastSnapshotFinderByDate.class);
- batchContainer.as(Characteristics.CACHE).addComponent(PastSnapshotFinderByDays.class);
- batchContainer.as(Characteristics.CACHE).addComponent(PastSnapshotFinderByPreviousAnalysis.class);
- batchContainer.as(Characteristics.CACHE).addComponent(PastSnapshotFinderByVersion.class);
- batchContainer.as(Characteristics.CACHE).addComponent(PastMeasuresLoader.class);
- batchContainer.as(Characteristics.CACHE).addComponent(PastSnapshotFinder.class);
- batchContainer.start();
-
- ProjectTree projectTree = batchContainer.getComponent(ProjectTree.class);
- DefaultIndex index = batchContainer.getComponent(DefaultIndex.class);
- analyzeModule(batchContainer, index, projectTree.getRootProject());
+ private void analyzeModules(Module bootstrapComponents) {
+ Module batchComponents = bootstrapComponents.installChild(new BatchComponents());
+ batchComponents.start();
+
+ ProjectTree projectTree = batchComponents.getComponent(ProjectTree.class);
+ DefaultIndex index = batchComponents.getComponent(DefaultIndex.class);
+ analyzeModule(batchComponents, index, projectTree.getRootProject());
// batchContainer is stopped by its parent
}
- private MutablePicoContainer buildPicoContainer() {
- MutablePicoContainer container = IocContainer.buildPicoContainer();
-
- register(container, configuration);
- register(container, ServerMetadata.class);// registered here because used by BootstrapClassLoader
- register(container, TempDirectories.class);// registered here because used by BootstrapClassLoader
- register(container, HttpDownloader.class);// registered here because used by BootstrapClassLoader
- register(container, ExtensionDownloader.class);// registered here because used by BootstrapClassLoader
- register(container, BootstrapClassLoader.class);
-
- URLClassLoader bootstrapClassLoader = container.getComponent(BootstrapClassLoader.class).getClassLoader();
- // set as the current context classloader for hibernate, else it does not find the JDBC driver.
- Thread.currentThread().setContextClassLoader(bootstrapClassLoader);
-
- register(container, new DriverDatabaseConnector(configuration, bootstrapClassLoader));
- register(container, ThreadLocalDatabaseSessionFactory.class);
- container.as(Characteristics.CACHE).addAdapter(new DatabaseSessionProvider());
- for (Object component : components) {
- register(container, component);
+ private static class BatchComponents extends Module {
+ @Override
+ protected void configure() {
+ addComponent(ProjectTree.class);
+ addComponent(DefaultResourceCreationLock.class);
+ addComponent(DefaultIndex.class);
+ addComponent(DefaultPersistenceManager.class);
+ addComponent(DependencyPersister.class);
+ addComponent(EventPersister.class);
+ addComponent(LinkPersister.class);
+ addComponent(MeasurePersister.class);
+ addComponent(DefaultResourcePersister.class);
+ addComponent(SourcePersister.class);
+ addComponent(ViolationPersister.class);
+ addComponent(JpaPluginDao.class);
+ addComponent(BatchPluginRepository.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);
}
- if (!isMavenPluginExecutorRegistered()) {
- register(container, FakeMavenPluginExecutor.class);
+ }
+
+ private class BootstrapComponents extends Module {
+ @Override
+ protected void configure() {
+ addComponent(configuration);
+ 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(ExtensionDownloader.class);// registered here because used by BootstrapClassLoader
+ addComponent(BootstrapClassLoader.class);
+
+ URLClassLoader bootstrapClassLoader = getComponent(BootstrapClassLoader.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);
+ addAdapter(new DatabaseSessionProvider());
+ for (Object component : components) {
+ addComponent(component);
+ }
+ if (!isMavenPluginExecutorRegistered()) {
+ addComponent(FakeMavenPluginExecutor.class);
+ }
}
- return container;
}
boolean isMavenPluginExecutorRegistered() {
return false;
}
- private void register(MutablePicoContainer container, Object component) {
- container.as(Characteristics.CACHE).addComponent(component);
- }
-
- private void analyzeModule(MutablePicoContainer container, DefaultIndex index, Project project) {
+ private void analyzeModule(Module batchComponents, DefaultIndex index, Project project) {
for (Project module : project.getModules()) {
- analyzeModule(container, index, module);
+ analyzeModule(batchComponents, index, module);
}
LOG.info("------------- Analyzing {}", project.getName());
LOG.info("Excluded sources : {}", Arrays.toString(exclusionPatterns));
}
- new ProjectBatch(container).execute(index, project);
+ new ProjectBatch(batchComponents).execute(index, project);
}
}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch;
+
+import java.util.List;
+
+import org.picocontainer.Characteristics;
+import org.picocontainer.ComponentAdapter;
+import org.picocontainer.MutablePicoContainer;
+import org.sonar.api.utils.IocContainer;
+
+/**
+ * Module describes group of components - {@link #configure()}.
+ * Several modules can be grouped together - {@link #install(Module)}, {@link #installChild(Module)}.
+ */
+public abstract class Module {
+
+ private MutablePicoContainer container;
+
+ /**
+ * @return this
+ */
+ public final Module init() {
+ this.container = IocContainer.buildPicoContainer();
+ configure();
+ return this;
+ }
+
+ /**
+ * @return this
+ */
+ private final Module init(MutablePicoContainer container) {
+ this.container = container;
+ configure();
+ return this;
+ }
+
+ /**
+ * Installs module into this module.
+ *
+ * @return this
+ */
+ public final Module install(Module module) {
+ module.init(container);
+ return this;
+ }
+
+ /**
+ * Installs module into new scope - see http://picocontainer.org/scopes.html
+ *
+ * @return installed module
+ */
+ public final Module installChild(Module module) {
+ MutablePicoContainer child = container.makeChildContainer();
+ // 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
+ child.addComponent(new IocContainer(child));
+ child.setName(module.toString());
+ module.init(child);
+ return module;
+ }
+
+ public final void uninstallChild(Module module) {
+ container.removeChildContainer(module.container);
+ }
+
+ /**
+ * @return this
+ */
+ public Module start() {
+ container.start();
+ return this;
+ }
+
+ /**
+ * @return this
+ */
+ public Module stop() {
+ container.stop();
+ return this;
+ }
+
+ /**
+ * 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)}.
+ */
+ protected abstract void configure();
+
+ protected final void addComponent(Object component) {
+ container.as(Characteristics.CACHE).addComponent(component);
+ }
+
+ protected final void addComponent(Object componentKey, Object component) {
+ container.as(Characteristics.CACHE).addComponent(componentKey, component);
+ }
+
+ protected final void addAdapter(ComponentAdapter<?> componentAdapter) {
+ container.addAdapter(componentAdapter);
+ }
+
+ protected final <T> T getComponent(Class<T> componentType) {
+ return container.getComponent(componentType);
+ }
+
+ protected final <T> List<T> getComponents(Class<T> componentType) {
+ return container.getComponents(componentType);
+ }
+
+ /**
+ * @TODO should not be used and should be removed
+ */
+ public final MutablePicoContainer getContainer() {
+ return container;
+ }
+
+}
*/
package org.sonar.batch;
-import org.picocontainer.Characteristics;
-import org.picocontainer.MutablePicoContainer;
import org.sonar.api.batch.BatchExtensionDictionnary;
import org.sonar.api.batch.ProjectClasspath;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.*;
import org.sonar.api.rules.DefaultRulesManager;
-import org.sonar.api.utils.IocContainer;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.bootstrap.BatchPluginRepository;
import org.sonar.batch.components.PastViolationsLoader;
public class ProjectBatch {
- private MutablePicoContainer globalContainer;
- private MutablePicoContainer batchContainer;
+ private Module globalComponents;
- public ProjectBatch(MutablePicoContainer container) {
- this.globalContainer = container;
+ public ProjectBatch(Module globalComponents) {
+ this.globalComponents = globalComponents;
}
public void execute(DefaultIndex index, Project project) {
+ Module projectComponents = null;
try {
- startChildContainer(index, project);
- batchContainer.getComponent(Phases.class).execute(project);
+ projectComponents = startChildContainer(index, project);
+
+ projectComponents.getComponent(Phases.class).execute(project);
} finally {
- stop();
+ if (projectComponents != null) {
+ try {
+ globalComponents.uninstallChild(projectComponents);
+ projectComponents.stop();
+ } catch (Exception e) {
+ // do not log
+ }
+ }
}
}
- public void startChildContainer(DefaultIndex index, Project project) {
- batchContainer = globalContainer.makeChildContainer();
-
- batchContainer.as(Characteristics.CACHE).addComponent(project);
- batchContainer.as(Characteristics.CACHE).addComponent(project.getPom());
- batchContainer.as(Characteristics.CACHE).addComponent(ProjectClasspath.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultProjectFileSystem.class);
- batchContainer.as(Characteristics.CACHE).addComponent(project.getConfiguration());
-
- // need to be registered after the Configuration
- batchContainer.getComponent(BatchPluginRepository.class).registerPlugins(batchContainer);
-
- batchContainer.as(Characteristics.CACHE).addComponent(DaoFacade.class);
- batchContainer.as(Characteristics.CACHE).addComponent(RulesDao.class);
-
- // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
- batchContainer.as(Characteristics.CACHE)
- .addComponent(globalContainer.getComponent(DefaultResourcePersister.class).getSnapshot(project));
-
- batchContainer.as(Characteristics.CACHE).addComponent(org.sonar.api.database.daos.MeasuresDao.class);
- batchContainer.as(Characteristics.CACHE).addComponent(ProfilesDao.class);
- batchContainer.as(Characteristics.CACHE).addComponent(AsyncMeasuresDao.class);
- batchContainer.as(Characteristics.CACHE).addComponent(AsyncMeasuresService.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultRulesManager.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultSensorContext.class);
- batchContainer.as(Characteristics.CACHE).addComponent(Languages.class);
- batchContainer.as(Characteristics.CACHE).addComponent(BatchExtensionDictionnary.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultTimeMachine.class);
- batchContainer.as(Characteristics.CACHE).addComponent(ViolationFilters.class);
- batchContainer.as(Characteristics.CACHE).addComponent(ResourceFilters.class);
- batchContainer.as(Characteristics.CACHE).addComponent(DefaultModelFinder.class);
- batchContainer.as(Characteristics.CACHE).addComponent(TimeMachineConfiguration.class);
- batchContainer.as(Characteristics.CACHE).addComponent(PastViolationsLoader.class);
- batchContainer.addAdapter(new ProfileProvider());
- batchContainer.addAdapter(new CheckProfileProvider());
- loadCoreComponents(batchContainer);
- batchContainer.as(Characteristics.CACHE).addComponent(new IocContainer(batchContainer));
- batchContainer.start();
+ public Module startChildContainer(DefaultIndex index, Project project) {
+ Module projectComponents = globalComponents.installChild(new ProjectComponents(project));
+ projectComponents.install(new ProjectCoreComponents());
+ projectComponents.start();
// post-initializations
- prepareProject(project, index);
- }
- private void prepareProject(Project project, DefaultIndex index) {
- Language language = getComponent(Languages.class).get(project.getLanguageKey());
+ Language language = projectComponents.getComponent(Languages.class).get(project.getLanguageKey());
if (language == null) {
throw new SonarException("Language with key '" + project.getLanguageKey() + "' not found");
}
project.setLanguage(language);
index.setCurrentProject(project,
- getComponent(ResourceFilters.class),
- getComponent(ViolationFilters.class),
- getComponent(RulesProfile.class));
+ projectComponents.getComponent(ResourceFilters.class),
+ projectComponents.getComponent(ViolationFilters.class),
+ projectComponents.getComponent(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(projectComponents.getComponent(ProjectFileSystem.class));
+
+ return projectComponents;
}
- private void loadCoreComponents(MutablePicoContainer container) {
- container.as(Characteristics.CACHE).addComponent(Phases.class);
- for (Class clazz : Phases.getPhaseClasses()) {
- container.as(Characteristics.CACHE).addComponent(clazz);
- }
- for (Metric metric : CoreMetrics.getMetrics()) {
- container.as(Characteristics.CACHE).addComponent(metric.getKey(), metric);
+ private static class ProjectComponents extends Module {
+ private Project project;
+
+ public ProjectComponents(Project project) {
+ this.project = project;
}
- for (Metrics metricRepo : container.getComponents(Metrics.class)) {
- for (Metric metric : metricRepo.getMetrics()) {
- container.as(Characteristics.CACHE).addComponent(metric.getKey(), metric);
- }
+
+ @Override
+ protected void configure() {
+ addComponent(project);
+ addComponent(project.getPom());
+ addComponent(ProjectClasspath.class);
+ addComponent(DefaultProjectFileSystem.class);
+ addComponent(project.getConfiguration());
+
+ // need to be registered after the Configuration
+ getComponent(BatchPluginRepository.class).registerPlugins(getContainer());
+
+ addComponent(DaoFacade.class);
+ addComponent(RulesDao.class);
+
+ // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
+ addComponent(getComponent(DefaultResourcePersister.class).getSnapshot(project));
+ // TODO was addComponent(globalComponents.getComponent(DefaultResourcePersister.class).getSnapshot(project));
+
+ addComponent(org.sonar.api.database.daos.MeasuresDao.class);
+ addComponent(ProfilesDao.class);
+ addComponent(AsyncMeasuresDao.class);
+ addComponent(AsyncMeasuresService.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(TimeMachineConfiguration.class);
+ addComponent(PastViolationsLoader.class);
+
+ addAdapter(new ProfileProvider());
+ addAdapter(new CheckProfileProvider());
}
}
- private void stop() {
- if (batchContainer != null) {
- try {
- globalContainer.removeChildContainer(batchContainer);
- batchContainer.stop();
- batchContainer = null;
- } catch (Exception e) {
- // do not log
+ private static class ProjectCoreComponents extends Module {
+ @Override
+ protected void configure() {
+ addComponent(Phases.class);
+ for (Class clazz : Phases.getPhaseClasses()) {
+ addComponent(clazz);
+ }
+ for (Metric metric : CoreMetrics.getMetrics()) {
+ addComponent(metric.getKey(), metric);
+ }
+ for (Metrics metricRepo : getComponents(Metrics.class)) {
+ for (Metric metric : metricRepo.getMetrics()) {
+ addComponent(metric.getKey(), metric);
+ }
}
}
}
- public <T> T getComponent(Class<T> clazz) {
- if (batchContainer != null) {
- return batchContainer.getComponent(clazz);
- }
- return globalContainer.getComponent(clazz);
- }
}