001    /**
002     * Copyright (c) 2000-2013 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.kernel.messaging.proxy;
016    
017    import com.liferay.portal.kernel.annotation.AnnotationLocator;
018    import com.liferay.portal.kernel.util.MethodKey;
019    import com.liferay.portal.kernel.util.StringBundler;
020    
021    import java.io.Externalizable;
022    import java.io.IOException;
023    import java.io.ObjectInput;
024    import java.io.ObjectOutput;
025    
026    import java.lang.reflect.InvocationTargetException;
027    import java.lang.reflect.Method;
028    
029    import java.util.Arrays;
030    import java.util.Map;
031    import java.util.concurrent.ConcurrentHashMap;
032    
033    /**
034     * @author Micha Kiener
035     * @author Michael C. Han
036     * @author Brian Wing Shun Chan
037     * @author Shuyang Zhou
038     */
039    public class ProxyRequest implements Externalizable {
040    
041            /**
042             * The empty constructor is required by {@link java.io.Externalizable}. Do
043             * not use this for any other purpose.
044             */
045            public ProxyRequest() {
046            }
047    
048            public ProxyRequest(Method method, Object[] arguments) throws Exception {
049                    _method = method;
050                    _arguments = arguments;
051    
052                    if (method.getReturnType() != Void.TYPE) {
053                            _hasReturnValue = true;
054                    }
055    
056                    boolean[] localAndSynchronous = _localAndSynchronousMap.get(method);
057    
058                    if (localAndSynchronous == null) {
059                            localAndSynchronous = new boolean[2];
060    
061                            MessagingProxy messagingProxy = AnnotationLocator.locate(
062                                    method, method.getDeclaringClass(), MessagingProxy.class);
063    
064                            if (messagingProxy != null) {
065                                    if (messagingProxy.local()) {
066                                            localAndSynchronous[0] = true;
067                                    }
068    
069                                    ProxyMode proxyMode = messagingProxy.mode();
070    
071                                    if (proxyMode.equals(ProxyMode.SYNC)) {
072                                            localAndSynchronous[1] = true;
073                                    }
074                            }
075    
076                            _localAndSynchronousMap.put(method, localAndSynchronous);
077                    }
078    
079                    _local = localAndSynchronous[0];
080                    _synchronous = localAndSynchronous[1];
081            }
082    
083            public Object execute(Object object) throws Exception {
084                    try {
085                            return _method.invoke(object, _arguments);
086                    }
087                    catch (InvocationTargetException ite) {
088                            Throwable t = ite.getCause();
089    
090                            if (t instanceof Exception) {
091                                    throw (Exception)t;
092                            }
093                            else {
094                                    throw new Exception(t);
095                            }
096                    }
097            }
098    
099            public Object[] getArguments() {
100                    return _arguments;
101            }
102    
103            public boolean hasReturnValue() {
104                    return _hasReturnValue;
105            }
106    
107            public boolean isLocal() {
108                    return _local;
109            }
110    
111            public boolean isSynchronous() {
112                    return _synchronous;
113            }
114    
115            @Override
116            public void readExternal(ObjectInput objectInput)
117                    throws ClassNotFoundException, IOException {
118    
119                    _arguments = (Object[])objectInput.readObject();
120                    _hasReturnValue = objectInput.readBoolean();
121    
122                    MethodKey methodKey = (MethodKey)objectInput.readObject();
123    
124                    try {
125                            _method = methodKey.getMethod();
126                    }
127                    catch (NoSuchMethodException nsme) {
128                            throw new IOException(nsme);
129                    }
130    
131                    _synchronous = objectInput.readBoolean();
132            }
133    
134            @Override
135            public String toString() {
136                    StringBundler sb = new StringBundler(9);
137    
138                    sb.append("{arguments=");
139                    sb.append(Arrays.toString(_arguments));
140                    sb.append(", hasReturnValue=");
141                    sb.append(_hasReturnValue);
142                    sb.append(", method=");
143                    sb.append(_method);
144                    sb.append(", synchronous");
145                    sb.append(_synchronous);
146                    sb.append("}");
147    
148                    return sb.toString();
149            }
150    
151            @Override
152            public void writeExternal(ObjectOutput objectOutput) throws IOException {
153                    objectOutput.writeObject(_arguments);
154                    objectOutput.writeBoolean(_hasReturnValue);
155                    objectOutput.writeObject(new MethodKey(_method));
156                    objectOutput.writeBoolean(_synchronous);
157            }
158    
159            private static Map<Method, boolean[]> _localAndSynchronousMap =
160                    new ConcurrentHashMap<Method, boolean[]>();
161    
162            private Object[] _arguments;
163            private boolean _hasReturnValue;
164            private boolean _local;
165            private Method _method;
166            private boolean _synchronous;
167    
168    }