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