001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * SonarQube is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.batch.bootstrap;
021    
022    import org.apache.commons.configuration.PropertiesConfiguration;
023    import org.sonar.api.CoreProperties;
024    import org.sonar.api.Plugin;
025    import org.sonar.api.config.EmailSettings;
026    import org.sonar.api.platform.ComponentContainer;
027    import org.sonar.api.platform.PluginMetadata;
028    import org.sonar.api.utils.Durations;
029    import org.sonar.api.utils.HttpDownloader;
030    import org.sonar.api.utils.System2;
031    import org.sonar.api.utils.UriReader;
032    import org.sonar.api.utils.internal.TempFolderCleaner;
033    import org.sonar.batch.components.PastSnapshotFinder;
034    import org.sonar.batch.components.PastSnapshotFinderByDate;
035    import org.sonar.batch.components.PastSnapshotFinderByDays;
036    import org.sonar.batch.components.PastSnapshotFinderByPreviousAnalysis;
037    import org.sonar.batch.components.PastSnapshotFinderByPreviousVersion;
038    import org.sonar.batch.components.PastSnapshotFinderByVersion;
039    import org.sonar.batch.referential.DefaultGlobalReferentialsLoader;
040    import org.sonar.batch.referential.DefaultProjectReferentialsLoader;
041    import org.sonar.batch.referential.GlobalReferentialsLoader;
042    import org.sonar.batch.referential.GlobalReferentialsProvider;
043    import org.sonar.batch.referential.ProjectReferentialsLoader;
044    import org.sonar.core.cluster.NullQueue;
045    import org.sonar.core.config.Logback;
046    import org.sonar.core.i18n.DefaultI18n;
047    import org.sonar.core.i18n.RuleI18nManager;
048    import org.sonar.core.persistence.DaoUtils;
049    import org.sonar.core.persistence.DatabaseVersion;
050    import org.sonar.core.persistence.MyBatis;
051    import org.sonar.core.persistence.SemaphoreUpdater;
052    import org.sonar.core.persistence.SemaphoresImpl;
053    import org.sonar.core.purge.PurgeProfiler;
054    import org.sonar.core.rule.CacheRuleFinder;
055    import org.sonar.core.user.HibernateUserFinder;
056    import org.sonar.jpa.dao.MeasuresDao;
057    import org.sonar.jpa.session.DefaultDatabaseConnector;
058    import org.sonar.jpa.session.JpaDatabaseSession;
059    
060    import java.util.List;
061    import java.util.Map;
062    
063    public class BootstrapContainer extends ComponentContainer {
064    
065      private final Map<String, String> bootstrapProperties;
066      private final boolean sensorMode;
067    
068      private BootstrapContainer(Map<String, String> bootstrapProperties) {
069        super();
070        this.sensorMode = CoreProperties.ANALYSIS_MODE_SENSOR.equals(bootstrapProperties.get(CoreProperties.ANALYSIS_MODE));
071        this.bootstrapProperties = bootstrapProperties;
072      }
073    
074      public static BootstrapContainer create(Map<String, String> bootstrapProperties, List extensions) {
075        BootstrapContainer container = new BootstrapContainer(bootstrapProperties);
076        container.add(extensions);
077        return container;
078      }
079    
080      @Override
081      protected void doBeforeStart() {
082        addBootstrapComponents();
083        if (!sensorMode) {
084          addDatabaseComponents();
085          addCoreComponents();
086        }
087      }
088    
089      private void addBootstrapComponents() {
090        add(
091          new PropertiesConfiguration(),
092          new BootstrapProperties(bootstrapProperties),
093          AnalysisMode.class,
094          BatchPluginRepository.class,
095          BatchPluginJarInstaller.class,
096          GlobalSettings.class,
097          ServerClient.class,
098          ExtensionInstaller.class,
099          Logback.class,
100          ServerMetadata.class,
101          org.sonar.batch.ServerMetadata.class,
102          new TempFolderProvider(),
103          TempFolderCleaner.class,
104          HttpDownloader.class,
105          UriReader.class,
106          new FileCacheProvider(),
107          System2.INSTANCE,
108          new GlobalReferentialsProvider());
109        if (getComponentByType(PluginsReferential.class) == null) {
110          add(DefaultPluginsReferential.class);
111        }
112        if (getComponentByType(GlobalReferentialsLoader.class) == null) {
113          add(DefaultGlobalReferentialsLoader.class);
114        }
115        if (getComponentByType(ProjectReferentialsLoader.class) == null) {
116          add(DefaultProjectReferentialsLoader.class);
117        }
118      }
119    
120      private void addDatabaseComponents() {
121        add(
122          PreviewDatabase.class,
123          JdbcDriverHolder.class,
124          BatchDatabase.class,
125          MyBatis.class,
126          NullQueue.class,
127          DatabaseVersion.class,
128          // TODO check that it still works (see @Freddy)
129          DatabaseCompatibility.class,
130          DefaultDatabaseConnector.class,
131          JpaDatabaseSession.class,
132          BatchDatabaseSessionFactory.class,
133          DaoUtils.getDaoClasses(),
134          PurgeProfiler.class,
135          CacheRuleFinder.class);
136      }
137    
138      /**
139       * These components MUST not depend on extensions provided by plugins
140       */
141      private void addCoreComponents() {
142        add(
143          EmailSettings.class,
144          DefaultI18n.class,
145          RuleI18nManager.class,
146          MeasuresDao.class,
147          HibernateUserFinder.class,
148          SemaphoreUpdater.class,
149          SemaphoresImpl.class,
150          PastSnapshotFinderByDate.class,
151          PastSnapshotFinderByDays.class,
152          PastSnapshotFinderByPreviousAnalysis.class,
153          PastSnapshotFinderByVersion.class,
154          PastSnapshotFinderByPreviousVersion.class,
155          PastSnapshotFinder.class,
156          Durations.class);
157      }
158    
159      @Override
160      protected void doAfterStart() {
161        installPlugins();
162      }
163    
164      private void installPlugins() {
165        for (Map.Entry<PluginMetadata, Plugin> entry : getComponentByType(BatchPluginRepository.class).getPluginsByMetadata().entrySet()) {
166          PluginMetadata metadata = entry.getKey();
167          Plugin plugin = entry.getValue();
168          addExtension(metadata, plugin);
169        }
170      }
171    
172      public void executeTask(Map<String, String> taskProperties, Object... components) {
173        new TaskContainer(this, taskProperties, components).execute();
174      }
175    
176    }