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 */
020 package org.sonar.batch.bootstrap;
021
022 import org.picocontainer.ComponentAdapter;
023 import org.sonar.api.platform.ComponentContainer;
024 import org.sonar.api.platform.PluginMetadata;
025
026 import 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 */
033 public 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 }