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 public static interface PACL {
196
197 public InvocationHandler getInvocationHandler(
198 InvocationHandler invocationHandler, AdvisedSupport advisedSupport);
199
200 }
201
202 private List<MethodInterceptor> _getMethodInterceptors(
203 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
204
205 List<MethodInterceptor> methodInterceptors =
206 new ArrayList<MethodInterceptor>(_fullMethodInterceptors);
207
208 if (!_mergeSpringMethodInterceptors) {
209 return methodInterceptors;
210 }
211
212 List<Object> list =
213 _advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
214 _advisedSupport, serviceBeanMethodInvocation.getMethod(),
215 serviceBeanMethodInvocation.getTargetClass());
216
217 Iterator<Object> itr = list.iterator();
218
219 while (itr.hasNext()) {
220 Object obj = itr.next();
221
222 if (obj instanceof MethodInterceptor) {
223 continue;
224 }
225
226 if (_log.isWarnEnabled()) {
227 _log.warn(
228 "Skipping unsupported interceptor type " + obj.getClass());
229 }
230
231 itr.remove();
232 }
233
234 if (list.isEmpty()) {
235 return methodInterceptors;
236 }
237
238 for (Object object : list) {
239 methodInterceptors.add((MethodInterceptor)object);
240 }
241
242 return methodInterceptors;
243 }
244
245 private void _setMethodInterceptors(
246 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
247
248 MethodInterceptorsBag methodInterceptorsBag =
249 _serviceBeanAopCacheManager.getMethodInterceptorsBag(
250 serviceBeanMethodInvocation);
251
252 if (methodInterceptorsBag == null) {
253 List<MethodInterceptor> methodInterceptors = _getMethodInterceptors(
254 serviceBeanMethodInvocation);
255
256 methodInterceptorsBag = new MethodInterceptorsBag(
257 _classLevelMethodInterceptors, methodInterceptors);
258
259 _serviceBeanAopCacheManager.putMethodInterceptorsBag(
260 serviceBeanMethodInvocation.toCacheKeyModel(),
261 methodInterceptorsBag);
262 }
263
264 serviceBeanMethodInvocation.setMethodInterceptors(
265 methodInterceptorsBag.getMergedMethodInterceptors());
266 }
267
268 private static Log _log = LogFactoryUtil.getLog(ServiceBeanAopProxy.class);
269
270 private static PACL _pacl = new NoPACL();
271
272 private AdvisedSupport _advisedSupport;
273 private AdvisorChainFactory _advisorChainFactory;
274 private final List<MethodInterceptor> _classLevelMethodInterceptors;
275 private final List<MethodInterceptor> _fullMethodInterceptors;
276 private boolean _mergeSpringMethodInterceptors;
277 private ServiceBeanAopCacheManager _serviceBeanAopCacheManager;
278
279 private static class NoPACL implements PACL {
280
281 @Override
282 public InvocationHandler getInvocationHandler(
283 InvocationHandler invocationHandler,
284 AdvisedSupport advisedSupport) {
285
286 return invocationHandler;
287 }
288
289 }
290
291 }