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 }