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 *****************************************************************************/
010package org.picocontainer.behaviors;
011
012import com.thoughtworks.xstream.XStream;
013import org.junit.Test;
014import org.picocontainer.Characteristics;
015import org.picocontainer.ComponentAdapter;
016import org.picocontainer.adapters.InstanceAdapter;
017import org.picocontainer.annotations.Cache;
018import org.picocontainer.containers.EmptyPicoContainer;
019import org.picocontainer.injectors.SetterInjector;
020import org.picocontainer.lifecycle.NullLifecycleStrategy;
021import org.picocontainer.monitors.NullComponentMonitor;
022
023import java.util.Enumeration;
024import java.util.HashMap;
025import java.util.Map;
026import java.util.Properties;
027
028import static org.junit.Assert.assertEquals;
029import static org.junit.Assert.assertFalse;
030import static org.junit.Assert.assertNotNull;
031import static org.junit.Assert.assertSame;
032import static org.junit.Assert.assertTrue;
033
034@SuppressWarnings("serial")
035public 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(), ComponentAdapter.NOTHING.class);
044        assertNotNull(map);
045        Map map2 = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
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(), ComponentAdapter.NOTHING.class);
057        assertNotNull(map);
058        Map map2 = (Map)ca.getComponentInstance(new EmptyPicoContainer(), ComponentAdapter.NOTHING.class);
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(), ComponentAdapter.NOTHING.class);
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(), ComponentAdapter.NOTHING.class);
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(), ComponentAdapter.NOTHING.class);
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(), null);
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(), ComponentAdapter.NOTHING.class);
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(), ComponentAdapter.NOTHING.class);
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-of 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}