1 8 package com.tirsen.nanning; 9 10 import java.io.IOException ; 11 import java.io.ObjectInputStream ; 12 import java.io.Serializable ; 13 import java.lang.reflect.InvocationHandler ; 14 import java.lang.reflect.Method ; 15 import java.lang.reflect.Proxy ; 16 import java.util.ArrayList ; 17 import java.util.Collections ; 18 import java.util.HashMap ; 19 import java.util.HashSet ; 20 import java.util.Iterator ; 21 import java.util.LinkedHashSet ; 22 import java.util.List ; 23 import java.util.Map ; 24 import java.util.Set ; 25 26 import org.apache.commons.collections.CollectionUtils; 27 import org.apache.commons.collections.Transformer; 28 29 47 public final class AspectInstance implements InvocationHandler , Serializable { 48 static final long serialVersionUID = 5462785783512485056L; 49 50 private Map mixins = new HashMap (); 51 private List mixinsList = new ArrayList (); 52 private Class classIdentifier; 53 54 private Object proxy; 55 private transient List constructionInterceptors = new ArrayList (); 56 private transient AspectFactory aspectFactory; 57 58 public AspectInstance() { 59 } 60 61 public AspectInstance(AspectFactory aspectFactory, Class classIdentifier) { 62 this.aspectFactory = aspectFactory; 63 this.classIdentifier = classIdentifier; 64 } 65 66 public AspectInstance(Class classIdentifier) { 67 this.classIdentifier = classIdentifier; 68 } 69 70 public Object createProxy(boolean runConstructionInterceptors) { 71 if (proxy == null) { 72 Set interfaces = getInterfaceClasses(); 73 proxy = Proxy.newProxyInstance(getClass().getClassLoader(), 74 (Class []) interfaces.toArray(new Class [0]), 75 this); 76 } 77 if (runConstructionInterceptors) { 78 proxy = executeConstructionInterceptors(proxy); 79 } 80 return proxy; 81 } 82 83 private Set getInterfaceClasses() { 84 Set interfaces = new HashSet (CollectionUtils.collect(mixins.values(), new Transformer() { 85 public Object transform(Object o) { 86 return ((MixinInstance) o).getInterfaceClass(); 87 } 88 })); 89 if (classIdentifier != null) { 90 interfaces.add(classIdentifier); 91 } 92 return interfaces; 93 } 94 95 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 96 97 Class interfaceClass = method.getDeclaringClass(); 98 99 if (interfaceClass != Object .class) { 100 Object prevThis = Aspects.getThis(); 101 try { 102 Aspects.setThis(proxy); 103 MixinInstance mixin = getMixinForInterface(interfaceClass); 104 return mixin.invokeMethod(proxy, method, args); 105 } finally { 106 Aspects.setThis(prevThis); 107 } 108 109 } else { 110 if (args != null) { 113 for (int i = 0; i < args.length; i++) { 114 Object arg = args[i]; 115 if (Aspects.isAspectObject(arg)) { 116 args[i] = Aspects.getAspectInstance(arg); 117 } 118 } 119 } 120 return method.invoke(this, args); 121 } 122 } 123 124 Object getTarget(Class interfaceClass) { 125 MixinInstance interfaceInstance = getMixinForInterface(interfaceClass); 126 return interfaceInstance.getTarget(); 127 } 128 129 Set getInterceptors(Class interfaceClass) { 130 MixinInstance interfaceInstance = getMixinForInterface(interfaceClass); 131 return interfaceInstance.getAllInterceptors(); 132 } 133 134 139 public MixinInstance getMixinForInterface(Class interfaceClass) { 140 MixinInstance mixinInstance = (MixinInstance) mixins.get(interfaceClass); 141 assert mixinInstance != null : "there is no mixin for interface " + interfaceClass + " mixins were " + mixins; 142 return mixinInstance; 143 } 144 145 public boolean hasMixinForInterface(Class interfaceClass) { 146 return mixins.containsKey(interfaceClass); 147 } 148 149 public void setTarget(Class interfaceClass, Object target) { 150 MixinInstance mixinInstance = getMixinForInterface(interfaceClass); 151 mixinInstance.setTarget(target); 152 } 153 154 public Object [] getTargets() { 155 return CollectionUtils.collect(mixinsList, new Transformer() { 156 public Object transform(Object o) { 157 return ((MixinInstance) o).getTarget(); 158 } 159 }).toArray(); 160 } 161 162 private void readObject(ObjectInputStream objectInputStream) throws IOException , ClassNotFoundException { 163 objectInputStream.defaultReadObject(); 164 AspectFactory currentAspectFactory = Aspects.getCurrentAspectFactory(); 165 assert currentAspectFactory != null : "context AspectFactory not specified, it is not possible to deserialize " + this; 166 aspectFactory = currentAspectFactory; 167 aspectFactory.reinitialize(this); 168 } 169 170 public Class getClassIdentifier() { 171 return classIdentifier; 172 } 173 174 178 public void addMixin(MixinInstance mixin) { 179 assert proxy == null : "Can't addMixin mixins when proxy has been created."; 180 Class interfaceClass = mixin.getInterfaceClass(); 181 bindMixinToInterface(interfaceClass, mixin); 182 mixinsList.add(mixin); 183 } 184 185 186 public void setMixins(List mixinsList) { 187 this.mixinsList = mixinsList; 188 mixins.clear(); 189 for (Iterator i = mixinsList.iterator(); i.hasNext();) { 190 MixinInstance mixinInstance = (MixinInstance) i.next(); 191 bindMixinToInterface(mixinInstance.getInterfaceClass(), mixinInstance); 192 } 193 } 194 195 201 private void bindMixinToInterface(Class interfaceClass, MixinInstance mixinInstance) { 202 mixins.put(interfaceClass, mixinInstance); 203 Class superclass = interfaceClass.getSuperclass(); 204 if (superclass != null) { 205 bindMixinToInterface(superclass, mixinInstance); 206 } 207 Class [] interfaces = interfaceClass.getInterfaces(); 208 if (interfaces != null) { 209 for (int i = 0; i < interfaces.length; i++) { 210 Class anInterface = interfaces[i]; 211 bindMixinToInterface(anInterface, mixinInstance); 212 } 213 } 214 } 215 216 221 public Set getAllInterceptors() { 222 Set result = new LinkedHashSet (); 223 if (constructionInterceptors != null) { 224 result.addAll(constructionInterceptors); 225 } 226 227 for (Iterator mixinIterator = mixinsList.iterator(); mixinIterator.hasNext();) { 228 MixinInstance mixinInstance = (MixinInstance) mixinIterator.next(); 229 Set allInterceptors = mixinInstance.getAllInterceptors(); 230 for (Iterator interceptorIterator = allInterceptors.iterator(); interceptorIterator.hasNext();) { 231 Interceptor interceptor = (Interceptor) interceptorIterator.next(); 232 result.add(interceptor); 233 } 234 } 235 return result; 236 } 237 238 244 public List getInterceptorsForMethod(Method method) { 245 return getMixinForInterface(method.getDeclaringClass()).getInterceptorsForMethod(method); 246 } 247 248 252 public final AspectFactory getAspectFactory() { 253 return aspectFactory; 254 } 255 256 public final class ConstructionInvocationImpl implements ConstructionInvocation { 257 private Object proxy; 258 private Class interfaceClass; 259 260 public ConstructionInvocationImpl(Object proxy, Class interfaceClass) { 261 this.proxy = proxy; 262 this.interfaceClass = interfaceClass; 263 } 264 265 public Object getProxy() { 266 return proxy; 267 } 268 269 public Object getTarget() { 270 return Aspects.getTarget(proxy, interfaceClass); 271 } 272 273 public void setTarget(Object target) { 274 Aspects.setTarget(proxy, interfaceClass, target); 275 } 276 } 277 278 public Object getProxy() { 279 return createProxy(true); 280 } 281 282 private Object executeConstructionInterceptors(Object proxy) { 283 Object prevThis = Aspects.getThis(); 284 try { 285 Aspects.setThis(proxy); 286 287 if (constructionInterceptors != null) { 288 for (Iterator iterator = constructionInterceptors.iterator(); iterator.hasNext();) { 289 ConstructionInterceptor constructionInterceptor = (ConstructionInterceptor) iterator.next(); 290 if (constructionInterceptor.interceptsConstructor(getClassIdentifier())) { 291 proxy = constructionInterceptor.construct(new ConstructionInvocationImpl(proxy, getClassIdentifier())); 292 } 293 } 294 } 295 296 } finally { 297 constructionInterceptors = null; 298 Aspects.setThis(prevThis); 299 } 300 return proxy; 301 } 302 303 public String toString() { 304 if (mixinsList.size() == 1) { 305 return "aspect{" + mixinsList.get(0).toString() + "}"; 306 } 307 return "aspect{class=" + classIdentifier + "," + 308 "mixins=" + mixinsList + "}"; 309 } 310 311 315 public List getMixins() { 316 return Collections.unmodifiableList(mixinsList); 317 } 318 319 322 public void addConstructionInterceptor(ConstructionInterceptor constructionInterceptor) { 323 if (constructionInterceptors == null) { 324 constructionInterceptors = new ArrayList (); 325 } 326 constructionInterceptors.add(constructionInterceptor); 327 } 328 329 public void addInterceptor(Interceptor interceptor) { 330 for (Iterator iterator = mixinsList.iterator(); iterator.hasNext();) { 331 MixinInstance mixin = (MixinInstance) iterator.next(); 332 mixin.addInterceptor(interceptor); 333 } 334 } 335 } 336 | Popular Tags |