001 /*****************************************************************************
002 * Copyright (C) NanoContainer Organization. All rights reserved. *
003 * ------------------------------------------------------------------------- *
004 * The software in this package is published under the terms of the BSD *
005 * style license a copy of which has been included with this distribution in *
006 * the LICENSE.txt file. *
007 * *
008 * Original code by Aslak Hellesoy and Paul Hammant *
009 *****************************************************************************/
010
011 package org.nanocontainer.script.xml;
012
013 import java.io.File;
014 import java.io.IOException;
015 import java.io.Reader;
016 import java.net.MalformedURLException;
017 import java.net.URL;
018 import java.security.Permission;
019 import java.util.ArrayList;
020 import java.util.List;
021
022 import javax.xml.parsers.DocumentBuilder;
023 import javax.xml.parsers.DocumentBuilderFactory;
024 import javax.xml.parsers.ParserConfigurationException;
025
026 import org.nanocontainer.ClassNameKey;
027 import org.nanocontainer.ClassPathElement;
028 import org.nanocontainer.DefaultNanoContainer;
029 import org.nanocontainer.NanoContainer;
030 import org.nanocontainer.reflection.DefaultNanoPicoContainer;
031 import org.nanocontainer.integrationkit.ContainerPopulator;
032 import org.nanocontainer.integrationkit.PicoCompositionException;
033 import org.nanocontainer.script.NanoContainerMarkupException;
034 import org.nanocontainer.script.ScriptedContainerBuilder;
035 import org.picocontainer.ComponentMonitor;
036 import org.picocontainer.MutablePicoContainer;
037 import org.picocontainer.Parameter;
038 import org.picocontainer.PicoContainer;
039 import org.picocontainer.defaults.ComponentAdapterFactory;
040 import org.picocontainer.defaults.ComponentMonitorStrategy;
041 import org.picocontainer.defaults.ComponentParameter;
042 import org.picocontainer.defaults.ConstantParameter;
043 import org.picocontainer.defaults.DefaultComponentAdapterFactory;
044 import org.picocontainer.defaults.DefaultPicoContainer;
045 import org.picocontainer.defaults.DelegatingComponentMonitor;
046 import org.w3c.dom.Element;
047 import org.w3c.dom.NodeList;
048 import org.xml.sax.EntityResolver;
049 import org.xml.sax.InputSource;
050 import org.xml.sax.SAXException;
051
052 /**
053 * This class builds up a hierarchy of PicoContainers from an XML configuration file.
054 *
055 * @author Paul Hammant
056 * @author Aslak Hellesøy
057 * @author Jeppe Cramon
058 * @author Mauro Talevi
059 * @version $Revision: 3397 $
060 */
061 public class XMLContainerBuilder extends ScriptedContainerBuilder implements ContainerPopulator {
062
063 private final static String DEFAULT_COMPONENT_ADAPTER_FACTORY = DefaultComponentAdapterFactory.class.getName();
064 private final static String DEFAULT_COMPONENT_INSTANCE_FACTORY = BeanComponentInstanceFactory.class.getName();
065 private final static String DEFAULT_COMPONENT_MONITOR = DelegatingComponentMonitor.class.getName();
066
067 private final static String CONTAINER = "container";
068 private final static String CLASSPATH = "classpath";
069 private final static String CLASSLOADER = "classloader";
070 private static final String CLASS_NAME_KEY = "class-name-key";
071 private final static String COMPONENT = "component";
072 private final static String COMPONENT_IMPLEMENTATION = "component-implementation";
073 private final static String COMPONENT_INSTANCE = "component-instance";
074 private final static String COMPONENT_ADAPTER = "component-adapter";
075 private final static String COMPONENT_ADAPTER_FACTORY = "component-adapter-factory";
076 private final static String COMPONENT_INSTANCE_FACTORY = "component-instance-factory";
077 private final static String COMPONENT_MONITOR = "component-monitor";
078 private final static String DECORATING_PICOCONTAINER = "decorating-picocontainer";
079 private final static String CLASS = "class";
080 private final static String FACTORY = "factory";
081 private final static String FILE = "file";
082 private final static String KEY = "key";
083 private final static String EMPTY_COLLECTION = "empty-collection";
084 private final static String COMPONENT_VALUE_TYPE = "component-value-type";
085 private final static String COMPONENT_KEY_TYPE = "component-key-type";
086 private final static String PARAMETER = "parameter";
087 private final static String URL = "url";
088
089 private final static String CLASSNAME = "classname";
090 private final static String CONTEXT = "context";
091 private final static String VALUE = "value";
092
093 private static final String EMPTY = "";
094
095 private Element rootElement;
096 /**
097 * The XMLComponentInstanceFactory globally defined for the container.
098 * It may be overridden at node level.
099 */
100 private XMLComponentInstanceFactory componentInstanceFactory;
101
102 public XMLContainerBuilder(Reader script, ClassLoader classLoader) {
103 super(script, classLoader);
104 try {
105 DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
106 parse(documentBuilder, new InputSource(script));
107 } catch (ParserConfigurationException e) {
108 throw new NanoContainerMarkupException(e);
109 }
110 }
111
112 public XMLContainerBuilder(final URL script, ClassLoader classLoader) {
113 super(script, classLoader);
114 try {
115 DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
116 documentBuilder.setEntityResolver(new EntityResolver() {
117 public InputSource resolveEntity(String publicId, String systemId) throws IOException {
118 URL url = new URL(script, systemId);
119 return new InputSource(url.openStream());
120 }
121 });
122 parse(documentBuilder, new InputSource(script.toString()));
123 } catch (ParserConfigurationException e) {
124 throw new NanoContainerMarkupException(e);
125 }
126 }
127
128 private void parse(DocumentBuilder documentBuilder, InputSource inputSource) {
129 try {
130 rootElement = documentBuilder.parse(inputSource).getDocumentElement();
131 } catch (SAXException e) {
132 throw new NanoContainerMarkupException(e);
133 } catch (IOException e) {
134 throw new NanoContainerMarkupException(e);
135 }
136 }
137
138 protected PicoContainer createContainerFromScript(PicoContainer parentContainer, Object assemblyScope) {
139 try {
140 // create ComponentInstanceFactory for the container
141 componentInstanceFactory = createComponentInstanceFactory(rootElement.getAttribute(COMPONENT_INSTANCE_FACTORY));
142 MutablePicoContainer childContainer = createMutablePicoContainer(rootElement.getAttribute(COMPONENT_ADAPTER_FACTORY),
143 rootElement.getAttribute(COMPONENT_MONITOR), parentContainer);
144 populateContainer(childContainer);
145 return childContainer;
146 } catch (ClassNotFoundException e) {
147 throw new NanoContainerMarkupException("Class not found:" + e.getMessage(), e);
148 }
149 }
150
151 private MutablePicoContainer createMutablePicoContainer(String cafName, String monitorName, PicoContainer parentContainer) throws PicoCompositionException, ClassNotFoundException {
152 MutablePicoContainer container = new DefaultNanoPicoContainer(getClassLoader(),createComponentAdapterFactory(cafName, new DefaultNanoContainer(getClassLoader())), parentContainer);
153 if ( !notSet(monitorName) ){
154 ComponentMonitor monitor = createComponentMonitor(monitorName);
155 ((ComponentMonitorStrategy)container).changeMonitor(monitor);
156 }
157 return container;
158 }
159
160 public void populateContainer(MutablePicoContainer container) {
161 try {
162 String parentClass = rootElement.getAttribute("parentclassloader");
163 ClassLoader classLoader = getClassLoader();
164 if (parentClass != null && !EMPTY.equals(parentClass)) {
165 classLoader = classLoader.loadClass(parentClass).getClassLoader();
166 }
167 NanoContainer nanoContainer = new DefaultNanoContainer(classLoader, container);
168 registerComponentsAndChildContainers(nanoContainer, rootElement, new DefaultNanoContainer(getClassLoader()));
169 } catch (ClassNotFoundException e) {
170 throw new NanoContainerMarkupException("Class not found: " + e.getMessage(), e);
171 } catch (IOException e) {
172 throw new NanoContainerMarkupException(e);
173 } catch (SAXException e) {
174 throw new NanoContainerMarkupException(e);
175 }
176 }
177
178 private void registerComponentsAndChildContainers(NanoContainer parentContainer, Element containerElement, NanoContainer knownComponentAdapterFactories) throws ClassNotFoundException, IOException, SAXException {
179
180 NanoContainer metaContainer = new DefaultNanoContainer(getClassLoader(), knownComponentAdapterFactories.getPico());
181 NodeList children = containerElement.getChildNodes();
182 // register classpath first, regardless of order in the document.
183 for (int i = 0; i < children.getLength(); i++) {
184 if (children.item(i) instanceof Element) {
185 Element childElement = (Element) children.item(i);
186 String name = childElement.getNodeName();
187 if (CLASSPATH.equals(name)) {
188 registerClasspath(parentContainer, childElement);
189 }
190 }
191 }
192 for (int i = 0; i < children.getLength(); i++) {
193 if (children.item(i) instanceof Element) {
194 Element childElement = (Element) children.item(i);
195 String name = childElement.getNodeName();
196 if (CONTAINER.equals(name)) {
197 MutablePicoContainer childContainer = parentContainer.getPico().makeChildContainer();
198 NanoContainer childNanoContainer = new DefaultNanoContainer(parentContainer.getComponentClassLoader(), childContainer);
199 registerComponentsAndChildContainers(childNanoContainer, childElement, metaContainer);
200 } else if (COMPONENT_IMPLEMENTATION.equals(name)
201 || COMPONENT.equals(name)) {
202 registerComponentImplementation(parentContainer, childElement);
203 } else if (COMPONENT_INSTANCE.equals(name)) {
204 registerComponentInstance(parentContainer, childElement);
205 } else if (COMPONENT_ADAPTER.equals(name)) {
206 registerComponentAdapter(parentContainer, childElement, metaContainer);
207 } else if (COMPONENT_ADAPTER_FACTORY.equals(name)) {
208 addComponentAdapterFactory(childElement, metaContainer);
209 } else if (CLASSLOADER.equals(name)) {
210 registerClassLoader(parentContainer, childElement, metaContainer);
211 } else if (DECORATING_PICOCONTAINER.equals(name)) {
212 addDecoratingPicoContainer(parentContainer, childElement);
213 } else if (CLASSPATH.equals(name) != true) {
214 throw new NanoContainerMarkupException("Unsupported element:" + name);
215 }
216 }
217 }
218 }
219
220
221 private void addComponentAdapterFactory(Element element, NanoContainer metaContainer) throws MalformedURLException, ClassNotFoundException {
222 if (notSet(element.getAttribute(KEY))) {
223 throw new NanoContainerMarkupException("'" + KEY + "' attribute not specified for " + element.getNodeName());
224 }
225 Element node = (Element)element.cloneNode(false);
226 NodeList children = element.getChildNodes();
227 for (int i = 0; i < children.getLength(); i++) {
228 if (children.item(i) instanceof Element) {
229 Element childElement = (Element) children.item(i);
230 String name = childElement.getNodeName();
231 if (COMPONENT_ADAPTER_FACTORY.equals(name)) {
232 if (!"".equals(childElement.getAttribute(KEY))) {
233 throw new NanoContainerMarkupException("'" + KEY + "' attribute must not be specified for nested " + element.getNodeName());
234 }
235 childElement = (Element)childElement.cloneNode(true);
236 String key = String.valueOf(System.identityHashCode(childElement));
237 childElement.setAttribute(KEY, key);
238 addComponentAdapterFactory(childElement, metaContainer);
239 // replace nested CAF with a ComponentParameter using an internally generated key
240 Element parameter = node.getOwnerDocument().createElement(PARAMETER);
241 parameter.setAttribute(KEY, key);
242 node.appendChild(parameter);
243 } else if (PARAMETER.equals(name)) {
244 node.appendChild(childElement.cloneNode(true));
245 }
246 }
247 }
248 // handle CAF now as standard component in the metaContainer
249 registerComponentImplementation(metaContainer, node);
250 }
251
252 private void registerClassLoader(NanoContainer parentContainer, Element childElement, NanoContainer metaContainer) throws IOException, SAXException, ClassNotFoundException {
253 String parentClass = childElement.getAttribute("parentclassloader");
254 ClassLoader parentClassLoader = parentContainer.getComponentClassLoader();
255 if (parentClass != null && !EMPTY.equals(parentClass)) {
256 parentClassLoader = parentClassLoader.loadClass(parentClass).getClassLoader();
257 }
258 NanoContainer nano = new DefaultNanoContainer(parentClassLoader, parentContainer.getPico());
259 registerComponentsAndChildContainers(nano, childElement, metaContainer);
260 }
261
262 private void registerClasspath(NanoContainer container, Element classpathElement) throws IOException, ClassNotFoundException {
263 NodeList children = classpathElement.getChildNodes();
264 for (int i = 0; i < children.getLength(); i++) {
265 if (children.item(i) instanceof Element) {
266 Element childElement = (Element) children.item(i);
267
268 String fileName = childElement.getAttribute(FILE);
269 String urlSpec = childElement.getAttribute(URL);
270 URL url = null;
271 if (urlSpec != null && !EMPTY.equals(urlSpec)) {
272 url = new URL(urlSpec);
273 } else {
274 File file = new File(fileName);
275 if (!file.exists()) {
276 throw new IOException(file.getAbsolutePath() + " doesn't exist");
277 }
278 url = file.toURL();
279 }
280 ClassPathElement cpe = container.addClassLoaderURL(url);
281 registerPermissions(cpe, childElement);
282 }
283 }
284 }
285
286 private void registerPermissions(ClassPathElement classPathElement, Element classPathXmlElement) throws ClassNotFoundException {
287 NodeList children = classPathXmlElement.getChildNodes();
288 for (int i = 0; i < children.getLength(); i++) {
289 if (children.item(i) instanceof Element) {
290 Element childElement = (Element) children.item(i);
291
292 String permissionClassName = childElement.getAttribute(CLASSNAME);
293 String action = childElement.getAttribute(CONTEXT);
294 String value = childElement.getAttribute(VALUE);
295 MutablePicoContainer mpc = new DefaultPicoContainer();
296 mpc.registerComponentImplementation(Permission.class, Class.forName(permissionClassName),new Parameter[] {new ConstantParameter(action), new ConstantParameter(value)});
297
298 Permission permission = (Permission) mpc.getComponentInstanceOfType(Permission.class);
299 classPathElement.grantPermission(permission);
300 }
301 }
302
303 }
304
305 private void registerComponentImplementation(NanoContainer container, Element element) throws ClassNotFoundException, MalformedURLException {
306 String className = element.getAttribute(CLASS);
307 if (notSet(className)) {
308 throw new NanoContainerMarkupException("'" + CLASS + "' attribute not specified for " + element.getNodeName());
309 }
310
311 Parameter[] parameters = createChildParameters(container, element);
312 Class clazz = container.getComponentClassLoader().loadClass(className);
313 Object key = element.getAttribute(KEY);
314 String classKey = element.getAttribute(CLASS_NAME_KEY);
315 if (notSet(key)) {
316 if (!notSet(classKey)) {
317 key = getClassLoader().loadClass(classKey);
318 } else {
319 key = clazz;
320 }
321 }
322 if (parameters == null) {
323 container.getPico().registerComponentImplementation(key, clazz);
324 } else {
325 container.getPico().registerComponentImplementation(key, clazz, parameters);
326 }
327 }
328
329 private void addDecoratingPicoContainer(NanoContainer parentContainer, Element childElement) throws ClassNotFoundException {
330 String className = childElement.getAttribute("class");
331
332 parentContainer.addDecoratingPicoContainer(getClassLoader().loadClass(className));
333
334 }
335
336
337
338 private Parameter[] createChildParameters(NanoContainer container, Element element) throws ClassNotFoundException, MalformedURLException {
339 List parametersList = new ArrayList();
340 NodeList children = element.getChildNodes();
341 for (int i = 0; i < children.getLength(); i++) {
342 if (children.item(i) instanceof Element) {
343 Element childElement = (Element) children.item(i);
344 if (PARAMETER.equals(childElement.getNodeName())) {
345 parametersList.add(createParameter(container.getPico(), childElement));
346 }
347 }
348 }
349
350 Parameter[] parameters = null;
351 if (!parametersList.isEmpty()) {
352 parameters = (Parameter[]) parametersList.toArray(new Parameter[parametersList.size()]);
353 }
354 return parameters;
355 }
356
357 /**
358 * Build the org.picocontainer.Parameter from the <code>parameter</code> element. This could
359 * create either a ComponentParameter or ConstantParameter instance,
360 * depending on the values of the element's attributes. This is somewhat
361 * complex because there are five constructors for ComponentParameter and one for
362 * ConstantParameter. These are:
363 *
364 * <a href="http://www.picocontainer.org/picocontainer/latest/picocontainer/apidocs/org/picocontainer/defaults/ComponentParameter.html">ComponentParameter Javadocs</a>:
365 *
366 * <code>ComponentParameter() - Expect any scalar paramter of the appropriate type or an Array.
367 * ComponentParameter(boolean emptyCollection) - Expect any scalar paramter of the appropriate type or an Array.
368 * ComponentParameter(Class componentValueType, boolean emptyCollection) - Expect any scalar paramter of the appropriate type or the collecting type Array,Collectionor Map.
369 * ComponentParameter(Class componentKeyType, Class componentValueType, boolean emptyCollection) - Expect any scalar paramter of the appropriate type or the collecting type Array,Collectionor Map.
370 * ComponentParameter(Object componentKey) - Expect a parameter matching a component of a specific key.</code>
371 *
372 * and
373 *
374 * <a href="http://www.picocontainer.org/picocontainer/latest/picocontainer/apidocs/org/picocontainer/defaults/ConstantParameter.html">ConstantParameter Javadocs</a>:
375 *
376 * <code>ConstantParameter(Object value)</code>
377 *
378 * The rules for this are, in order:
379 *
380 * 1) If the <code>key</code> attribute is not null/empty, the fifth constructor will be used.
381 * 2) If the <code>componentKeyType</code> attribute is not null/empty, the fourth constructor will be used.
382 * In this case, both the <code>componentValueType</code> and <code>emptyCollection</code> attributes must be non-null/empty or an exception will be thrown.
383 * 3) If the <code>componentValueType</code> attribute is not null/empty, the third constructor will be used.
384 * In this case, the <code>emptyCollection</code> attribute must be non-null/empty.
385 * 4) If the <code>emptyCollection</code> attribute is not null/empty, the second constructor will be used.
386 * 5) If there is no child element of the parameter, the first constructor will be used.
387 * 6) Otherwise, the return value will be a ConstantParameter with the return from the createInstance value.
388 */
389 private Parameter createParameter(PicoContainer pico, Element element) throws ClassNotFoundException, MalformedURLException {
390 final Parameter parameter;
391 String key = element.getAttribute(KEY);
392 String emptyCollectionString = element.getAttribute(EMPTY_COLLECTION);
393 String componentValueTypeString = element.getAttribute(COMPONENT_VALUE_TYPE);
394 String componentKeyTypeString = element.getAttribute(COMPONENT_KEY_TYPE);
395
396 // key not null/empty takes precidence
397 if (key != null && !EMPTY.equals(key)) {
398 parameter = new ComponentParameter(key);
399 } else if (componentKeyTypeString != null && !EMPTY.equals(componentKeyTypeString)) {
400 if (emptyCollectionString == null || componentValueTypeString == null ||
401 EMPTY.equals(emptyCollectionString) || EMPTY.equals(componentValueTypeString)) {
402
403 throw new NanoContainerMarkupException("The componentKeyType attribute was specified (" +
404 componentKeyTypeString + ") but one or both of the emptyCollection (" +
405 emptyCollectionString + ") or componentValueType (" + componentValueTypeString +
406 ") was empty or null.");
407 }
408
409 Class componentKeyType = getClassLoader().loadClass(componentKeyTypeString);
410 Class componentValueType = getClassLoader().loadClass(componentValueTypeString);
411
412 boolean emptyCollection = Boolean.valueOf(emptyCollectionString).booleanValue();
413
414 parameter = new ComponentParameter(componentKeyType, componentValueType, emptyCollection);
415 } else if (componentValueTypeString != null && !EMPTY.equals(componentValueTypeString)) {
416 if (emptyCollectionString == null || EMPTY.equals(emptyCollectionString)) {
417
418 throw new NanoContainerMarkupException("The componentValueType attribute was specified (" +
419 componentValueTypeString + ") but the emptyCollection (" +
420 emptyCollectionString + ") was empty or null.");
421 }
422
423 Class componentValueType = getClassLoader().loadClass(componentValueTypeString);
424
425 boolean emptyCollection = Boolean.valueOf(emptyCollectionString).booleanValue();
426
427 parameter = new ComponentParameter(componentValueType, emptyCollection);
428 } else if (emptyCollectionString != null && !EMPTY.equals(emptyCollectionString)) {
429 boolean emptyCollection = Boolean.valueOf(emptyCollectionString).booleanValue();
430
431 parameter = new ComponentParameter(emptyCollection);
432 }
433 else if (getFirstChildElement(element, false) == null) {
434 parameter = new ComponentParameter();
435 } else {
436 Object instance = createInstance(pico, element);
437 parameter = new ConstantParameter(instance);
438 }
439 return parameter;
440 }
441
442 private void registerComponentInstance(NanoContainer container, Element element) throws ClassNotFoundException, PicoCompositionException, MalformedURLException {
443 Object instance = createInstance(container.getPico(), element);
444 String key = element.getAttribute(KEY);
445 String classKey = element.getAttribute(CLASS_NAME_KEY);
446 if (notSet(key)) {
447 if (!notSet(classKey)) {
448 container.getPico().registerComponentInstance(getClassLoader().loadClass(classKey), instance);
449 } else {
450 container.getPico().registerComponentInstance(instance);
451 }
452 } else {
453 container.getPico().registerComponentInstance(key, instance);
454 }
455 }
456
457 private Object createInstance(PicoContainer pico, Element element) throws ClassNotFoundException, MalformedURLException {
458 XMLComponentInstanceFactory factory = createComponentInstanceFactory(element.getAttribute(FACTORY));
459 Element instanceElement = getFirstChildElement(element, true);
460 return factory.makeInstance(pico, instanceElement, getClassLoader());
461 }
462
463 private Element getFirstChildElement(Element parent, boolean fail) {
464 NodeList children = parent.getChildNodes();
465 Element child = null;
466 for (int i = 0; i < children.getLength(); i++) {
467 if (children.item(i) instanceof Element) {
468 child = (Element) children.item(i);
469 break;
470 }
471 }
472 if (child == null && fail) {
473 throw new NanoContainerMarkupException(parent.getNodeName() + " needs a child element");
474 }
475 return child;
476 }
477
478 private XMLComponentInstanceFactory createComponentInstanceFactory(String factoryClass) throws ClassNotFoundException {
479 if ( notSet(factoryClass)) {
480 // no factory has been specified for the node
481 // return globally defined factory for the container - if there is one
482 if (componentInstanceFactory != null) {
483 return componentInstanceFactory;
484 }
485 factoryClass = DEFAULT_COMPONENT_INSTANCE_FACTORY;
486 }
487
488 NanoContainer adapter = new DefaultNanoContainer(getClassLoader());
489 adapter.registerComponentImplementation(XMLComponentInstanceFactory.class.getName(), factoryClass);
490 return (XMLComponentInstanceFactory) adapter.getPico().getComponentInstances().get(0);
491 }
492
493 private void registerComponentAdapter(NanoContainer container, Element element, NanoContainer metaContainer) throws ClassNotFoundException, PicoCompositionException, MalformedURLException {
494 String className = element.getAttribute(CLASS);
495 if (notSet(className)) {
496 throw new NanoContainerMarkupException("'" + CLASS + "' attribute not specified for " + element.getNodeName());
497 }
498 Class implementationClass = getClassLoader().loadClass(className);
499 Object key = element.getAttribute(KEY);
500 String classKey = element.getAttribute(CLASS_NAME_KEY);
501 if (notSet(key)) {
502 if (!notSet(classKey)) {
503 key = getClassLoader().loadClass(classKey);
504 } else {
505 key = implementationClass;
506 }
507 }
508 Parameter[] parameters = createChildParameters(container, element);
509 ComponentAdapterFactory componentAdapterFactory = createComponentAdapterFactory(element.getAttribute(FACTORY), metaContainer);
510 container.getPico().registerComponent(componentAdapterFactory.createComponentAdapter(key, implementationClass, parameters));
511 }
512
513 private ComponentAdapterFactory createComponentAdapterFactory(String factoryName, NanoContainer metaContainer) throws ClassNotFoundException, PicoCompositionException {
514 if ( notSet(factoryName)) {
515 factoryName = DEFAULT_COMPONENT_ADAPTER_FACTORY;
516 }
517 final Object key;
518 if (metaContainer.getPico().getComponentAdapter(factoryName) != null) {
519 key = factoryName;
520 } else {
521 metaContainer.registerComponentImplementation(new ClassNameKey(ComponentAdapterFactory.class.getName()), factoryName);
522 key = ComponentAdapterFactory.class;
523 }
524 return (ComponentAdapterFactory) metaContainer.getPico().getComponentInstance(key);
525 }
526
527 private ComponentMonitor createComponentMonitor(String monitorName) throws ClassNotFoundException, PicoCompositionException {
528 if (notSet(monitorName)) {
529 monitorName = DEFAULT_COMPONENT_MONITOR;
530 }
531 Class monitorClass = getClassLoader().loadClass(monitorName);
532 try {
533 return (ComponentMonitor) monitorClass.newInstance();
534 } catch (InstantiationException e) {
535 throw new NanoContainerMarkupException(e);
536 } catch (IllegalAccessException e) {
537 throw new NanoContainerMarkupException(e);
538 }
539 }
540
541 private boolean notSet(Object string) {
542 return string == null || string.equals(EMPTY);
543 }
544
545 }