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}