001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.spring.aop;
016    
017    import com.liferay.portal.kernel.util.ProxyUtil;
018    import com.liferay.portal.kernel.util.StringBundler;
019    import com.liferay.portal.kernel.util.StringPool;
020    import com.liferay.portal.kernel.util.Validator;
021    
022    import java.io.Serializable;
023    
024    import java.lang.reflect.AccessibleObject;
025    import java.lang.reflect.InvocationTargetException;
026    import java.lang.reflect.Method;
027    
028    import java.util.List;
029    
030    import org.aopalliance.intercept.MethodInterceptor;
031    import org.aopalliance.intercept.MethodInvocation;
032    
033    import org.springframework.aop.TargetSource;
034    import org.springframework.aop.framework.AdvisedSupport;
035    
036    /**
037     * @author Shuyang Zhou
038     */
039    public class ServiceBeanMethodInvocation
040            implements MethodInvocation, Serializable {
041    
042            public ServiceBeanMethodInvocation(
043                    Object target, Class<?> targetClass, Method method,
044                    Object[] arguments) {
045    
046                    _target = target;
047                    _targetClass = targetClass;
048                    _method = method;
049                    _arguments = arguments;
050    
051                    if (!_method.isAccessible()) {
052                            _method.setAccessible(true);
053                    }
054    
055                    if (_method.getDeclaringClass() == Object.class) {
056                            String methodName = _method.getName();
057    
058                            if (methodName.equals("equals")) {
059                                    _equalsMethod = true;
060                            }
061                    }
062            }
063    
064            @Override
065            public boolean equals(Object obj) {
066                    if (this == obj) {
067                            return true;
068                    }
069    
070                    if (!(obj instanceof ServiceBeanMethodInvocation)) {
071                            return false;
072                    }
073    
074                    ServiceBeanMethodInvocation serviceBeanMethodInvocation =
075                            (ServiceBeanMethodInvocation)obj;
076    
077                    if (Validator.equals(_method, serviceBeanMethodInvocation._method)) {
078                            return true;
079                    }
080    
081                    return false;
082            }
083    
084            @Override
085            public Object[] getArguments() {
086                    return _arguments;
087            }
088    
089            @Override
090            public Method getMethod() {
091                    return _method;
092            }
093    
094            @Override
095            public AccessibleObject getStaticPart() {
096                    return _method;
097            }
098    
099            public Class<?> getTargetClass() {
100                    return _targetClass;
101            }
102    
103            @Override
104            public Object getThis() {
105                    return _target;
106            }
107    
108            @Override
109            public int hashCode() {
110                    if (_hashCode == 0) {
111                            _hashCode = _method.hashCode();
112                    }
113    
114                    return _hashCode;
115            }
116    
117            public void mark() {
118                    _markIndex = _index;
119            }
120    
121            @Override
122            public Object proceed() throws Throwable {
123                    if (_index < _methodInterceptors.size()) {
124                            MethodInterceptor methodInterceptor = _methodInterceptors.get(
125                                    _index++);
126    
127                            return methodInterceptor.invoke(this);
128                    }
129    
130                    if (_equalsMethod) {
131                            Object argument = _arguments[0];
132    
133                            if (argument == null) {
134                                    return false;
135                            }
136    
137                            if (ProxyUtil.isProxyClass(argument.getClass())) {
138                                    AdvisedSupport advisedSupport =
139                                            ServiceBeanAopProxy.getAdvisedSupport(argument);
140    
141                                    if (advisedSupport != null) {
142                                            TargetSource targetSource =
143                                                    advisedSupport.getTargetSource();
144    
145                                            argument = targetSource.getTarget();
146                                    }
147                            }
148    
149                            return _target.equals(argument);
150                    }
151    
152                    try {
153                            return _method.invoke(_target, _arguments);
154                    }
155                    catch (InvocationTargetException ite) {
156                            throw ite.getTargetException();
157                    }
158            }
159    
160            public void reset() {
161                    _index = _markIndex;
162            }
163    
164            public void setMethodInterceptors(
165                    List<MethodInterceptor> methodInterceptors) {
166    
167                    _methodInterceptors = methodInterceptors;
168            }
169    
170            public ServiceBeanMethodInvocation toCacheKeyModel() {
171                    ServiceBeanMethodInvocation serviceBeanMethodInvocation =
172                            new ServiceBeanMethodInvocation(null, null, _method, null);
173    
174                    serviceBeanMethodInvocation._equalsMethod = _equalsMethod;
175                    serviceBeanMethodInvocation._hashCode = _hashCode;
176    
177                    return serviceBeanMethodInvocation;
178            }
179    
180            @Override
181            public String toString() {
182                    if (_toString != null) {
183                            return _toString;
184                    }
185    
186                    Class<?>[] parameterTypes = _method.getParameterTypes();
187    
188                    StringBundler sb = new StringBundler(parameterTypes.length * 2 + 6);
189    
190                    Class<?> declaringClass = _method.getDeclaringClass();
191    
192                    sb.append(declaringClass.getName());
193    
194                    sb.append(StringPool.PERIOD);
195                    sb.append(_method.getName());
196                    sb.append(StringPool.OPEN_PARENTHESIS);
197    
198                    for (int i = 0; i < parameterTypes.length; i++) {
199                            Class<?> parameterType = parameterTypes[i];
200    
201                            sb.append(parameterType.getName());
202    
203                            if ((i + 1) < parameterTypes.length) {
204                                    sb.append(StringPool.COMMA);
205                            }
206                    }
207    
208                    sb.append(StringPool.CLOSE_PARENTHESIS);
209    
210                    if (_targetClass != null) {
211                            sb.append(StringPool.AT);
212                            sb.append(_targetClass.getName());
213                    }
214    
215                    _toString = sb.toString();
216    
217                    return _toString;
218            }
219    
220            private final Object[] _arguments;
221            private boolean _equalsMethod;
222            private int _hashCode;
223            private int _index;
224            private int _markIndex;
225            private final Method _method;
226            private List<MethodInterceptor> _methodInterceptors;
227            private final Object _target;
228            private final Class<?> _targetClass;
229            private String _toString;
230    
231    }