1 /*
2 * Copyright 2002-2007 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.springframework.remoting.support;
18
19 import java.io.Serializable;
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import org.aopalliance.intercept.MethodInvocation;
26
27 import org.springframework.util.ClassUtils;
28
29 /**
30 * Encapsulates a remote invocation, providing core method invocation properties
31 * in a serializable fashion. Used for RMI and HTTP-based serialization invokers.
32 *
33 * <p>This is an SPI class, typically not used directly by applications.
34 * Can be subclassed for additional invocation parameters.
35 *
36 * @author Juergen Hoeller
37 * @since 25.02.2004
38 * @see RemoteInvocationResult
39 * @see RemoteInvocationFactory
40 * @see RemoteInvocationExecutor
41 * @see org.springframework.remoting.rmi.RmiProxyFactoryBean
42 * @see org.springframework.remoting.rmi.RmiServiceExporter
43 * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean
44 * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter
45 */
46 public class RemoteInvocation implements Serializable {
47
48 /** use serialVersionUID from Spring 1.1 for interoperability */
49 private static final long serialVersionUID = 6876024250231820554L;
50
51
52 private String methodName;
53
54 private Class[] parameterTypes;
55
56 private Object[] arguments;
57
58 private Map attributes;
59
60
61 /**
62 * Create a new RemoteInvocation for use as JavaBean.
63 */
64 public RemoteInvocation() {
65 }
66
67 /**
68 * Create a new RemoteInvocation for the given parameters.
69 * @param methodName the name of the method to invoke
70 * @param parameterTypes the parameter types of the method
71 * @param arguments the arguments for the invocation
72 */
73 public RemoteInvocation(String methodName, Class[] parameterTypes, Object[] arguments) {
74 this.methodName = methodName;
75 this.parameterTypes = parameterTypes;
76 this.arguments = arguments;
77 }
78
79 /**
80 * Create a new RemoteInvocation for the given AOP method invocation.
81 * @param methodInvocation the AOP invocation to convert
82 */
83 public RemoteInvocation(MethodInvocation methodInvocation) {
84 this.methodName = methodInvocation.getMethod().getName();
85 this.parameterTypes = methodInvocation.getMethod().getParameterTypes();
86 this.arguments = methodInvocation.getArguments();
87 }
88
89
90 /**
91 * Set the name of the target method.
92 */
93 public void setMethodName(String methodName) {
94 this.methodName = methodName;
95 }
96
97 /**
98 * Return the name of the target method.
99 */
100 public String getMethodName() {
101 return this.methodName;
102 }
103
104 /**
105 * Set the parameter types of the target method.
106 */
107 public void setParameterTypes(Class[] parameterTypes) {
108 this.parameterTypes = parameterTypes;
109 }
110
111 /**
112 * Return the parameter types of the target method.
113 */
114 public Class[] getParameterTypes() {
115 return this.parameterTypes;
116 }
117
118 /**
119 * Set the arguments for the target method call.
120 */
121 public void setArguments(Object[] arguments) {
122 this.arguments = arguments;
123 }
124
125 /**
126 * Return the arguments for the target method call.
127 */
128 public Object[] getArguments() {
129 return this.arguments;
130 }
131
132
133 /**
134 * Add an additional invocation attribute. Useful to add additional
135 * invocation context without having to subclass RemoteInvocation.
136 * <p>Attribute keys have to be unique, and no overriding of existing
137 * attributes is allowed.
138 * <p>The implementation avoids to unnecessarily create the attributes
139 * Map, to minimize serialization size.
140 * @param key the attribute key
141 * @param value the attribute value
142 * @throws IllegalStateException if the key is already bound
143 */
144 public void addAttribute(String key, Serializable value) throws IllegalStateException {
145 if (this.attributes == null) {
146 this.attributes = new HashMap();
147 }
148 if (this.attributes.containsKey(key)) {
149 throw new IllegalStateException("There is already an attribute with key '" + key + "' bound");
150 }
151 this.attributes.put(key, value);
152 }
153
154 /**
155 * Retrieve the attribute for the given key, if any.
156 * <p>The implementation avoids to unnecessarily create the attributes
157 * Map, to minimize serialization size.
158 * @param key the attribute key
159 * @return the attribute value, or <code>null</code> if not defined
160 */
161 public Serializable getAttribute(String key) {
162 if (this.attributes == null) {
163 return null;
164 }
165 return (Serializable) this.attributes.get(key);
166 }
167
168 /**
169 * Set the attributes Map. Only here for special purposes:
170 * Preferably, use {@link #addAttribute} and {@link #getAttribute}.
171 * @param attributes the attributes Map
172 * @see #addAttribute
173 * @see #getAttribute
174 */
175 public void setAttributes(Map attributes) {
176 this.attributes = attributes;
177 }
178
179 /**
180 * Return the attributes Map. Mainly here for debugging purposes:
181 * Preferably, use {@link #addAttribute} and {@link #getAttribute}.
182 * @return the attributes Map, or <code>null</code> if none created
183 * @see #addAttribute
184 * @see #getAttribute
185 */
186 public Map getAttributes() {
187 return this.attributes;
188 }
189
190
191 /**
192 * Perform this invocation on the given target object.
193 * Typically called when a RemoteInvocation is received on the server.
194 * @param targetObject the target object to apply the invocation to
195 * @return the invocation result
196 * @throws NoSuchMethodException if the method name could not be resolved
197 * @throws IllegalAccessException if the method could not be accessed
198 * @throws InvocationTargetException if the method invocation resulted in an exception
199 * @see java.lang.reflect.Method#invoke
200 */
201 public Object invoke(Object targetObject)
202 throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
203
204 Method method = targetObject.getClass().getMethod(this.methodName, this.parameterTypes);
205 return method.invoke(targetObject, this.arguments);
206 }
207
208
209 public String toString() {
210 return "RemoteInvocation: method name '" + this.methodName + "'; parameter types " +
211 ClassUtils.classNamesToString(this.parameterTypes);
212 }
213
214 }