1 package org.apache.stratum.component;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import java.io.IOException;
21 import java.util.List;
22
23 import org.apache.commons.configuration.CompositeConfiguration;
24 import org.apache.commons.configuration.Configuration;
25 import org.apache.commons.configuration.PropertiesConfiguration;
26 import org.apache.log4j.Category;
27 import org.apache.stratum.lifecycle.Configurable;
28 import org.apache.stratum.lifecycle.Initializable;
29
30 /***
31 * Loader for Components implementing the lifecyle Interfaces. NOTE: This class is in its infancy and will more than likely change.
32 *
33 * @author <a href="mailto:eric NOSPAM dobbse.net">Eric Dobbs </a>
34 * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl </a>
35 * @version $Id: ComponentLoader.java 264191 2005-08-29 18:07:52Z henning $
36 */
37 public class ComponentLoader
38 {
39 /*** Log4j category used for logging. NOTE: we should change this to use the commons-logging API. */
40 private static Category log = Category.getInstance(ComponentLoader.class);
41
42 /*** Component tag used in Configurations */
43 private static String COMPONENT = "component";
44
45 /*** Class name tag used in Configurations */
46 private static String CLASSNAME = "classname";
47
48 /*** Extension used for Configuration files. */
49 private static String CONFIG = "config";
50
51 /*** Extension used for Additional properties. */
52 private static String PROPERTY = "property";
53
54 /*** Name tag used in Configurations */
55 private static String NAME = "name";
56
57 /*** Configuration used by this ComponentLoader. */
58 private Configuration configuration;
59
60 /***
61 * Constructor
62 *
63 * @param configuration
64 */
65 public ComponentLoader(Configuration configuration)
66 {
67 this.configuration = configuration;
68 }
69
70 /***
71 * Set the configuration for this ComponentLoader
72 *
73 * @param configuration Configuration
74 */
75 public void setConfiguration(Configuration configuration)
76 {
77 this.configuration = configuration;
78 }
79
80 /***
81 * Support method for testing the constructor
82 *
83 * @return the configuration
84 */
85 public Configuration getConfiguration()
86 {
87 return configuration;
88 }
89
90 /***
91 * <p>
92 * Load all the components listed in the ComponentLoader's configuration. Log any errors, but throw no exceptions if components
93 * cannot be loaded.
94 * </p>
95 * Configuration notes:<br>
96 * Components are identified in the properties file as follows: <br>
97 * <code> component.name=NAME component.NAME.classname = com.mycompany.components.SomeComponent component.NAME.config =
98 * path/to/SomeComponent.properties </code>
99 *
100 * @return an array of loaded components
101 */
102 public Object [] load()
103 {
104 List components = configuration.getList(COMPONENT + '.' + NAME);
105 Object [] loadedComponents = new Object[components.size()];
106
107 String componentName;
108 String componentClassName;
109 String componentConfig;
110 Configuration componentAdditionalConfig;
111
112 for (int i = 0; i < components.size(); i++)
113 {
114 componentName = (String) components.get(i);
115 componentClassName = getComponentClassname(componentName);
116 componentConfig = getComponentConfigFile(componentName);
117 componentAdditionalConfig = getComponentAdditionalConfig(componentName);
118
119 log.info("loading component: name=" + componentName + " class=" + componentClassName + " config=" + componentConfig);
120
121 loadedComponents[i] = loadComponent(componentClassName, componentConfig, componentAdditionalConfig);
122 }
123
124 return loadedComponents;
125 }
126
127 /***
128 * load the given component, configure it with the given config file, and initialize it. <br>
129 * The component must implement the <code>Initializable</code> and <code>Configurable</code> interfaces.
130 *
131 * @param className the String class name of the component to load
132 * @param configFile the String path name of the component's config file
133 * @param additionalConfig TODO: DOCUMENT ME!
134 *
135 * @return the loaded component or null if it failed to load
136 *
137 * @see Initializable
138 * @see Configurable
139 */
140 public Object loadComponent(String className, String configFile, Configuration additionalConfig)
141 {
142 Object component = null;
143
144 if (log.isDebugEnabled())
145 {
146 log.debug("attempting to load '" + className + "' with the config file '" + configFile + "'.");
147 }
148
149 try
150 {
151 component = Class.forName(className).newInstance();
152
153
154 CompositeConfiguration config = new CompositeConfiguration();
155 config.addConfiguration(new PropertiesConfiguration(configFile));
156 config.addConfiguration(additionalConfig);
157 ((Configurable) component).configure(config);
158
159
160 ((Initializable) component).initialize();
161
162 if (log.isDebugEnabled())
163 {
164 log.debug("good news! " + className + " successfully configured and initialized");
165 }
166 }
167 catch (IOException ioe)
168 {
169 log.error(className + " could not be configured with file '" + configFile + "'.", ioe);
170 }
171 catch (Exception e)
172 {
173 log.error(className + " could not be initialized!", e);
174 }
175
176 return component;
177 }
178
179 /***
180 * <p>
181 * Get the component's classname as defined in the ComponentLoader configuration.
182 * </p>
183 *
184 * <p>
185 * Example property: <br/> component.NAME.classname=com.mycompany.components.MyComponent
186 * </p>
187 *
188 * @param name the String NAME of the component in the classfile
189 *
190 * @return the configured classname
191 */
192 private String getComponentClassname(String name)
193 {
194 return configuration.getString(COMPONENT + '.' + name + '.' + CLASSNAME);
195 }
196
197 /***
198 * <p>
199 * Get the component's config file as defined in the ComponentLoader configuration.
200 * </p>
201 *
202 * <p>
203 * Example property: <br/>component.NAME.config=path/to/your/config
204 * </p>
205 *
206 * @param name the String NAME of the component in the classfile
207 *
208 * @return the configured config file
209 */
210 private String getComponentConfigFile(String name)
211 {
212 return configuration.getString(COMPONENT + '.' + name + '.' + CONFIG);
213 }
214
215 /***
216 * <p>
217 * Get any additional configuration properties from the master configuration.
218 * </p>
219 *
220 * <p>
221 * Example property: <br/>
222 * component.NAME.property.key1==value1 <br/>
223 * component.NAME.property.key2==value2 <br/>
224 * component.NAME.property.key3==value3 <br/>
225 * </p>
226 *
227 * @param name the String NAME of the component in the classfile
228 *
229 * @return the extra properties as a Configuration object
230 */
231 private Configuration getComponentAdditionalConfig(String name)
232 {
233 return configuration.subset(COMPONENT + '.' + name + '.' + PROPERTY);
234 }
235 }