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