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.InvocationHandler;
026 import java.lang.reflect.Method;
027
028 import java.util.ArrayList;
029 import java.util.Iterator;
030 import java.util.List;
031
032 import org.aopalliance.intercept.MethodInterceptor;
033
034 import org.springframework.aop.SpringProxy;
035 import org.springframework.aop.TargetSource;
036 import org.springframework.aop.framework.AdvisedSupport;
037 import org.springframework.aop.framework.AdvisorChainFactory;
038 import org.springframework.aop.framework.AopProxy;
039 import org.springframework.aop.framework.AopProxyUtils;
040 import org.springframework.util.ClassUtils;
041
042
045 public class ServiceBeanAopProxy
046 implements AdvisedSupportProxy, AopProxy, InvocationHandler {
047
048 public static AdvisedSupport getAdvisedSupport(Object proxy)
049 throws Exception {
050
051 InvocationHandler invocationHandler = ProxyUtil.getInvocationHandler(
052 proxy);
053
054 if (invocationHandler instanceof AdvisedSupportProxy) {
055 AdvisedSupportProxy advisableSupportProxy =
056 (AdvisedSupportProxy)invocationHandler;
057
058 return advisableSupportProxy.getAdvisedSupport();
059 }
060
061 return null;
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 AdvisedSupport getAdvisedSupport() {
137 return _advisedSupport;
138 }
139
140 @Override
141 public Object getProxy() {
142 return getProxy(ClassUtils.getDefaultClassLoader());
143 }
144
145 @Override
146 public Object getProxy(ClassLoader classLoader) {
147 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(
148 _advisedSupport);
149
150 InvocationHandler invocationHandler = _pacl.getInvocationHandler(
151 this, _advisedSupport);
152
153 return ProxyUtil.newProxyInstance(
154 classLoader, proxiedInterfaces, invocationHandler);
155 }
156
157 @Override
158 public Object invoke(Object proxy, Method method, Object[] arguments)
159 throws Throwable {
160
161 TargetSource targetSource = _advisedSupport.getTargetSource();
162
163 Object target = null;
164
165 try {
166 target = targetSource.getTarget();
167
168 ServiceBeanMethodInvocation serviceBeanMethodInvocation =
169 new ServiceBeanMethodInvocation(
170 target, targetSource.getTargetClass(), method, arguments);
171
172 _setMethodInterceptors(serviceBeanMethodInvocation);
173
174 return serviceBeanMethodInvocation.proceed();
175 }
176 finally {
177 if ((target != null) && !targetSource.isStatic()) {
178 targetSource.releaseTarget(target);
179 }
180 }
181 }
182
183 public interface PACL {
184
185 public InvocationHandler getInvocationHandler(
186 InvocationHandler invocationHandler, AdvisedSupport advisedSupport);
187
188 }
189
190 private List<MethodInterceptor> _getMethodInterceptors(
191 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
192
193 List<MethodInterceptor> methodInterceptors =
194 new ArrayList<MethodInterceptor>(_fullMethodInterceptors);
195
196 if (!_mergeSpringMethodInterceptors) {
197 return methodInterceptors;
198 }
199
200 List<Object> list =
201 _advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
202 _advisedSupport, serviceBeanMethodInvocation.getMethod(),
203 serviceBeanMethodInvocation.getTargetClass());
204
205 Iterator<Object> itr = list.iterator();
206
207 while (itr.hasNext()) {
208 Object obj = itr.next();
209
210 if (obj instanceof MethodInterceptor) {
211 continue;
212 }
213
214 if (_log.isWarnEnabled()) {
215 _log.warn(
216 "Skipping unsupported interceptor type " + obj.getClass());
217 }
218
219 itr.remove();
220 }
221
222 if (list.isEmpty()) {
223 return methodInterceptors;
224 }
225
226 for (Object object : list) {
227 methodInterceptors.add((MethodInterceptor)object);
228 }
229
230 return methodInterceptors;
231 }
232
233 private void _setMethodInterceptors(
234 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
235
236 MethodInterceptorsBag methodInterceptorsBag =
237 _serviceBeanAopCacheManager.getMethodInterceptorsBag(
238 serviceBeanMethodInvocation);
239
240 if (methodInterceptorsBag == null) {
241 List<MethodInterceptor> methodInterceptors = _getMethodInterceptors(
242 serviceBeanMethodInvocation);
243
244 methodInterceptorsBag = new MethodInterceptorsBag(
245 _classLevelMethodInterceptors, methodInterceptors);
246
247 _serviceBeanAopCacheManager.putMethodInterceptorsBag(
248 serviceBeanMethodInvocation.toCacheKeyModel(),
249 methodInterceptorsBag);
250 }
251
252 serviceBeanMethodInvocation.setMethodInterceptors(
253 methodInterceptorsBag.getMergedMethodInterceptors());
254 }
255
256 private static final Log _log = LogFactoryUtil.getLog(
257 ServiceBeanAopProxy.class);
258
259 private static final PACL _pacl = new NoPACL();
260
261 private final AdvisedSupport _advisedSupport;
262 private final AdvisorChainFactory _advisorChainFactory;
263 private final List<MethodInterceptor> _classLevelMethodInterceptors;
264 private final List<MethodInterceptor> _fullMethodInterceptors;
265 private final boolean _mergeSpringMethodInterceptors;
266 private final 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 }