001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar 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 * Sonar 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
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019 */
020package org.sonar.batch.bootstrap;
021
022import org.picocontainer.ComponentAdapter;
023import org.sonar.api.platform.ComponentContainer;
024import org.sonar.api.platform.PluginMetadata;
025
026import java.util.List;
027
028/**
029 * Module describes group of components - {@link #configure()}.
030 * Several modules can be grouped together - {@link #install(Module)}, {@link #installChild(Module)}.
031 * <p/>
032 */
033public abstract class Module {
034
035  ComponentContainer container;
036
037  /**
038   * @return this
039   */
040  public final Module init() {
041    return init(new ComponentContainer());
042  }
043
044  /**
045   * @return this
046   */
047  private Module init(ComponentContainer container) {
048    this.container = container;
049    configure();
050    return this;
051  }
052
053  /**
054   * Installs module into this module.
055   *
056   * @return this
057   */
058  public final Module install(Module module) {
059    module.init(container);
060    return this;
061  }
062
063  /**
064   * Installs module into new scope - see http://picocontainer.org/scopes.html
065   *
066   * @return installed module
067   */
068  public final Module installChild(Module child) {
069    ComponentContainer childContainer = container.createChild();
070    child.init(childContainer);
071    return child;
072  }
073
074  public final void uninstallChild() {
075    container.removeChild();
076  }
077
078  /**
079   * @return this
080   */
081  public final Module start() {
082    container.startComponents();
083    doStart();
084    return this;
085  }
086
087  protected void doStart() {
088    // empty method to be overridden
089  }
090
091  /**
092   * @return this
093   */
094  public final Module stop() {
095    try {
096      doStop();
097      container.stopComponents();
098    } catch (Exception e) {
099      // ignore
100    }
101    return this;
102  }
103
104  protected void doStop() {
105    // empty method to be overridden
106  }
107
108  /**
109   * Implementation of this method must not contain conditional logic and just should contain several invocations of
110   * {@link #addCoreSingleton(Object)}, {@link #addExtension(org.sonar.api.platform.PluginMetadata, Object)} or {@link #addAdapter(ComponentAdapter)}.
111   */
112  protected abstract void configure();
113
114  protected final void addCoreSingleton(Object component) {
115    container.addSingleton(component);
116  }
117
118  protected final void declareExtension(PluginMetadata plugin, Object extension) {
119    container.declareExtension(plugin, extension);
120  }
121
122  protected final void addExtension(PluginMetadata plugin, Object extension) {
123    container.addExtension(plugin, extension);
124  }
125
126  protected final void addAdapter(ComponentAdapter<?> componentAdapter) {
127    container.addPicoAdapter(componentAdapter);
128  }
129
130  public final <T> T getComponentByType(Class<T> componentType) {
131    return container.getComponentByType(componentType);
132  }
133
134  public final Object getComponentByKey(Object key) {
135    return container.getComponentByKey(key);
136  }
137
138  public final <T> List<T> getComponents(Class<T> componentType) {
139    return container.getComponentsByType(componentType);
140  }
141}