001
014
015 package com.liferay.portal.spring.aop;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.util.ArrayUtil;
020 import com.liferay.portal.kernel.util.ProxyUtil;
021
022 import java.lang.annotation.Annotation;
023 import java.lang.annotation.ElementType;
024 import java.lang.annotation.Target;
025 import java.lang.reflect.Field;
026 import java.lang.reflect.InvocationHandler;
027 import java.lang.reflect.Method;
028
029 import java.util.ArrayList;
030 import java.util.Iterator;
031 import java.util.List;
032
033 import org.aopalliance.intercept.MethodInterceptor;
034
035 import org.springframework.aop.SpringProxy;
036 import org.springframework.aop.TargetSource;
037 import org.springframework.aop.framework.AdvisedSupport;
038 import org.springframework.aop.framework.AdvisorChainFactory;
039 import org.springframework.aop.framework.AopProxy;
040 import org.springframework.aop.framework.AopProxyUtils;
041 import org.springframework.util.ClassUtils;
042
043
046 public class ServiceBeanAopProxy implements AopProxy, InvocationHandler {
047
048 public static AdvisedSupport getAdvisedSupport(Object proxy)
049 throws Exception {
050
051 InvocationHandler invocationHandler = ProxyUtil.getInvocationHandler(
052 proxy);
053
054 Class<?> invocationHandlerClass = invocationHandler.getClass();
055
056 Field advisedSupportField = invocationHandlerClass.getDeclaredField(
057 "_advisedSupport");
058
059 advisedSupportField.setAccessible(true);
060
061 return (AdvisedSupport)advisedSupportField.get(invocationHandler);
062 }
063
064 public ServiceBeanAopProxy(
065 AdvisedSupport advisedSupport, MethodInterceptor methodInterceptor,
066 ServiceBeanAopCacheManager serviceBeanAopCacheManager) {
067
068 _advisedSupport = advisedSupport;
069 _advisorChainFactory = _advisedSupport.getAdvisorChainFactory();
070
071 Class<?>[] proxyInterfaces = _advisedSupport.getProxiedInterfaces();
072
073 _mergeSpringMethodInterceptors = !ArrayUtil.contains(
074 proxyInterfaces, SpringProxy.class);
075
076 ArrayList<MethodInterceptor> classLevelMethodInterceptors =
077 new ArrayList<MethodInterceptor>();
078 ArrayList<MethodInterceptor> fullMethodInterceptors =
079 new ArrayList<MethodInterceptor>();
080
081 while (true) {
082 if (!(methodInterceptor instanceof ChainableMethodAdvice)) {
083 classLevelMethodInterceptors.add(methodInterceptor);
084 fullMethodInterceptors.add(methodInterceptor);
085
086 break;
087 }
088
089 ChainableMethodAdvice chainableMethodAdvice =
090 (ChainableMethodAdvice)methodInterceptor;
091
092 chainableMethodAdvice.setServiceBeanAopCacheManager(
093 serviceBeanAopCacheManager);
094
095 if (methodInterceptor instanceof AnnotationChainableMethodAdvice) {
096 AnnotationChainableMethodAdvice<?>
097 annotationChainableMethodAdvice =
098 (AnnotationChainableMethodAdvice<?>)methodInterceptor;
099
100 Class<? extends Annotation> annotationClass =
101 annotationChainableMethodAdvice.getAnnotationClass();
102
103 Target target = annotationClass.getAnnotation(Target.class);
104
105 if (target == null) {
106 classLevelMethodInterceptors.add(methodInterceptor);
107 }
108 else {
109 for (ElementType elementType : target.value()) {
110 if (elementType == ElementType.TYPE) {
111 classLevelMethodInterceptors.add(methodInterceptor);
112
113 break;
114 }
115 }
116 }
117 }
118 else {
119 classLevelMethodInterceptors.add(methodInterceptor);
120 }
121
122 fullMethodInterceptors.add(methodInterceptor);
123
124 methodInterceptor = chainableMethodAdvice.nextMethodInterceptor;
125 }
126
127 classLevelMethodInterceptors.trimToSize();
128
129 _classLevelMethodInterceptors = classLevelMethodInterceptors;
130 _fullMethodInterceptors = fullMethodInterceptors;
131
132 _serviceBeanAopCacheManager = serviceBeanAopCacheManager;
133 }
134
135 @Override
136 public Object getProxy() {
137 return getProxy(ClassUtils.getDefaultClassLoader());
138 }
139
140 @Override
141 public Object getProxy(ClassLoader classLoader) {
142 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(
143 _advisedSupport);
144
145 InvocationHandler invocationHandler = _pacl.getInvocationHandler(
146 this, _advisedSupport);
147
148 return ProxyUtil.newProxyInstance(
149 classLoader, proxiedInterfaces, invocationHandler);
150 }
151
152 @Override
153 public Object invoke(Object proxy, Method method, Object[] arguments)
154 throws Throwable {
155
156 TargetSource targetSource = _advisedSupport.getTargetSource();
157
158 Object target = null;
159
160 try {
161 Class<?> targetClass = null;
162
163 target = targetSource.getTarget();
164
165 if (target != null) {
166 targetClass = target.getClass();
167 }
168
169 ServiceBeanMethodInvocation serviceBeanMethodInvocation =
170 new ServiceBeanMethodInvocation(
171 target, targetClass, method, arguments);
172
173 _setMethodInterceptors(serviceBeanMethodInvocation);
174
175 return serviceBeanMethodInvocation.proceed();
176 }
177 finally {
178 if ((target != null) && !targetSource.isStatic()) {
179 targetSource.releaseTarget(target);
180 }
181 }
182 }
183
184 public static interface PACL {
185
186 public InvocationHandler getInvocationHandler(
187 InvocationHandler invocationHandler, AdvisedSupport advisedSupport);
188
189 }
190
191 private List<MethodInterceptor> _getMethodInterceptors(
192 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
193
194 List<MethodInterceptor> methodInterceptors =
195 new ArrayList<MethodInterceptor>(_fullMethodInterceptors);
196
197 if (!_mergeSpringMethodInterceptors) {
198 return methodInterceptors;
199 }
200
201 List<Object> list =
202 _advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
203 _advisedSupport, serviceBeanMethodInvocation.getMethod(),
204 serviceBeanMethodInvocation.getTargetClass());
205
206 Iterator<Object> itr = list.iterator();
207
208 while (itr.hasNext()) {
209 Object obj = itr.next();
210
211 if (obj instanceof MethodInterceptor) {
212 continue;
213 }
214
215 if (_log.isWarnEnabled()) {
216 _log.warn(
217 "Skipping unsupported interceptor type " + obj.getClass());
218 }
219
220 itr.remove();
221 }
222
223 if (list.isEmpty()) {
224 return methodInterceptors;
225 }
226
227 for (Object object : list) {
228 methodInterceptors.add((MethodInterceptor)object);
229 }
230
231 return methodInterceptors;
232 }
233
234 private void _setMethodInterceptors(
235 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
236
237 MethodInterceptorsBag methodInterceptorsBag =
238 _serviceBeanAopCacheManager.getMethodInterceptorsBag(
239 serviceBeanMethodInvocation);
240
241 if (methodInterceptorsBag == null) {
242 List<MethodInterceptor> methodInterceptors = _getMethodInterceptors(
243 serviceBeanMethodInvocation);
244
245 methodInterceptorsBag = new MethodInterceptorsBag(
246 _classLevelMethodInterceptors, methodInterceptors);
247
248 _serviceBeanAopCacheManager.putMethodInterceptorsBag(
249 serviceBeanMethodInvocation.toCacheKeyModel(),
250 methodInterceptorsBag);
251 }
252
253 serviceBeanMethodInvocation.setMethodInterceptors(
254 methodInterceptorsBag.getMergedMethodInterceptors());
255 }
256
257 private static Log _log = LogFactoryUtil.getLog(ServiceBeanAopProxy.class);
258
259 private static PACL _pacl = new NoPACL();
260
261 private AdvisedSupport _advisedSupport;
262 private AdvisorChainFactory _advisorChainFactory;
263 private final List<MethodInterceptor> _classLevelMethodInterceptors;
264 private final List<MethodInterceptor> _fullMethodInterceptors;
265 private boolean _mergeSpringMethodInterceptors;
266 private ServiceBeanAopCacheManager _serviceBeanAopCacheManager;
267
268 private static class NoPACL implements PACL {
269
270 @Override
271 public InvocationHandler getInvocationHandler(
272 InvocationHandler invocationHandler,
273 AdvisedSupport advisedSupport) {
274
275 return invocationHandler;
276 }
277
278 }
279
280 }