1 /*************************************************
2 * Copyright (c) Shen Li. All rights reserved. *
3 * http://joyaop.sourceforge.net *
4 * -------------------------------------------- *
5 * Distributable under LGPL license. *
6 * See terms of license at gnu.org. *
7 ************************************************/
8 package net.sf.joyaop.impl;
9
10 import net.sf.cglib.proxy.Callback;
11 import net.sf.cglib.proxy.CallbackFilter;
12 import net.sf.cglib.proxy.Dispatcher;
13 import net.sf.cglib.proxy.Enhancer;
14 import net.sf.cglib.proxy.Factory;
15 import net.sf.cglib.proxy.MethodInterceptor;
16 import net.sf.cglib.proxy.MethodProxy;
17 import net.sf.cglib.proxy.NoOp;
18 import net.sf.joyaop.AbstractInterceptor;
19 import net.sf.joyaop.AspectRuntimeException;
20 import net.sf.joyaop.framework.AspectFactory;
21 import net.sf.joyaop.util.ClassUtils;
22
23 import java.io.Serializable;
24 import java.lang.reflect.Method;
25 import java.lang.reflect.Modifier;
26
27 /***
28 * The default instantiation strategy for the aspects.
29 * Other implementations could subclass it.
30 *
31 * @author Shen Li
32 */
33 public class DefaultAspectFactory implements AspectFactory {
34 private static final Class[] interfaceClasses = new Class[]{AspectProxy.class};
35
36 public Object newInstance(Class implementationClass) {
37 return newInstance(implementationClass, new Class[0], new Object[0]);
38 }
39
40 public Object newInstance(Class implementaionClass, Class[] argTypes, Object[] args) {
41 if (!Modifier.isAbstract(implementaionClass.getModifiers())) {
42 return ClassUtils.newInstance(implementaionClass, argTypes, args);
43 }
44 Factory factory = ClassUtils.getProxyFactory(implementaionClass);
45 if (factory == null) {
46 CallbackFilter callbackFilter = new CallbackFilterImpl(implementaionClass);
47 Enhancer enhancer = new Enhancer();
48 enhancer.setSuperclass(implementaionClass);
49 enhancer.setInterfaces(interfaceClasses);
50 enhancer.setClassLoader(ClassUtils.getClassLoader());
51 enhancer.setCallbacks(new Callback[]{
52 new SelfCallback(),
53 new ProxyCallback(),
54 new GetterCallback(),
55 CallbackFactory.forAspectProxy(interfaceClasses, callbackFilter).getCallback(null),
56 new AbstractInterceptorCallback()
57 });
58 enhancer.setCallbackFilter(callbackFilter);
59 factory = (Factory) enhancer.create(argTypes, args);
60 ClassUtils.putProxyFactory(implementaionClass, factory);
61 return factory;
62 }
63 return factory.newInstance(argTypes, args, factory.getCallbacks());
64 }
65
66 private static class GetterCallback implements MethodInterceptor, Serializable {
67 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
68 String name = method.getName();
69 if (!name.startsWith("get")) {
70 throw new AspectRuntimeException();
71 }
72 Object proxy = InvocationImpl.getCurrentInvocation().getProxy();
73 if (method.getReturnType().isAssignableFrom(proxy.getClass())) {
74 return proxy;
75 }
76 if (name.length() > 3) {
77 name = new StringBuffer(name.length() - 3)
78 .append(name.substring(3, 4).toLowerCase())
79 .append(name.substring(4)).toString();
80 return InvocationImpl.getCurrentInvocation().getParameter(name);
81
82 }
83 throw new AspectRuntimeException("Method " + method.getName() + " is not a getter method.");
84 }
85 }
86
87 private static class ProxyCallback implements Dispatcher, Serializable {
88 public Object loadObject() throws Exception {
89 return InvocationImpl.getCurrentInvocation().getProxy();
90 }
91 }
92
93 private static class AbstractInterceptorCallback implements Dispatcher, Serializable {
94 public Object loadObject() throws Exception {
95 return InvocationImpl.getCurrentInvocation();
96 }
97 }
98
99 private static class SelfCallback implements NoOp, Serializable {
100 }
101
102 private static class CallbackFilterImpl implements CallbackFilter, Serializable {
103 private Class implementationClass;
104
105 public CallbackFilterImpl(Class implementationClass) {
106 this.implementationClass = implementationClass;
107 }
108
109 public int accept(Method method) {
110
111 if (!Modifier.isAbstract(method.getModifiers())) {
112 return 0;
113 }
114 Class clazz = method.getDeclaringClass();
115 if (implementationClass == clazz) {
116 if (method.getName().startsWith("get")) {
117 return 2;
118 } else {
119 throw new AspectRuntimeException();
120 }
121 } else if (AspectProxy.class == clazz) {
122 return 3;
123 } else if (clazz.isAssignableFrom(AbstractInterceptor.class)) {
124 return 4;
125 } else {
126 return 1;
127 }
128 }
129 }
130 }