View Javadoc

1   package org.apache.stratum.component;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation or its licensors,
5    * as applicable.
6    *
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
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             // configure component using the given config file
154             CompositeConfiguration config = new CompositeConfiguration();
155             config.addConfiguration(new PropertiesConfiguration(configFile));
156             config.addConfiguration(additionalConfig);
157             ((Configurable) component).configure(config);
158 
159             // initialize component
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 }