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            @Override
118            public Object proceed() throws Throwable {
119                    if (_index < _methodInterceptors.size()) {
120                            MethodInterceptor methodInterceptor = _methodInterceptors.get(
121                                    _index++);
122    
123                            return methodInterceptor.invoke(this);
124                    }
125    
126                    if (_equalsMethod) {
127                            Object argument = _arguments[0];
128    
129                            if (argument == null) {
130                                    return false;
131                            }
132    
133                            if (ProxyUtil.isProxyClass(argument.getClass())) {
134                                    AdvisedSupport advisedSupport =
135                                            ServiceBeanAopProxy.getAdvisedSupport(argument);
136    
137                                    if (advisedSupport != null) {
138                                            TargetSource targetSource =
139                                                    advisedSupport.getTargetSource();
140    
141                                            argument = targetSource.getTarget();
142                                    }
143                            }
144    
145                            return _target.equals(argument);
146                    }
147    
148                    try {
149                            return _method.invoke(_target, _arguments);
150                    }
151                    catch (InvocationTargetException ite) {
152                            throw ite.getTargetException();
153                    }
154            }
155    
156            public void setMethodInterceptors(
157                    List<MethodInterceptor> methodInterceptors) {
158    
159                    _methodInterceptors = methodInterceptors;
160            }
161    
162            public ServiceBeanMethodInvocation toCacheKeyModel() {
163                    ServiceBeanMethodInvocation serviceBeanMethodInvocation =
164                            new ServiceBeanMethodInvocation(null, null, _method, null);
165    
166                    serviceBeanMethodInvocation._equalsMethod = _equalsMethod;
167                    serviceBeanMethodInvocation._hashCode = _hashCode;
168    
169                    return serviceBeanMethodInvocation;
170            }
171    
172            @Override
173            public String toString() {
174                    if (_toString != null) {
175                            return _toString;
176                    }
177    
178                    Class<?>[] parameterTypes = _method.getParameterTypes();
179    
180                    StringBundler sb = new StringBundler(parameterTypes.length * 2 + 6);
181    
182                    Class<?> declaringClass = _method.getDeclaringClass();
183    
184                    sb.append(declaringClass.getName());
185    
186                    sb.append(StringPool.PERIOD);
187                    sb.append(_method.getName());
188                    sb.append(StringPool.OPEN_PARENTHESIS);
189    
190                    for (int i = 0; i < parameterTypes.length; i++) {
191                            Class<?> parameterType = parameterTypes[i];
192    
193                            sb.append(parameterType.getName());
194    
195                            if ((i + 1) < parameterTypes.length) {
196                                    sb.append(StringPool.COMMA);
197                            }
198                    }
199    
200                    sb.append(StringPool.CLOSE_PARENTHESIS);
201    
202                    if (_targetClass != null) {
203                            sb.append(StringPool.AT);
204                            sb.append(_targetClass.getName());
205                    }
206    
207                    _toString = sb.toString();
208    
209                    return _toString;
210            }
211    
212            private Object[] _arguments;
213            private boolean _equalsMethod;
214            private int _hashCode;
215            private int _index;
216            private Method _method;
217            private List<MethodInterceptor> _methodInterceptors;
218            private Object _target;
219            private Class<?> _targetClass;
220            private String _toString;
221    
222    }