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