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 }