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 return ProxyUtil.newProxyInstance(classLoader, proxiedInterfaces, this);
129 }
130
131 public Object invoke(Object proxy, Method method, Object[] arguments)
132 throws Throwable {
133
134 TargetSource targetSource = _advisedSupport.getTargetSource();
135
136 Object target = null;
137
138 try {
139 Class<?> targetClass = null;
140
141 target = targetSource.getTarget();
142
143 if (target != null) {
144 targetClass = target.getClass();
145 }
146
147 ServiceBeanMethodInvocation serviceBeanMethodInvocation =
148 new ServiceBeanMethodInvocation(
149 target, targetClass, method, arguments);
150
151 Skip skip = ServiceBeanAopCacheManager.getAnnotation(
152 serviceBeanMethodInvocation, Skip.class, null);
153
154 if (skip != null) {
155 serviceBeanMethodInvocation.setMethodInterceptors(
156 Collections.<MethodInterceptor>emptyList());
157 }
158 else {
159 _setMethodInterceptors(serviceBeanMethodInvocation);
160 }
161
162 return serviceBeanMethodInvocation.proceed();
163 }
164 finally {
165 if ((target != null) && !targetSource.isStatic()) {
166 targetSource.releaseTarget(target);
167 }
168 }
169 }
170
171 private List<MethodInterceptor> _getMethodInterceptors(
172 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
173
174 List<MethodInterceptor> methodInterceptors =
175 new ArrayList<MethodInterceptor>(_fullMethodInterceptors);
176
177 if (!_mergeSpringMethodInterceptors) {
178 return methodInterceptors;
179 }
180
181 List<Object> list =
182 _advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
183 _advisedSupport, serviceBeanMethodInvocation.getMethod(),
184 serviceBeanMethodInvocation.getTargetClass());
185
186 Iterator<Object> itr = list.iterator();
187
188 while (itr.hasNext()) {
189 Object obj = itr.next();
190
191 if (obj instanceof MethodInterceptor) {
192 continue;
193 }
194
195 if (_log.isWarnEnabled()) {
196 _log.warn(
197 "Skipping unsupported interceptor type " + obj.getClass());
198 }
199
200 itr.remove();
201 }
202
203 if (list.isEmpty()) {
204 return methodInterceptors;
205 }
206
207 for (Object object : list) {
208 methodInterceptors.add((MethodInterceptor)object);
209 }
210
211 return methodInterceptors;
212 }
213
214 private void _setMethodInterceptors(
215 ServiceBeanMethodInvocation serviceBeanMethodInvocation) {
216
217 MethodInterceptorsBag methodInterceptorsBag =
218 _serviceBeanAopCacheManager.getMethodInterceptorsBag(
219 serviceBeanMethodInvocation);
220
221 if (methodInterceptorsBag == null) {
222 List<MethodInterceptor> methodInterceptors = _getMethodInterceptors(
223 serviceBeanMethodInvocation);
224
225 methodInterceptorsBag = new MethodInterceptorsBag(
226 _classLevelMethodInterceptors, methodInterceptors);
227
228 _serviceBeanAopCacheManager.putMethodInterceptorsBag(
229 serviceBeanMethodInvocation.toCacheKeyModel(),
230 methodInterceptorsBag);
231 }
232
233 serviceBeanMethodInvocation.setMethodInterceptors(
234 methodInterceptorsBag.getMergedMethodInterceptors());
235 }
236
237 private static Log _log = LogFactoryUtil.getLog(ServiceBeanAopProxy.class);
238
239 private AdvisedSupport _advisedSupport;
240 private AdvisorChainFactory _advisorChainFactory;
241 private final List<MethodInterceptor> _classLevelMethodInterceptors;
242 private final List<MethodInterceptor> _fullMethodInterceptors;
243 private boolean _mergeSpringMethodInterceptors;
244 private ServiceBeanAopCacheManager _serviceBeanAopCacheManager;
245
246 }