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