001    /*****************************************************************************
002     * Copyright (C) PicoContainer 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                                                          *
009     *****************************************************************************/
010    package org.picocontainer.behaviors;
011    
012    import static org.junit.Assert.assertEquals;
013    import static org.junit.Assert.assertFalse;
014    import static org.junit.Assert.assertNotNull;
015    import static org.junit.Assert.assertSame;
016    import static org.junit.Assert.assertTrue;
017    
018    import java.util.Enumeration;
019    import java.util.HashMap;
020    import java.util.Map;
021    import java.util.Properties;
022    
023    import org.junit.Test;
024    import org.picocontainer.Characteristics;
025    import org.picocontainer.ComponentAdapter;
026    import org.picocontainer.adapters.InstanceAdapter;
027    import org.picocontainer.annotations.Cache;
028    import org.picocontainer.containers.EmptyPicoContainer;
029    import org.picocontainer.injectors.SetterInjector;
030    import org.picocontainer.lifecycle.NullLifecycleStrategy;
031    import org.picocontainer.monitors.NullComponentMonitor;
032    
033    import com.thoughtworks.xstream.XStream;
034    
035    @SuppressWarnings("serial")
036    public class AdaptingBehaviorTestCase {
037    
038        @Test public void testCachingBehaviorCanBeAddedByCharacteristics() {
039            AdaptingBehavior abf = new AdaptingBehavior();
040            Properties cc = new Properties();
041            mergeInto(Characteristics.CACHE,cc);
042            ComponentAdapter ca = abf.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, Map.class, HashMap.class);
043            assertTrue(ca instanceof Cached);
044            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
045            assertNotNull(map);
046            Map map2 = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
047            assertSame(map, map2);
048            assertEquals(0, cc.size());
049            assertEquals("Cached:ConstructorInjector-interface java.util.Map",ca.toString());
050        }
051    
052        @Test public void testCachingBehaviorCanBeAddedByAnnotation() {
053            AdaptingBehavior abf = new AdaptingBehavior();
054            Properties cc = new Properties();
055            ComponentAdapter ca = abf.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, Map.class, MyHashMap.class);
056            assertTrue(ca instanceof Cached);
057            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
058            assertNotNull(map);
059            Map map2 = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
060            assertSame(map, map2);
061            assertEquals(0, cc.size());
062            assertEquals("Cached:ConstructorInjector-interface java.util.Map",ca.toString());
063        }
064    
065        @Cache
066        public static class MyHashMap extends HashMap {
067            public MyHashMap() {
068            }
069        }
070    
071        public static class MyHashMap2 extends HashMap {
072            private String foo;
073    
074            public MyHashMap2() {
075            }
076            public void setFoo(String foo) {
077                this.foo = foo;
078            }
079        }
080    
081        @Test public void testImplementationHidingBehaviorCanBeAddedByCharacteristics() {
082            AdaptingBehavior abf = new AdaptingBehavior();
083            Properties cc = new Properties();
084            mergeInto(Characteristics.HIDE_IMPL,cc);
085            ComponentAdapter ca = abf.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, Map.class, HashMap.class);
086            assertTrue(ca instanceof HiddenImplementation);
087            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
088            assertNotNull(map);
089            assertTrue(!(map instanceof HashMap));
090    
091            assertEquals(0, cc.size());
092            assertEquals("Hidden:ConstructorInjector-interface java.util.Map",ca.toString());
093    
094        }
095    
096        @Test public void testPropertyApplyingBehaviorCanBeAddedByCharacteristics() {
097            AdaptingBehavior abf = new AdaptingBehavior();
098            Properties cc = new Properties();
099            mergeInto(Characteristics.PROPERTY_APPLYING,cc);
100            ComponentAdapter ca = abf.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, Map.class, MyHashMap2.class);
101            assertTrue(ca instanceof PropertyApplicator);
102            PropertyApplicator pa = (PropertyApplicator)ca;
103            pa.setProperty("foo", "bar");
104            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
105            assertNotNull(map);
106            assertTrue(map instanceof HashMap);
107            assertTrue(map instanceof MyHashMap2);
108            assertEquals("bar", ((MyHashMap2) map).foo);
109    
110            assertEquals(0, cc.size());
111            assertEquals("PropertyApplied:ConstructorInjector-interface java.util.Map",ca.toString());
112    
113        }
114    
115        @Test public void testSetterInjectionCanBeTriggereedMeaningAdaptiveInjectorIsUsed() {
116            AdaptingBehavior abf = new AdaptingBehavior();
117            Properties cc = new Properties();
118            mergeInto(Characteristics.SDI,cc);
119            ComponentAdapter ca = abf.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, Map.class, HashMap.class);
120            assertTrue(ca instanceof SetterInjector);
121            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
122            assertNotNull(map);
123            assertEquals(0, cc.size());
124            assertEquals("SetterInjector-interface java.util.Map",ca.toString());
125    
126        }
127    
128        @Test public void testCachingAndImplHidingAndThreadSafetySetupCorrectly() {
129            AdaptingBehavior abf = new AdaptingBehavior();
130            Properties cc = new Properties();
131            mergeInto(Characteristics.CACHE,cc);
132            mergeInto(Characteristics.HIDE_IMPL,cc);
133            mergeInto(Characteristics.SYNCHRONIZE,cc);
134            ComponentAdapter ca = abf.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, Map.class, HashMap.class);
135            assertTrue(ca instanceof Cached);
136            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), null);
137            assertNotNull(map);
138            assertTrue(!(map instanceof HashMap));
139    
140            XStream xs = new XStream();
141            String foo = xs.toXML(ca);
142    
143            int ih = foo.indexOf(HiddenImplementation.class.getName());
144            int sb = foo.indexOf(Synchronized.class.getName());
145    
146            // check right nesting order
147            assertTrue(ih>0);
148            assertTrue(sb>0);
149            assertTrue(sb>ih);
150    
151            assertEquals(0, cc.size());
152            assertEquals("Cached:Hidden:Synchronized:ConstructorInjector-interface java.util.Map",ca.toString());
153    
154            
155    
156    
157        }
158    
159        @Test public void testCachingAndImplHidingAndThreadSafetySetupCorrectlyForExtraCaching() {
160            Caching cbf = new Caching();
161            AdaptingBehavior abf = new AdaptingBehavior();
162            cbf.wrap(abf);
163            Properties cc = new Properties();
164            mergeInto(Characteristics.CACHE,cc);
165            mergeInto(Characteristics.HIDE_IMPL,cc);
166            mergeInto(Characteristics.SYNCHRONIZE,cc);
167            ComponentAdapter ca = cbf.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, Map.class, HashMap.class);
168            assertTrue(ca instanceof Cached);
169            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
170            assertNotNull(map);
171            assertTrue(!(map instanceof HashMap));
172    
173            XStream xs = new XStream();
174            String foo = xs.toXML(ca);
175    
176            assertTrue(foo.indexOf("<" + Cached.class.getName() + ">", 0)  > -1);  // xml does start with CB
177            assertFalse(foo.indexOf("<" + Cached.class.getName() + ">", 1)  > -1); // but only contains it once.
178            assertEquals("Cached:Hidden:Synchronized:ConstructorInjector-interface java.util.Map",ca.toString());
179    
180        }
181    
182        @Test public void testCachingAndImplHidingAndThreadSafetySetupCorrectlyForExtraCachingForAdapter() {
183            Caching cbf = new Caching();
184            AdaptingBehavior abf = new AdaptingBehavior();
185            cbf.wrap(abf);
186            Properties cc = new Properties();
187            mergeInto(Characteristics.CACHE,cc);
188            mergeInto(Characteristics.HIDE_IMPL,cc);
189            mergeInto(Characteristics.SYNCHRONIZE,cc);
190            ComponentAdapter ca = cbf.addComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), cc, new InstanceAdapter(Map.class, new HashMap(), new NullLifecycleStrategy(), new NullComponentMonitor()));
191            assertTrue(ca instanceof Cached);
192            Map map = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
193            assertNotNull(map);
194            assertTrue(!(map instanceof HashMap));
195    
196            XStream xs = new XStream();
197            String foo = xs.toXML(ca);
198    
199            assertTrue(foo.indexOf("<" + Cached.class.getName() + ">", 0)  > -1);  // xml does start with CB
200            assertFalse(foo.indexOf("<" + Cached.class.getName() + ">", 1)  > -1); // but only contains it once.
201            assertEquals("Cached:Hidden:Synchronized:Instance-interface java.util.Map",ca.toString());
202    
203        }
204    
205    
206    
207        public void mergeInto(Properties p, Properties into) {
208            Enumeration e = p.propertyNames();
209            while (e.hasMoreElements()) {
210                String s = (String)e.nextElement();
211                into.setProperty(s, p.getProperty(s));
212            }
213    
214        }
215    
216    
217    }