View Javadoc

1   package org.ocltf.common;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   
6   import org.apache.commons.collections.CollectionUtils;
7   import org.apache.commons.collections.Predicate;
8   import org.apache.commons.lang.StringUtils;
9   import org.apache.commons.logging.Log;
10  import org.apache.commons.logging.LogFactory;
11  import org.ocltf.utils.ClassUtils;
12  import org.ocltf.utils.ExceptionUtils;
13  import org.ocltf.utils.FileResourceUtils;
14  import org.picocontainer.MutablePicoContainer;
15  import org.picocontainer.defaults.DefaultPicoContainer;
16  
17  /***
18   * This handles all registration and retrieval 
19   * of components within the framework.
20   * 
21   * @author Chad Brandon
22   * @version 1.0
23   */
24  public class ComponentContainer {
25      
26      private static Log logger = LogFactory.getLog(ComponentContainer.class);
27      
28      /***
29       * Where all component default implementations are found.
30       */
31      private static final String DEFAULTS_DIR = "META-INF/defaults/";
32  
33      /***
34       * The container instance
35       */
36  	private MutablePicoContainer container;
37      
38      private static final ComponentContainer instance = new ComponentContainer();
39      
40      /***
41       * Constructs an instance of ComponentContainer.
42       */
43      protected ComponentContainer() {
44      	this.container = new DefaultPicoContainer();
45      }
46      
47      /***
48       * Gets the shared instance of this ComponentContainer.
49       * 
50       * @return PluginDiscoverer the static instance.
51       */
52      public static ComponentContainer instance() {
53          return instance;
54      }
55      
56      /***
57       * Finds the component with the specified <code>key</code>.
58       * 
59       * @param key the unique key of the component as an Object.
60       * @return Object the component instance.
61       */
62      public Object findComponent(Object key) {
63      	return this.container.getComponentInstance(key);
64      }
65      
66      /***
67       * Finds the component with the specified <code>key</code>.
68       * 
69       * @param key the unique key as a Class.
70       * @return Object the component instance.
71       */
72      public Object findComponent(Class key) {
73      	final String methodName = "ComponentContainer.findComponent";
74      	ExceptionUtils.checkNull(methodName, "key", key);
75      	return this.container.getComponentInstance(key.getName());
76      }
77      
78      /***
79       * Attempts to find the component with the 
80       * specified unique <code>key</code>, if it can't be found, 
81       * the default of the specified <code>type</code> is
82       * returned, if no default is set, null is returned.
83       * 
84       * @param key the unique key of the component.
85       * @return Object the component instance.
86       */
87      public Object findComponent(String key, Class type) {
88          String methodName = "findComponent";
89          ExceptionUtils.checkNull(methodName, "type", type);
90          try {
91  
92              Object component = this.container.getComponentInstance(key);
93  
94              if (component == null) {
95                  String typeName = type.getName();
96              	component = this.container.getComponentInstance(typeName);
97                  //if the component doesn't have a default already 
98                  //(componet == null), then see if we can find the default 
99                  //configuration file.
100                 if (component == null) {
101                     String defaultImpl = 
102                         StringUtils.trimToEmpty(
103                                 FileResourceUtils.getResourceContentsAsString(
104                                         DEFAULTS_DIR + type.getName()));
105                    
106                     if (StringUtils.isNotEmpty(defaultImpl)) {
107                     	component = this.registerDefaultComponent(
108                             ClassUtils.loadClass(typeName), 
109                     		ClassUtils.loadClass(defaultImpl));
110                     } else {
111                         if (logger.isWarnEnabled()) {
112                             logger.warn("WARNING! No default implementation for '" 
113                                     + type + "' found, check defaults directory --> '" 
114                                     + DEFAULTS_DIR + "'");
115                         }
116                     }
117                 }
118             }
119             return component;
120         } catch (Throwable th) {
121         	String errMsg = "Error performing " + methodName;
122             logger.error(errMsg, th);
123             throw new ComponentContainerException(errMsg, th);
124         }
125     }
126     
127     /***
128      * Finds all components having the given <code>type</code>.
129      * 
130      * @param type the component type.
131      * @return Collection all components
132      */
133     public Collection findComponentsOfType(final Class type) {
134         class ClassMatcher implements Predicate {
135             public boolean evaluate(Object object) {
136                 boolean match = false;
137                 if (object != null) {
138                     match = type.isAssignableFrom(object.getClass());
139                 }
140                 return match;
141             }
142         }
143         Collection components = new ArrayList(this.container.getComponentInstances());
144         CollectionUtils.filter(
145                 components, 
146                 new ClassMatcher());        
147         return components;
148     }
149     
150     /***
151      * Registers the component in this container
152      * with a unique (within this container) <code>key</code>.
153      * 
154      * @param key the unique key.
155      * @return Object the registered component.
156      */
157     public Object registerComponent(String key, Object component) {
158         String methodName = "registerComponent";
159         ExceptionUtils.checkNull(methodName, "component", component);
160         if (logger.isDebugEnabled()) {
161         	logger.debug("registering component '" 
162                 + component + "' with key --> '" + key + "'");
163         }
164         return container.registerComponentInstance(
165             key, component).getComponentInstance();
166     }
167     
168     /***
169      * Registers the "default" for the specified componentInterface.
170      * 
171      * @param componentInterface the interface for the component.
172      * @param defaultType the "default" implementation to use for the
173      *        componentInterface.
174      * @return Object the registered component.
175      */
176     public Object registerDefaultComponent(Class componentInterface, Class defaultType) {
177         String methodName = "registerDefaultComponent";
178         ExceptionUtils.checkNull(
179             methodName, 
180             "componentInterface", 
181             componentInterface);
182         ExceptionUtils.checkNull(
183             methodName, 
184             "defaultType", 
185             defaultType);
186         if (logger.isDebugEnabled()) {
187             logger.debug("registering default for component '" 
188                     + componentInterface  + "' as type --> '" + defaultType + "'");
189         }
190         try {
191             return container.registerComponentInstance(
192                 componentInterface.getName(),
193                 defaultType.newInstance()).getComponentInstance();
194         } catch (Throwable th) {
195         	String errMsg = "Error performing " + methodName;
196             logger.error(errMsg);
197             throw new ComponentContainerException(errMsg, th);
198         }
199     }
200     
201     /***
202      * Registers the component of the specified <code>type</code>.
203      * 
204      * @param type the type Class.
205      * @return Object an instance of the type registered.
206      */
207     public Object registerComponentType(Class type) {
208         String methodName = "registerComponent";
209         ExceptionUtils.checkNull(methodName, "type", type);
210         return this.container.registerComponentImplementation(
211             type).getComponentInstance();
212     }
213     
214     /***
215      * Registers the components of the specified 
216      * <code>type</code>.
217      * @param type the name of a type (must have be able
218      *        to be instantiated into a Class instance)
219      * @return Object an instance of the type registered.
220      */
221     public Object registerComponentType(String type) {
222         String methodName = "registerComponent";
223         ExceptionUtils.checkNull(methodName, "type", type);
224         try {
225             Object component = ClassUtils.loadClass(type).newInstance();
226         	return this.registerComponent(type, component);
227         } catch (Throwable th) {
228         	String errMsg = "Error performing "
229                 + methodName;
230         	logger.error(errMsg, th);
231             throw new ComponentContainerException(errMsg, th);
232         }
233     }
234     
235 }