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