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.io.StringReader; 017 import java.io.StringWriter; 018 import java.io.Writer; 019 import java.text.SimpleDateFormat; 020 import java.util.ArrayList; 021 import java.util.Date; 022 import java.util.Iterator; 023 import java.util.Map; 024 import java.util.Vector; 025 026 import javax.swing.JButton; 027 028 import org.nanocontainer.script.AbstractScriptedContainerBuilderTestCase; 029 import org.nanocontainer.script.BarDecoratingPicoContainer; 030 import org.nanocontainer.script.FooDecoratingPicoContainer; 031 import org.nanocontainer.script.NanoContainerMarkupException; 032 import org.nanocontainer.testmodel.CustomerEntityImpl; 033 import org.nanocontainer.testmodel.DefaultWebServerConfig; 034 import org.nanocontainer.testmodel.Entity; 035 import org.nanocontainer.testmodel.ListSupport; 036 import org.nanocontainer.testmodel.MapSupport; 037 import org.nanocontainer.testmodel.OrderEntityImpl; 038 import org.nanocontainer.testmodel.WebServerConfig; 039 import org.nanocontainer.testmodel.WebServerConfigComp; 040 import org.picocontainer.ComponentAdapter; 041 import org.picocontainer.PicoContainer; 042 import org.picocontainer.PicoException; 043 import org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory; 044 import org.picocontainer.defaults.DefaultComponentAdapterFactory; 045 import org.picocontainer.monitors.WriterComponentMonitor; 046 import org.picocontainer.testmodel.SimpleTouchable; 047 import org.picocontainer.testmodel.Touchable; 048 import org.w3c.dom.Element; 049 import org.xml.sax.SAXException; 050 051 /** 052 * @author Paul Hammant 053 * @author Aslak Hellesøy 054 * @author Jeppe Cramon 055 * @author Mauro Talevi 056 * @version $Revision: 3407 $ 057 */ 058 public class XMLContainerBuilderTestCase extends AbstractScriptedContainerBuilderTestCase { 059 060 //TODO some tests for XMLContainerBuilder that use a classloader that is retrieved at testtime. 061 // i.e. not a programatic consequence of this.getClass().getClassLoader() 062 063 public void testCreateSimpleContainer() { 064 Reader script = new StringReader("" + 065 "<container>" + 066 " <component-implementation class='java.lang.StringBuffer'/>" + 067 " <component-implementation class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 068 " <component-implementation key='org.nanocontainer.testmodel.WebServer' class='org.nanocontainer.testmodel.WebServerImpl'/>" + 069 "</container>"); 070 071 PicoContainer pico = buildContainer(script); 072 assertEquals(3, pico.getComponentInstances().size()); 073 assertNotNull(pico.getComponentInstance(StringBuffer.class)); 074 assertNotNull(pico.getComponentInstance(DefaultWebServerConfig.class)); 075 assertNotNull(pico.getComponentInstance("org.nanocontainer.testmodel.WebServer")); 076 } 077 078 public void testCreateSimpleContainerWithExplicitKeysAndParameters() { 079 Reader script = new StringReader("" + 080 "<container>" + 081 " <component-implementation key='aBuffer' class='java.lang.StringBuffer'/>" + 082 " <component-implementation key='org.nanocontainer.testmodel.WebServerConfig' class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 083 " <component-implementation key='org.nanocontainer.testmodel.WebServer' class='org.nanocontainer.testmodel.WebServerImpl'>" + 084 " <parameter key='org.nanocontainer.testmodel.WebServerConfig'/>" + 085 " <parameter key='aBuffer'/>" + 086 " </component-implementation>" + 087 "</container>"); 088 089 PicoContainer pico = buildContainer(script); 090 assertEquals(3, pico.getComponentInstances().size()); 091 assertNotNull(pico.getComponentInstance("aBuffer")); 092 assertNotNull(pico.getComponentInstance("org.nanocontainer.testmodel.WebServerConfig")); 093 assertNotNull(pico.getComponentInstance("org.nanocontainer.testmodel.WebServer")); 094 } 095 096 public void testCreateSimpleContainerWithExplicitKeysAndImplicitParameter() { 097 Reader script = new StringReader("" + 098 "<container>" + 099 " <component-implementation key='aBuffer' class='java.lang.StringBuffer'/>" + 100 " <component-implementation key='org.nanocontainer.testmodel.WebServerConfig' class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 101 " <component-implementation key='org.nanocontainer.testmodel.WebServer' class='org.nanocontainer.testmodel.WebServerImpl'>" + 102 " <parameter/>" + 103 " <parameter key='aBuffer'/>" + 104 " </component-implementation>" + 105 "</container>"); 106 107 PicoContainer pico = buildContainer(script); 108 assertEquals(3, pico.getComponentInstances().size()); 109 assertNotNull(pico.getComponentInstance("aBuffer")); 110 assertNotNull(pico.getComponentInstance("org.nanocontainer.testmodel.WebServerConfig")); 111 assertNotNull(pico.getComponentInstance("org.nanocontainer.testmodel.WebServer")); 112 } 113 114 public void testNonParameterElementsAreIgnoredInComponentImplementation() { 115 Reader script = new StringReader("" + 116 "<container>" + 117 " <component-implementation key='aBuffer' class='java.lang.StringBuffer'/>" + 118 " <component-implementation key='org.nanocontainer.testmodel.WebServerConfig' class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 119 " <component-implementation key='org.nanocontainer.testmodel.WebServer' class='org.nanocontainer.testmodel.WebServerImpl'>" + 120 " <parameter key='org.nanocontainer.testmodel.WebServerConfig'/>" + 121 " <parameter key='aBuffer'/>" + 122 " <any-old-stuff/>" + 123 " </component-implementation>" + 124 "</container>"); 125 126 PicoContainer pico = buildContainer(script); 127 assertEquals(3, pico.getComponentInstances().size()); 128 assertNotNull(pico.getComponentInstance("aBuffer")); 129 assertNotNull(pico.getComponentInstance("org.nanocontainer.testmodel.WebServerConfig")); 130 assertNotNull(pico.getComponentInstance("org.nanocontainer.testmodel.WebServer")); 131 } 132 133 public void testContainerCanHostAChild() { 134 Reader script = new StringReader("" + 135 "<container>" + 136 " <component-implementation class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 137 " <component-implementation class='java.lang.StringBuffer'/>" + 138 " <container>" + 139 " <component-implementation key='org.nanocontainer.testmodel.WebServer' class='org.nanocontainer.testmodel.WebServerImpl'/>" + 140 " </container>" + 141 "</container>"); 142 143 PicoContainer pico = buildContainer(script); 144 assertNotNull(pico.getComponentInstance(DefaultWebServerConfig.class)); 145 146 StringBuffer sb = (StringBuffer) pico.getComponentInstance(StringBuffer.class); 147 assertTrue(sb.toString().indexOf("-WebServerImpl") != -1); 148 } 149 150 public void testClassLoaderHierarchy() throws IOException { 151 String testcompJarFileName = System.getProperty("testcomp.jar", "src/test-comp/TestComp.jar"); 152 // Paul's path to TestComp. PLEASE do not take out. 153 //testcompJarFileName = "D:/OSS/PN/java/nanocontainer/src/test-comp/TestComp.jar"; 154 File testCompJar = new File(testcompJarFileName); 155 assertTrue("The testcomp.jar system property should point to java/nanocontainer/src/test-comp/TestComp.jar", testCompJar.isFile()); 156 File testCompJar2 = new File(testCompJar.getParentFile(), "TestComp2.jar"); 157 File notStartableJar = new File(testCompJar.getParentFile(), "NotStartable.jar"); 158 159 assertTrue(testCompJar.isFile()); 160 assertTrue(testCompJar2.isFile()); 161 162 Reader script = new StringReader("" + 163 "<container>" + 164 " <classpath>" + 165 " <element file='" + testCompJar.getCanonicalPath() + "'>" + 166 " <grant classname='java.io.FilePermission' context='*' value='read' />" + 167 " </element>" + 168 " </classpath>" + 169 " <component-implementation key='foo' class='TestComp'/>" + 170 " <container>" + 171 " <classpath>" + 172 " <element file='" + testCompJar2.getCanonicalPath() + "'/>" + 173 " <element file='" + notStartableJar.getCanonicalPath() + "'/>" + 174 " </classpath>" + 175 " <component-implementation key='bar' class='TestComp2'/>" + 176 " <component-implementation key='phony' class='NotStartable'/>" + 177 " </container>" + 178 " <component-implementation class='java.lang.StringBuffer'/>" + 179 "</container>"); 180 181 PicoContainer pico = buildContainer(script); 182 Object fooTestComp = pico.getComponentInstance("foo"); 183 assertNotNull("Container should have a 'foo' component", fooTestComp); 184 185 StringBuffer sb = (StringBuffer) pico.getComponentInstance(StringBuffer.class); 186 assertTrue("Container should have instantiated a 'TestComp2' component because it is Startable", sb.toString().indexOf("-TestComp2") != -1); 187 // We are using the DefaultLifecycleManager, which only instantiates Startable components, and not non-Startable components. 188 assertTrue("Container should NOT have instantiated a 'NotStartable' component because it is NOT Startable", sb.toString().indexOf("-NotStartable") == -1); 189 } 190 191 public void testUnknownclassThrowsNanoContainerMarkupException() { 192 try { 193 Reader script = new StringReader("" + 194 "<container>" + 195 " <component-implementation class='Foo'/>" + 196 "</container>"); 197 buildContainer(script); 198 fail(); 199 } catch (NanoContainerMarkupException expected) { 200 assertTrue(expected.getCause() instanceof ClassNotFoundException); 201 } 202 } 203 204 public void testNoImplementationClassThrowsNanoContainerMarkupException() { 205 Reader script = new StringReader("" + 206 "<container>" + 207 " <component-implementation/>" + 208 "</container>"); 209 try { 210 buildContainer(script); 211 } catch (NanoContainerMarkupException expected) { 212 assertEquals("'class' attribute not specified for component-implementation", expected.getMessage()); 213 } 214 } 215 216 public void testConstantParameterWithNoChildElementThrowsNanoContainerMarkupException() { 217 Reader script = new StringReader("" + 218 "<container>" + 219 " <component-implementation class='org.nanocontainer.script.xml.TestBeanComposer'>" + 220 " <parameter>" + 221 " </parameter>" + 222 " </component-implementation>" + 223 "</container>"); 224 225 try { 226 buildContainer(script); 227 } catch (NanoContainerMarkupException e) { 228 assertEquals("parameter needs a child element", e.getMessage()); 229 } 230 } 231 232 public void testEmptyScriptDoesNotThrowsEmptyCompositionException() { 233 Reader script = new StringReader("<container/>"); 234 buildContainer(script); 235 } 236 237 public void testCreateContainerFromScriptThrowsSAXException() { 238 Reader script = new StringReader("" + 239 "<container component-adapter-factory='" + ConstructorInjectionComponentAdapterFactory.class.getName() + "'>" + 240 " <component-implementation class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 241 "<container>"); 242 try { 243 buildContainer(script); 244 } catch (NanoContainerMarkupException e) { 245 assertTrue("SAXException", e.getCause() instanceof SAXException); 246 } 247 } 248 249 public void testCreateContainerFromNullScriptThrowsNullPointerException() { 250 Reader script = null; 251 try { 252 buildContainer(script); 253 fail("NullPointerException expected"); 254 } catch (NullPointerException expected) { 255 } 256 } 257 258 public void testShouldThrowExceptionForNonExistantCafClass() { 259 Reader script = new StringReader("" + 260 "<container component-adapter-factory='org.nanocontainer.SomeInexistantFactory'>" + 261 " <component-implementation class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 262 "</container>"); 263 try { 264 buildContainer(script); 265 fail(); 266 } catch (NanoContainerMarkupException expected) { 267 assertTrue("Message of exception does not contain missing class", expected.getMessage().indexOf("org.nanocontainer.SomeInexistantFactory") > 0); 268 } 269 } 270 271 public void testComponentInstanceWithNoChildElementThrowsNanoContainerMarkupException() { 272 Reader script = new StringReader("" + 273 "<container>" + 274 " <component-instance>" + 275 " </component-instance>" + 276 "</container>"); 277 278 try { 279 buildContainer(script); 280 fail(); 281 } catch (NanoContainerMarkupException expected) { 282 assertEquals("component-instance needs a child element", expected.getMessage()); 283 } 284 } 285 286 public void testComponentInstanceWithFactoryCanBeUsed() { 287 Reader script = new StringReader("" + 288 "<container>" + 289 " <component-instance factory='org.nanocontainer.script.xml.XMLContainerBuilderTestCase$TestFactory'>" + 290 " <config-or-whatever/>" + 291 " </component-instance>" + 292 "</container>"); 293 294 PicoContainer pico = buildContainer(script); 295 Object instance = pico.getComponentInstances().get(0); 296 assertNotNull(instance); 297 assertTrue(instance instanceof String); 298 assertEquals("Hello", instance.toString()); 299 } 300 301 public void testComponentInstanceWithDefaultFactory() { 302 Reader script = new StringReader("" + 303 "<container>" + 304 " <component-instance>" + 305 " <org.nanocontainer.script.xml.TestBean>" + 306 " <foo>10</foo>" + 307 " <bar>hello</bar>" + 308 " </org.nanocontainer.script.xml.TestBean>" + 309 " </component-instance>" + 310 "</container>"); 311 312 PicoContainer pico = buildContainer(script); 313 Object instance = pico.getComponentInstances().get(0); 314 assertNotNull(instance); 315 assertTrue(instance instanceof TestBean); 316 assertEquals(10, ((TestBean) instance).getFoo()); 317 assertEquals("hello", ((TestBean) instance).getBar()); 318 } 319 320 public void testComponentInstanceWithBeanFactory() { 321 Reader script = new StringReader("" + 322 "<container>" + 323 " <component-instance factory='org.nanocontainer.script.xml.BeanComponentInstanceFactory'>" + 324 " <org.nanocontainer.script.xml.TestBean>" + 325 " <foo>10</foo>" + 326 " <bar>hello</bar>" + 327 " </org.nanocontainer.script.xml.TestBean>" + 328 " </component-instance>" + 329 "</container>"); 330 331 PicoContainer pico = buildContainer(script); 332 Object instance = pico.getComponentInstances().get(0); 333 assertNotNull(instance); 334 assertTrue(instance instanceof TestBean); 335 assertEquals(10, ((TestBean) instance).getFoo()); 336 assertEquals("hello", ((TestBean) instance).getBar()); 337 } 338 339 public void testComponentInstanceWithBeanFactoryAndInstanceThatIsDefinedInContainer() { 340 Reader script = new StringReader("" + 341 "<container>" + 342 " <component-instance key='date' factory='org.nanocontainer.script.xml.BeanComponentInstanceFactory'>" + 343 " <java.util.Date>" + 344 " <time>0</time>" + 345 " </java.util.Date>" + 346 " </component-instance>" + 347 " <component-instance factory='org.nanocontainer.script.xml.BeanComponentInstanceFactory'>" + 348 " <java.text.SimpleDateFormat>" + 349 " <lenient>false</lenient>" + 350 " <date name='2DigitYearStart'>date</date>" + 351 " </java.text.SimpleDateFormat>" + 352 " </component-instance>" + 353 "</container>"); 354 355 PicoContainer pico = buildContainer(script); 356 Object instance = pico.getComponentInstance(SimpleDateFormat.class); 357 assertNotNull(instance); 358 assertTrue(instance instanceof SimpleDateFormat); 359 SimpleDateFormat format = ((SimpleDateFormat) instance); 360 assertFalse(format.isLenient()); 361 assertEquals(new Date(0), format.get2DigitYearStart()); 362 } 363 364 public void testComponentInstanceWithKey() { 365 Reader script = new StringReader("" + 366 "<container>" + 367 " <component-instance key='aString'>" + 368 " <string>Hello</string>" + 369 " </component-instance>" + 370 "" + 371 " <component-instance key='aLong'>" + 372 " <long>22</long>" + 373 " </component-instance>" + 374 "" + 375 " <component-instance key='aButton'>" + 376 " <javax.swing.JButton>" + 377 " <text>Hello</text>" + 378 " <alignmentX>0.88</alignmentX>" + 379 " </javax.swing.JButton>" + 380 " </component-instance>" + 381 "</container>"); 382 383 PicoContainer pico = buildContainer(script); 384 assertEquals("Hello", pico.getComponentInstance("aString")); 385 assertEquals(new Long(22), pico.getComponentInstance("aLong")); 386 JButton button = (JButton) pico.getComponentInstance("aButton"); 387 assertEquals("Hello", button.getText()); 388 assertEquals(0.88, button.getAlignmentX(), 0.01); 389 } 390 391 public void testComponentInstanceWithClassKey() { 392 Reader script = new StringReader("" + 393 "<container>" + 394 " <component-instance class-name-key='java.util.Map' factory='org.nanocontainer.script.xml.XStreamComponentInstanceFactory'>" + 395 " <properties>" + 396 " <property name='foo' value='bar'/>" + 397 " </properties>" + 398 " </component-instance>" + 399 "</container>"); 400 401 PicoContainer pico = buildContainer(script); 402 Map map = (Map)pico.getComponentInstance(Map.class); 403 assertNotNull(map); 404 assertEquals("bar", map.get("foo")); 405 } 406 407 public void testComponentInstanceWithFactoryAndKey() { 408 Reader script = new StringReader("" + 409 "<container>" + 410 " <component-instance factory='org.nanocontainer.script.xml.XMLContainerBuilderTestCase$TestFactory'" + 411 " key='aKey'>" + 412 " <config-or-whatever/>" + 413 " </component-instance>" + 414 "</container>"); 415 416 PicoContainer pico = buildContainer(script); 417 Object instance = pico.getComponentInstance("aKey"); 418 assertNotNull(instance); 419 assertTrue(instance instanceof String); 420 assertEquals("Hello", instance.toString()); 421 } 422 423 public void testComponentInstanceWithContainerFactoryAndKey() { 424 Reader script = new StringReader("" + 425 "<container component-instance-factory='org.nanocontainer.script.xml.XMLContainerBuilderTestCase$ContainerTestFactory'>" + 426 " <component-instance factory='org.nanocontainer.script.xml.XMLContainerBuilderTestCase$TestFactory'" + 427 " key='firstKey'>" + 428 " <config-or-whatever/>" + 429 " </component-instance>" + 430 " <component-instance key='secondKey'>" + 431 " <config-or-whatever/>" + 432 " </component-instance>" + 433 "</container>"); 434 435 PicoContainer pico = buildContainer(script); 436 Object first = pico.getComponentInstance("firstKey"); 437 assertNotNull(first); 438 assertTrue(first instanceof String); 439 assertEquals("Hello", first.toString()); 440 Object second = pico.getComponentInstance("secondKey"); 441 assertNotNull(second); 442 assertTrue(second instanceof String); 443 assertEquals("ContainerHello", second.toString()); 444 } 445 446 public static class TestFactory implements XMLComponentInstanceFactory { 447 public Object makeInstance(PicoContainer pico, Element elem, ClassLoader classLoader) { 448 return "Hello"; 449 } 450 } 451 452 public static class ContainerTestFactory implements XMLComponentInstanceFactory { 453 public Object makeInstance(PicoContainer pico, Element elem, ClassLoader classLoader) { 454 return "ContainerHello"; 455 } 456 } 457 458 public void testInstantiationOfComponentsWithParams() { 459 Reader script = new StringReader("" + 460 "<container>" + 461 " <component-implementation class='org.nanocontainer.testmodel.WebServerConfigComp'>" + 462 " <parameter><string>localhost</string></parameter>" + 463 " <parameter><int>8080</int></parameter>" + 464 " </component-implementation>" + 465 " <component-implementation key='org.nanocontainer.testmodel.WebServer' class='org.nanocontainer.testmodel.WebServerImpl'/>" + 466 "</container>"); 467 PicoContainer pico = buildContainer(script); 468 assertNotNull(pico.getComponentInstance(WebServerConfigComp.class)); 469 WebServerConfigComp config = (WebServerConfigComp) pico.getComponentInstanceOfType(WebServerConfigComp.class); 470 assertEquals("localhost", config.getHost()); 471 assertEquals(8080, config.getPort()); 472 } 473 474 public void testInstantiationOfComponentsWithParameterInstancesOfSameComponent() { 475 Reader script = new StringReader("" + 476 "<container>" + 477 " <component-implementation class='org.nanocontainer.script.xml.TestBeanComposer'>" + 478 " <parameter>" + 479 " <org.nanocontainer.script.xml.TestBean>" + 480 " <foo>10</foo>" + 481 " <bar>hello1</bar>" + 482 " </org.nanocontainer.script.xml.TestBean>" + 483 " </parameter>" + 484 " <parameter>" + 485 " <org.nanocontainer.script.xml.TestBean>" + 486 " <foo>10</foo>" + 487 " <bar>hello2</bar>" + 488 " </org.nanocontainer.script.xml.TestBean>" + 489 " </parameter>" + 490 " </component-implementation>" + 491 "</container>"); 492 PicoContainer pico = buildContainer(script); 493 assertNotNull(pico.getComponentInstance(TestBeanComposer.class)); 494 TestBeanComposer composer = (TestBeanComposer) pico.getComponentInstance(TestBeanComposer.class); 495 assertEquals("bean1", "hello1", composer.getBean1().getBar()); 496 assertEquals("bean2", "hello2", composer.getBean2().getBar()); 497 } 498 499 public void testInstantiationOfComponentsWithParameterInstancesOfSameComponentAndBeanFactory() { 500 Reader script = new StringReader("" + 501 "<container>" + 502 " <component-implementation class='org.nanocontainer.script.xml.TestBeanComposer'>" + 503 " <parameter factory='org.nanocontainer.script.xml.BeanComponentInstanceFactory'>" + 504 " <org.nanocontainer.script.xml.TestBean>" + 505 " <foo>10</foo>" + 506 " <bar>hello1</bar>" + 507 " </org.nanocontainer.script.xml.TestBean>" + 508 " </parameter>" + 509 " <parameter factory='org.nanocontainer.script.xml.BeanComponentInstanceFactory'>" + 510 " <org.nanocontainer.script.xml.TestBean>" + 511 " <foo>10</foo>" + 512 " <bar>hello2</bar>" + 513 " </org.nanocontainer.script.xml.TestBean>" + 514 " </parameter>" + 515 " </component-implementation>" + 516 "</container>"); 517 PicoContainer pico = buildContainer(script); 518 assertNotNull(pico.getComponentInstance(TestBeanComposer.class)); 519 TestBeanComposer composer = (TestBeanComposer) pico.getComponentInstance(TestBeanComposer.class); 520 assertEquals("bean1", "hello1", composer.getBean1().getBar()); 521 assertEquals("bean2", "hello2", composer.getBean2().getBar()); 522 } 523 524 public void testInstantiationOfComponentsWithParameterKeys() { 525 Reader script = new StringReader("" + 526 "<container>" + 527 " <component-instance key='bean1'>" + 528 " <org.nanocontainer.script.xml.TestBean>" + 529 " <foo>10</foo>" + 530 " <bar>hello1</bar>" + 531 " </org.nanocontainer.script.xml.TestBean>" + 532 " </component-instance>" + 533 " <component-instance key='bean2'>" + 534 " <org.nanocontainer.script.xml.TestBean>" + 535 " <foo>10</foo>" + 536 " <bar>hello2</bar>" + 537 " </org.nanocontainer.script.xml.TestBean>" + 538 " </component-instance>" + 539 " <component-implementation class='org.nanocontainer.script.xml.TestBeanComposer'>" + 540 " <parameter key='bean1'/>" + 541 " <parameter key='bean2'/>" + 542 " </component-implementation>" + 543 "</container>"); 544 PicoContainer pico = buildContainer(script); 545 assertNotNull(pico.getComponentInstance(TestBeanComposer.class)); 546 TestBeanComposer composer = (TestBeanComposer) pico.getComponentInstance(TestBeanComposer.class); 547 assertEquals("bean1", "hello1", composer.getBean1().getBar()); 548 assertEquals("bean2", "hello2", composer.getBean2().getBar()); 549 } 550 551 public void testInstantiationOfComponentsWithComponentAdapter() { 552 Reader script = new StringReader("" + 553 "<container>" + 554 " <component-instance key='bean1'>" + 555 " <org.nanocontainer.script.xml.TestBean>" + 556 " <foo>10</foo>" + 557 " <bar>hello1</bar>" + 558 " </org.nanocontainer.script.xml.TestBean>" + 559 " </component-instance>" + 560 " <component-instance key='bean2'>" + 561 " <org.nanocontainer.script.xml.TestBean>" + 562 " <foo>10</foo>" + 563 " <bar>hello2</bar>" + 564 " </org.nanocontainer.script.xml.TestBean>" + 565 " </component-instance>" + 566 " <component-adapter key='beanKey' class='org.nanocontainer.script.xml.TestBeanComposer'>" + 567 " <parameter key='bean1'/>" + 568 " <parameter key='bean2'/>" + 569 " </component-adapter>" + 570 "</container>"); 571 PicoContainer pico = buildContainer(script); 572 assertNotNull(pico.getComponentInstance("beanKey")); 573 TestBeanComposer composer = (TestBeanComposer) pico.getComponentInstance("beanKey"); 574 assertEquals("bean1", "hello1", composer.getBean1().getBar()); 575 assertEquals("bean2", "hello2", composer.getBean2().getBar()); 576 } 577 578 public void testComponentAdapterWithSpecifiedFactory() { 579 Reader script = new StringReader("" + 580 "<container>" + 581 " <component-instance key='bean1'>" + 582 " <org.nanocontainer.script.xml.TestBean>" + 583 " <foo>10</foo>" + 584 " <bar>hello1</bar>" + 585 " </org.nanocontainer.script.xml.TestBean>" + 586 " </component-instance>" + 587 " <component-instance key='bean2'>" + 588 " <org.nanocontainer.script.xml.TestBean>" + 589 " <foo>10</foo>" + 590 " <bar>hello2</bar>" + 591 " </org.nanocontainer.script.xml.TestBean>" + 592 " </component-instance>" + 593 " <component-adapter key='beanKey' class='org.nanocontainer.script.xml.TestBeanComposer'" + 594 " factory='" + DefaultComponentAdapterFactory.class.getName() + "'>" + 595 " <parameter key='bean1'/>" + 596 " <parameter key='bean2'/>" + 597 " </component-adapter>" + 598 "</container>"); 599 PicoContainer pico = buildContainer(script); 600 assertNotNull(pico.getComponentInstance("beanKey")); 601 TestBeanComposer composer = (TestBeanComposer) pico.getComponentInstance("beanKey"); 602 assertEquals("bean1", "hello1", composer.getBean1().getBar()); 603 assertEquals("bean2", "hello2", composer.getBean2().getBar()); 604 } 605 606 public void testComponentAdapterWithNoKeyUsesTypeAsKey() { 607 Reader script = new StringReader("" + 608 "<container>" + 609 " <component-adapter class='org.nanocontainer.script.xml.TestBeanComposer'/>" + 610 "</container>"); 611 PicoContainer pico = buildContainer(script); 612 ComponentAdapter adapter = (ComponentAdapter)pico.getComponentAdapters().iterator().next(); 613 assertSame(TestBeanComposer.class, adapter.getComponentImplementation()); 614 } 615 616 public void testComponentAdapterWithNoClassThrowsNanoContainerMarkupException() { 617 Reader script = new StringReader("" + 618 "<container>" + 619 " <component-adapter key='beanKey'/> " + 620 "</container>"); 621 try { 622 buildContainer(script); 623 fail(); 624 } catch (NanoContainerMarkupException expected) { 625 assertEquals("'class' attribute not specified for component-adapter", expected.getMessage()); 626 } 627 } 628 629 // This is of little value given that nested adapters can't be specified in XML. 630 public void testComponentAdapterClassCanBeSpecifiedInContainerElement() { 631 Reader script = new StringReader("" + 632 "<container component-adapter-factory='" + ConstructorInjectionComponentAdapterFactory.class.getName() + "'>" + 633 " <component-implementation class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 634 "</container>"); 635 636 PicoContainer pico = buildContainer(script); 637 Object wsc1 = pico.getComponentInstanceOfType(WebServerConfig.class); 638 Object wsc2 = pico.getComponentInstanceOfType(WebServerConfig.class); 639 640 assertNotSame(wsc1, wsc2); 641 } 642 643 public void testComponentMonitorCanBeSpecified() { 644 Reader script = new StringReader("" + 645 "<container component-monitor='" + StaticWriterComponentMonitor.class.getName() + "'>" + 646 " <component-implementation class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 647 "</container>"); 648 649 PicoContainer pico = buildContainer(script); 650 pico.getComponentInstanceOfType(WebServerConfig.class); 651 assertTrue(StaticWriterComponentMonitor.WRITER.toString().length() > 0); 652 } 653 654 public void testComponentMonitorCanBeSpecifiedIfCAFIsSpecified() { 655 Reader script = new StringReader("" + 656 "<container component-adapter-factory='" +DefaultComponentAdapterFactory.class.getName() + 657 "' component-monitor='" + StaticWriterComponentMonitor.class.getName() + "'>" + 658 " <component-implementation class='org.nanocontainer.testmodel.DefaultWebServerConfig'/>" + 659 "</container>"); 660 661 PicoContainer pico = buildContainer(script); 662 pico.getComponentInstanceOfType(WebServerConfig.class); 663 assertTrue(StaticWriterComponentMonitor.WRITER.toString().length() > 0); 664 } 665 666 public void testComponentCanUsePredefinedCAF() { 667 Reader script = new StringReader("" + 668 "<container>" + 669 " <component-adapter-factory class='org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory' key='factory'/>" + 670 " <component-adapter class='org.nanocontainer.testmodel.DefaultWebServerConfig' factory='factory'/>" + 671 "</container>"); 672 PicoContainer pico = buildContainer(script); 673 WebServerConfig cfg1 = (WebServerConfig)pico.getComponentInstanceOfType(WebServerConfig.class); 674 WebServerConfig cfg2 = (WebServerConfig)pico.getComponentInstanceOfType(WebServerConfig.class); 675 assertNotSame("Instances for components registered with a CICA must not be the same", cfg1, cfg2); 676 } 677 678 public void testComponentCanUsePredefinedNestedCAF() { 679 Reader script = new StringReader("" + 680 "<container>" + 681 " <component-adapter-factory class='org.picocontainer.defaults.ImplementationHidingComponentAdapterFactory' key='factory'>" + 682 " <component-adapter-factory class='org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory'/>" + 683 " </component-adapter-factory>" + 684 " <component-adapter class-name-key='org.nanocontainer.testmodel.WebServerConfig' class='org.nanocontainer.testmodel.DefaultWebServerConfig' factory='factory'/>" + 685 "</container>"); 686 PicoContainer pico = buildContainer(script); 687 WebServerConfig cfg1 = (WebServerConfig)pico.getComponentInstanceOfType(WebServerConfig.class); 688 WebServerConfig cfg2 = (WebServerConfig)pico.getComponentInstanceOfType(WebServerConfig.class); 689 assertNotSame("Instances for components registered with a CICA must not be the same", cfg1, cfg2); 690 assertFalse("Instance exposes only interface", cfg1 instanceof DefaultWebServerConfig); 691 } 692 693 public void testComponentCanUsePredefinedCAFWithParameters() { 694 Reader script = new StringReader("" + 695 "<container>" + 696 " <component-adapter-factory class='org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory' key='factory'>" + 697 " <parameter><boolean>true</boolean></parameter>" + 698 " </component-adapter-factory>" + 699 " <component-adapter key='pc1' class='org.nanocontainer.script.xml.XMLContainerBuilderTestCase$PrivateComponent' factory='org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory'/>" + 700 " <component-adapter key='pc2' class='org.nanocontainer.script.xml.XMLContainerBuilderTestCase$PrivateComponent' factory='factory'/>" + 701 "</container>"); 702 PicoContainer pico = buildContainer(script); 703 PrivateComponent pc2 = (PrivateComponent)pico.getComponentInstance("pc2"); 704 assertNotNull(pc2); 705 try { 706 pico.getComponentInstance("pc1"); 707 fail("Thrown " + PicoException.class.getName() + " expected"); 708 } catch (final PicoException e) { 709 assertTrue(e.getMessage().indexOf(PrivateComponent.class.getName())>0); 710 } 711 } 712 713 public void testChainOfDecoratingPicoContainersCanDoInterceptionOfMutablePicoContainerMethods() throws ClassNotFoundException { 714 715 Reader script = new StringReader("" + 716 "<container>\n" + 717 " <decorating-picocontainer class='"+FooDecoratingPicoContainer.class.getName()+"'/>" + 718 " <decorating-picocontainer class='"+BarDecoratingPicoContainer.class.getName()+"'/>" + 719 " <component-implementation class='java.util.Vector'/>" + 720 "</container>"); 721 722 PicoContainer pico = buildContainer(script); 723 724 // decorators are fairly dirty - they replace a very select implementation in this TestCase. 725 assertNotNull(pico.getComponentInstanceOfType(ArrayList.class)); 726 assertNull(pico.getComponentInstanceOfType(Vector.class)); 727 } 728 729 public void testChainOfWrappedComponents() { 730 731 Reader script = new StringReader("" + 732 "<container>\n" + 733 " <component-implementation key='wrapped' class='"+SimpleTouchable.class.getName()+"'/>" + 734 " <component-implementation class-name-key=\'"+Touchable.class.getName()+"\' class='"+WrapsTouchable.class.getName()+"'/>" + 735 "</container>"); 736 737 PicoContainer pico = buildContainer(script); 738 739 // decorators are fairly dirty - they replace a very select implementation in this TestCase. 740 assertNotNull(pico.getComponentInstanceOfType(Touchable.class)); 741 } 742 743 public void testListSupport() { 744 745 Reader script = new StringReader("" + 746 "<container>\n" + 747 " <component-implementation class='"+ListSupport.class.getName()+"'>" + 748 " <parameter empty-collection='false' component-value-type='"+Entity.class.getName()+"'/>" + 749 " </component-implementation>" + 750 " <component-implementation class=\'"+CustomerEntityImpl.class.getName()+"\'/>" + 751 " <component-implementation class=\'"+OrderEntityImpl.class.getName()+"\'/>" + 752 "</container>"); 753 754 PicoContainer pico = buildContainer(script); 755 756 ListSupport listSupport = (ListSupport)pico.getComponentInstanceOfType(ListSupport.class); 757 758 assertNotNull(listSupport); 759 assertNotNull(listSupport.getAListOfEntityObjects()); 760 assertEquals(2, listSupport.getAListOfEntityObjects().size()); 761 762 Entity entity1 = (Entity)listSupport.getAListOfEntityObjects().get(0); 763 Entity entity2 = (Entity)listSupport.getAListOfEntityObjects().get(1); 764 765 assertNotNull(entity1); 766 assertEquals(CustomerEntityImpl.class, entity1.getClass()); 767 768 assertNotNull(entity2); 769 assertEquals(OrderEntityImpl.class, entity2.getClass()); 770 } 771 772 public void testMapSupport() { 773 774 Reader script = new StringReader("" + 775 "<container>\n" + 776 " <component-implementation class='" + MapSupport.class.getName() + "'>" + 777 " <parameter empty-collection='false' component-value-type='" + Entity.class.getName() + "'/>" + 778 " </component-implementation>" + 779 " <component-implementation key='customer' class=\'" + CustomerEntityImpl.class.getName() + "\'/>" + 780 " <component-implementation key='order' class=\'" + OrderEntityImpl.class.getName() + "\'/>" + 781 "</container>"); 782 783 PicoContainer pico = buildContainer(script); 784 785 MapSupport mapSupport = (MapSupport) pico.getComponentInstanceOfType(MapSupport.class); 786 787 assertNotNull(mapSupport); 788 assertNotNull(mapSupport.getAMapOfEntities()); 789 assertEquals(2, mapSupport.getAMapOfEntities().size()); 790 791 Map aMapOfEntities = mapSupport.getAMapOfEntities(); 792 793 Entity entity1 = (Entity) aMapOfEntities.get("customer"); 794 Entity entity2 = (Entity) aMapOfEntities.get("order"); 795 796 assertNotNull(entity1); 797 assertEquals(CustomerEntityImpl.class, entity1.getClass()); 798 799 assertNotNull(entity2); 800 assertEquals(OrderEntityImpl.class, entity2.getClass()); 801 } 802 803 public void testNoEmptyCollectionWithComponentKeyTypeFailure() { 804 805 Reader script = new StringReader("" + 806 "<container>\n" + 807 " <component-implementation class='"+ MapSupport.class.getName()+ "'>" + 808 " <parameter empty-collection='false' component-key-type='"+Entity.class.getName()+"'/>" + 809 " </component-implementation>" + 810 " <component-implementation key='customer' class=\'"+CustomerEntityImpl.class.getName()+"\'/>" + 811 " <component-implementation key='order' class=\'"+OrderEntityImpl.class.getName()+"\'/>" + 812 "</container>"); 813 814 try { 815 buildContainer(script); 816 fail("Thrown " + PicoException.class.getName() + " expected"); 817 } catch (final PicoException e) { 818 assertTrue(e.getMessage().indexOf("one or both of the emptyCollection")>0); 819 } 820 } 821 822 public void testNoComponentValueTypeWithComponentKeyTypeFailure() { 823 824 Reader script = new StringReader("" + 825 "<container>\n" + 826 " <component-implementation class='"+ MapSupport.class.getName()+ "'>" + 827 " <parameter component-value-type='"+Entity.class.getName()+"' component-key-type='"+Entity.class.getName()+"'/>" + 828 " </component-implementation>" + 829 " <component-implementation key='customer' class=\'"+CustomerEntityImpl.class.getName()+"\'/>" + 830 " <component-implementation key='order' class=\'"+OrderEntityImpl.class.getName()+"\'/>" + 831 "</container>"); 832 833 try { 834 buildContainer(script); 835 fail("Thrown " + PicoException.class.getName() + " expected"); 836 } catch (final PicoException e) { 837 assertTrue(e.getMessage().indexOf("but one or both of the emptyCollection")>0); 838 } 839 } 840 841 public void testNoEmptyCollectionWithComponentValueTypeFailure() { 842 843 Reader script = new StringReader("" + 844 "<container>\n" + 845 " <component-implementation class='"+ MapSupport.class.getName()+ "'>" + 846 " <parameter component-value-type='"+Entity.class.getName()+"'/>" + 847 " </component-implementation>" + 848 " <component-implementation key='customer' class=\'"+CustomerEntityImpl.class.getName()+"\'/>" + 849 " <component-implementation key='order' class=\'"+OrderEntityImpl.class.getName()+"\'/>" + 850 "</container>"); 851 852 try { 853 buildContainer(script); 854 fail("Thrown " + PicoException.class.getName() + " expected"); 855 } catch (final PicoException e) { 856 System.out.println(e); 857 858 assertTrue(e.getMessage().indexOf("but the emptyCollection () was empty or null")>0); 859 } 860 } 861 862 private PicoContainer buildContainer(Reader script) { 863 return buildContainer(new XMLContainerBuilder(script, getClass().getClassLoader()), null, "SOME_SCOPE"); 864 } 865 866 static public class StaticWriterComponentMonitor extends WriterComponentMonitor { 867 static Writer WRITER = new StringWriter(); 868 869 public StaticWriterComponentMonitor() { 870 super(WRITER); 871 } 872 873 } 874 875 static private class PrivateComponent { 876 } 877 878 // TODO: Move this into pico-tck as soon as nano is dependend on a pico snapshot again ... 879 public static class WrapsTouchable implements Touchable { 880 private final Touchable wrapped; 881 882 public WrapsTouchable(final Touchable wrapped) { 883 this.wrapped = wrapped; 884 } 885 886 public void touch() { 887 this.wrapped.touch(); 888 } 889 } 890 } 891