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