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