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<>();
078 ArrayList<MethodInterceptor> fullMethodInterceptors = new ArrayList<>();
079
080 while (true) {
081 if (!(methodInterceptor instanceof ChainableMethodAdvice)) {
082 classLevelMethodInterceptors.add(methodInterceptor);
083 fullMethodInterceptors.add(methodInterceptor);
084
085 break;
086 }
087
088 ChainableMethodAdvice chainableMethodAdvice =
089 (ChainableMethodAdvice)methodInterceptor;
090
091 chainableMethodAdvice.setServiceBeanAopCacheManager(
092 serviceBeanAopCacheManager);
093
094 if (methodInterceptor instanceof AnnotationChainableMethodAdvice) {
095 AnnotationChainableMethodAdvice<?>
096 annotationChainableMethodAdvice =
097 (AnnotationChainableMethodAdvice<?>)methodInterceptor;
098
099 Class<? extends Annotation> annotationClass =
100 annotationChainableMethodAdvice.getAnnotationClass();
101
102 Target target = annotationClass.getAnnotation(Target.class);
103
104 if (target == null) {
105 classLevelMethodInterceptors.add(methodInterceptor);
106 }
107 else {
108 for (ElementType elementType : target.value()) {
109 if (elementType == ElementType.TYPE) {
110 classLevelMethodInterceptors.add(methodInterceptor);
111
112 break;
113 }
114 }
115 }
116 }
117 else {
118 classLevelMethodInterceptors.add(methodInterceptor);
119 }
120
121 fullMethodInterceptors.add(methodInterceptor);
122
123 methodInterceptor = chainableMethodAdvice.nextMethodInterceptor;
124 }
125
126 classLevelMethodInterceptors.trimToSize();
127
128 _classLevelMethodInterceptors = classLevelMethodInterceptors;
129 _fullMethodInterceptors = fullMethodInterceptors;
130
131 _serviceBeanAopCacheManager = serviceBeanAopCacheManager;
132 }
133
134 @Override
135 public AdvisedSupport getAdvisedSupport() {
136 return _advisedSupport;
137 }
138
139 @Override
140 public Object getProxy() {
141 return getProxy(ClassUtils.getDefaultClassLoader());
142 }
143
144 @Override
145 public Object getProxy(ClassLoader classLoader) {
146 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(
147 _advisedSupport);
148
149 InvocationHandler invocationHandler = _pacl.getInvocationHandler(
150 this, _advisedSupport);
151
152 return ProxyUtil.newProxyInstance(
153 classLoader, proxiedInterfaces, invocationHandler);
154 }
155
156 @Override
157 public Object invoke(Object proxy, Method method, Object[] arguments)
158 throws Throwable {
159
160 TargetSource targetSource = _advisedSupport.getTargetSource();
161
162 Object target = null;
163
164 try {
165 target = targetSource.getTarget();
166
167 ServiceBeanMethodInvocation serviceBeanMethodInvocation =
168 new ServiceBeanMethodInvocation(
169 target, targetSource.getTargetClass(), method, arguments);
170
171 _setMethodInterceptors(serviceBeanMethodInvocation);
172
173 return serviceBeanMethodInvocation.proceed();
174 }
175 finally {
176 if ((target != null) && !targetSource.isStatic()) {
177 targetSource.releaseTarget(target);
178 }
179 }
180 }
181
182 public interface PACL {
183
184 public InvocationHandler getInvocationHandler(
185 InvocationHandler invocationHandler, AdvisedSupport advisedSupport);
186
187 }
188
189 private List<MethodInterceptor> _getMethodInterceptors(
190 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
191
192 List<MethodInterceptor> methodInterceptors = new ArrayList<>(
193 _fullMethodInterceptors);
194
195 if (!_mergeSpringMethodInterceptors) {
196 return methodInterceptors;
197 }
198
199 List<Object> list =
200 _advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
201 _advisedSupport, serviceBeanMethodInvocation.getMethod(),
202 serviceBeanMethodInvocation.getTargetClass());
203
204 Iterator<Object> itr = list.iterator();
205
206 while (itr.hasNext()) {
207 Object obj = itr.next();
208
209 if (obj instanceof MethodInterceptor) {
210 continue;
211 }
212
213 if (_log.isWarnEnabled()) {
214 _log.warn(
215 "Skipping unsupported interceptor type " + obj.getClass());
216 }
217
218 itr.remove();
219 }
220
221 if (list.isEmpty()) {
222 return methodInterceptors;
223 }
224
225 for (Object object : list) {
226 methodInterceptors.add((MethodInterceptor)object);
227 }
228
229 return methodInterceptors;
230 }
231
232 private void _setMethodInterceptors(
233 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
234
235 MethodInterceptorsBag methodInterceptorsBag =
236 _serviceBeanAopCacheManager.getMethodInterceptorsBag(
237 serviceBeanMethodInvocation);
238
239 if (methodInterceptorsBag == null) {
240 List<MethodInterceptor> methodInterceptors = _getMethodInterceptors(
241 serviceBeanMethodInvocation);
242
243 methodInterceptorsBag = new MethodInterceptorsBag(
244 _classLevelMethodInterceptors, methodInterceptors);
245
246 _serviceBeanAopCacheManager.putMethodInterceptorsBag(
247 serviceBeanMethodInvocation.toCacheKeyModel(),
248 methodInterceptorsBag);
249 }
250
251 serviceBeanMethodInvocation.setMethodInterceptors(
252 methodInterceptorsBag.getMergedMethodInterceptors());
253 }
254
255 private static final Log _log = LogFactoryUtil.getLog(
256 ServiceBeanAopProxy.class);
257
258 private static final PACL _pacl = new NoPACL();
259
260 private final AdvisedSupport _advisedSupport;
261 private final AdvisorChainFactory _advisorChainFactory;
262 private final List<MethodInterceptor> _classLevelMethodInterceptors;
263 private final List<MethodInterceptor> _fullMethodInterceptors;
264 private final boolean _mergeSpringMethodInterceptors;
265 private final ServiceBeanAopCacheManager _serviceBeanAopCacheManager;
266
267 private static class NoPACL implements PACL {
268
269 @Override
270 public InvocationHandler getInvocationHandler(
271 InvocationHandler invocationHandler,
272 AdvisedSupport advisedSupport) {
273
274 return invocationHandler;
275 }
276
277 }
278
279 }