1 package org.picocontainer.gems; 2 3 import com.thoughtworks.proxy.factory.CglibProxyFactory; 4 import com.thoughtworks.proxy.toys.hotswap.Swappable; 5 import org.picocontainer.MutablePicoContainer; 6 import org.picocontainer.defaults.CachingComponentAdapter; 7 import org.picocontainer.defaults.CachingComponentAdapterFactory; 8 import org.picocontainer.defaults.ComponentAdapterFactory; 9 import org.picocontainer.defaults.ConstructorInjectionComponentAdapter; 10 import org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory; 11 import org.picocontainer.defaults.DefaultComponentAdapterFactory; 12 import org.picocontainer.defaults.DefaultPicoContainer; 13 import org.picocontainer.tck.AbstractComponentAdapterFactoryTestCase; 14 15 import java.io.Serializable ; 16 import java.util.ArrayList ; 17 import java.util.Collection ; 18 import java.util.List ; 19 20 public class HotSwappingComponentAdapterFactoryTestCase extends AbstractComponentAdapterFactoryTestCase { 21 private HotSwappingComponentAdapterFactory implementationHidingComponentAdapterFactory = new HotSwappingComponentAdapterFactory(new DefaultComponentAdapterFactory()); 22 private CachingComponentAdapterFactory cachingComponentAdapterFactory = new CachingComponentAdapterFactory(implementationHidingComponentAdapterFactory); 23 24 public void testComponentRegisteredWithInterfaceKeyOnlyImplementsThatInterfaceUsingStandardProxyfactory() { 25 DefaultPicoContainer pico = new DefaultPicoContainer(new HotSwappingComponentAdapterFactory(new ConstructorInjectionComponentAdapterFactory())); 26 pico.registerComponentImplementation(Collection .class, ArrayList .class); 27 Object collection = pico.getComponentInstance(Collection .class); 28 assertTrue(collection instanceof Collection ); 29 assertFalse(collection instanceof List ); 30 assertFalse(collection instanceof ArrayList ); 31 } 32 33 public void testComponentRegisteredWithOtherKeyImplementsAllInterfacesUsingStandardProxyFactory() { 34 DefaultPicoContainer pico = new DefaultPicoContainer(new HotSwappingComponentAdapterFactory(new ConstructorInjectionComponentAdapterFactory())); 35 pico.registerComponentImplementation("list", ArrayList .class); 36 Object collection = pico.getComponentInstance("list"); 37 assertTrue(collection instanceof List ); 38 assertFalse(collection instanceof ArrayList ); 39 } 40 41 public void testComponentRegisteredWithInterfaceKeyOnlyImplementsThatInterfaceUsingCGLIBProxyfactory() { 42 DefaultPicoContainer pico = new DefaultPicoContainer(new HotSwappingComponentAdapterFactory(new ConstructorInjectionComponentAdapterFactory(), new CglibProxyFactory())); 43 pico.registerComponentImplementation(Collection .class, ArrayList .class); 44 Object collection = pico.getComponentInstance(Collection .class); 45 assertTrue(collection instanceof Collection ); 46 assertFalse(collection instanceof List ); 47 assertFalse(collection instanceof ArrayList ); 48 } 49 50 public void testComponentRegisteredWithOtherKeyImplementsAllInterfacesUsingCGLIBProxyFactory() { 51 DefaultPicoContainer pico = new DefaultPicoContainer(new HotSwappingComponentAdapterFactory(new ConstructorInjectionComponentAdapterFactory(), new CglibProxyFactory())); 52 pico.registerComponentImplementation("list", ArrayList .class); 53 Object collection = pico.getComponentInstance("list"); 54 assertTrue(collection instanceof Collection ); 55 assertTrue(collection instanceof List ); 56 assertTrue(collection instanceof ArrayList ); 57 assertTrue(collection.getClass().getSuperclass().equals(ArrayList .class)); 58 } 59 60 61 public static interface Man { 63 Woman getWoman(); 64 65 void kiss(); 66 67 boolean wasKissed(); 68 } 69 71 public static interface Woman { 73 Man getMan(); 74 } 75 77 public static interface SuperWoman extends Woman { 78 } 79 80 public static class Husband implements Man { 81 public final Woman partner; 82 private boolean wasKissed; 83 84 public Husband(Woman partner) { 85 this.partner = partner; 86 } 87 88 public Woman getWoman() { 89 return partner; 90 } 91 92 public void kiss() { 93 wasKissed = true; 94 } 95 96 public boolean wasKissed() { 97 return wasKissed; 98 } 99 } 100 101 public static class Wife implements SuperWoman { 102 public final Man partner; 103 104 public Wife(Man partner) { 105 this.partner = partner; 106 } 107 108 public Man getMan() { 109 return partner; 110 } 111 } 112 113 public void testLowLevelCheating() { 114 ComponentAdapterFactory caf = createComponentAdapterFactory(); 115 DefaultPicoContainer pico = new DefaultPicoContainer(caf); 116 117 CachingComponentAdapter wifeAdapter = (CachingComponentAdapter) caf.createComponentAdapter("wife", Wife.class, null); 118 CachingComponentAdapter husbandAdapter = (CachingComponentAdapter) caf.createComponentAdapter("husband", Husband.class, null); 119 120 pico.registerComponent(wifeAdapter); 121 pico.registerComponent(husbandAdapter); 122 123 Woman wife = (Woman) wifeAdapter.getComponentInstance(pico); 124 Man wifesMan = wife.getMan(); 125 wifesMan.kiss(); 126 Man man = (Man) husbandAdapter.getComponentInstance(pico); 127 assertTrue(man.wasKissed()); 128 129 assertSame(man, wife.getMan()); 130 assertSame(wife, man.getWoman()); 131 132 Man newMan = new Husband(null); 134 Man oldMan = (Man) ((Swappable) man).hotswap(newMan); 135 136 wife.getMan().kiss(); 137 assertTrue(newMan.wasKissed()); 138 assertNotSame(man, oldMan); 139 assertNotSame(oldMan, newMan); 140 assertNotSame(newMan, man); 141 142 assertFalse(man.hashCode() == oldMan.hashCode()); 143 assertFalse(oldMan.hashCode() == newMan.hashCode()); 144 assertFalse(newMan.hashCode() == man.hashCode()); 145 } 146 147 public void testHighLevelCheating() { 148 MutablePicoContainer pico = new DefaultPicoContainer(createComponentAdapterFactory()); 149 150 pico.registerComponentImplementation(Wife.class); 152 pico.registerComponentImplementation(Husband.class); 153 154 Woman wife = (Woman) pico.getComponentInstance(Wife.class); 155 Man man = (Man) pico.getComponentInstance(Husband.class); 156 157 assertSame(man, wife.getMan()); 158 assertSame(wife, man.getWoman()); 159 160 Man newMan = new Husband(null); 162 Man oldMan = (Man) ((Swappable) man).hotswap(newMan); 163 164 wife.getMan().kiss(); 165 assertFalse(oldMan.wasKissed()); 166 assertTrue(newMan.wasKissed()); 167 168 } 169 170 public void testBigamy() { 171 DefaultPicoContainer pico = new DefaultPicoContainer(new HotSwappingComponentAdapterFactory(new ConstructorInjectionComponentAdapterFactory())); 172 pico.registerComponentImplementation(Woman.class, Wife.class); 173 Woman firstWife = (Woman) pico.getComponentInstance(Woman.class); 174 Woman secondWife = (Woman) pico.getComponentInstance(Woman.class); 175 assertNotSame(firstWife, secondWife); 176 177 } 178 179 public static class Bad implements Serializable { 180 public Bad() { 181 throw new IllegalStateException ("HAHA"); 182 } 183 } 184 185 public void testIHCAFwithCTORandNoCaching() { 186 MutablePicoContainer pico = new DefaultPicoContainer(); 188 pico.registerComponent(new HotSwappingComponentAdapter(new ConstructorInjectionComponentAdapter("l", ArrayList .class))); 189 190 List list1 = (List ) pico.getComponentInstance("l"); 191 List list2 = (List ) pico.getComponentInstance("l"); 192 193 assertNotSame(list1, list2); 194 assertFalse(list1 instanceof ArrayList ); 195 196 list1.add("Hello"); 197 assertTrue(list1.contains("Hello")); 198 assertFalse(list2.contains("Hello")); 199 } 200 201 public void testSwappingViaSwappableInterface() { 202 MutablePicoContainer pico = new DefaultPicoContainer(); 203 pico.registerComponent(new HotSwappingComponentAdapter(new ConstructorInjectionComponentAdapter("l", ArrayList .class))); 204 List l = (List ) pico.getComponentInstance("l"); 205 l.add("Hello"); 206 final ArrayList newList = new ArrayList (); 207 ArrayList oldSubject = (ArrayList ) ((Swappable) l).hotswap(newList); 208 assertEquals("Hello", oldSubject.get(0)); 209 assertTrue(l.isEmpty()); 210 l.add("World"); 211 assertEquals("World", l.get(0)); 212 } 213 214 public interface OtherSwappable { 215 Object hotswap(Object newSubject); 216 } 217 218 public static class OtherSwappableImpl implements OtherSwappable { 219 public Object hotswap(Object newSubject) { 220 return "TADA"; 221 } 222 } 223 224 public void testInterferingSwapMethodsInComponentMasksHotSwappingFunctionality() { 225 MutablePicoContainer pico = new DefaultPicoContainer(); 226 pico.registerComponent(new HotSwappingComponentAdapter(new ConstructorInjectionComponentAdapter("os", OtherSwappableImpl.class))); 227 OtherSwappable os = (OtherSwappable) pico.getComponentInstance("os"); 228 OtherSwappable os2 = new OtherSwappableImpl(); 229 230 assertEquals("TADA", os.hotswap(os2)); 231 Swappable os_ = (Swappable) os; 232 assertEquals("TADA", os_.hotswap(os2)); 233 } 234 235 protected ComponentAdapterFactory createComponentAdapterFactory() { 236 return cachingComponentAdapterFactory; 237 } 238 239 public static class Yin { 240 private final Yang yang; 241 242 public Yin(Yang yang) { 243 this.yang = yang; 244 } 245 246 public Yang getYang() { 247 return yang; 248 } 249 } 250 251 public static class Yang { 252 private final Yin yin; 253 254 public Yang(Yin yin) { 255 this.yin = yin; 256 } 257 258 public Yin getYin() { 259 return yin; 260 } 261 } 262 263 public void testShouldBeAbleToHandleMutualDependenciesWithoutInterfaceImplSeparation() { 265 MutablePicoContainer pico = new DefaultPicoContainer(new CachingComponentAdapterFactory(new HotSwappingComponentAdapterFactory(new ConstructorInjectionComponentAdapterFactory(), 266 new CglibProxyFactory()))); 267 268 pico.registerComponentImplementation(Yin.class); 269 pico.registerComponentImplementation(Yang.class); 270 271 Yin yin = (Yin) pico.getComponentInstance(Yin.class); 272 Yang yang = (Yang) pico.getComponentInstance(Yang.class); 273 274 assertSame(yin, yang.getYin()); 275 assertSame(yang, yin.getYang()); 276 } 277 278 } 279 | Popular Tags |