/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.support;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.ClassUtils;
/**
* Encapsulates a remote invocation, providing core method invocation properties
* in a serializable fashion. Used for RMI and HTTP-based serialization invokers.
*
* <p>This is an SPI class, typically not used directly by applications.
* Can be subclassed for additional invocation parameters.
*
* @author Juergen Hoeller
* @since 25.02.2004
* @see RemoteInvocationResult
* @see RemoteInvocationFactory
* @see RemoteInvocationExecutor
* @see org.springframework.remoting.rmi.RmiProxyFactoryBean
* @see org.springframework.remoting.rmi.RmiServiceExporter
* @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean
* @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter
*/
public class RemoteInvocation implements Serializable {
/** use serialVersionUID from Spring 1.1 for interoperability */
private static final long serialVersionUID = 6876024250231820554L;
private String methodName;
private Class[] parameterTypes;
private Object[] arguments;
private Map<String, Serializable> attributes;
/**
* Create a new RemoteInvocation for use as JavaBean.
*/
public RemoteInvocation() {
}
/**
* Create a new RemoteInvocation for the given parameters.
* @param methodName the name of the method to invoke
* @param parameterTypes the parameter types of the method
* @param arguments the arguments for the invocation
*/
public RemoteInvocation(String methodName, Class[] parameterTypes, Object[] arguments) {
this.methodName = methodName;
this.parameterTypes = parameterTypes;
this.arguments = arguments;
}
/**
* Create a new RemoteInvocation for the given AOP method invocation.
* @param methodInvocation the AOP invocation to convert
*/
public RemoteInvocation(MethodInvocation methodInvocation) {
this.methodName = methodInvocation.getMethod().getName();
this.parameterTypes = methodInvocation.getMethod().getParameterTypes();
this.arguments = methodInvocation.getArguments();
}
/**
* Set the name of the target method.
*/
public void setMethodName(String methodName) {
this.methodName = methodName;
}
/**
* Return the name of the target method.
*/
public String getMethodName() {
return this.methodName;
}
/**
* Set the parameter types of the target method.
*/
public void setParameterTypes(Class[] parameterTypes) {
this.parameterTypes = parameterTypes;
}
/**
* Return the parameter types of the target method.
*/
public Class[] getParameterTypes() {
return this.parameterTypes;
}
/**
* Set the arguments for the target method call.
*/
public void setArguments(Object[] arguments) {
this.arguments = arguments;
}
/**
* Return the arguments for the target method call.
*/
public Object[] getArguments() {
return this.arguments;
}
/**
* Add an additional invocation attribute. Useful to add additional
* invocation context without having to subclass RemoteInvocation.
* <p>Attribute keys have to be unique, and no overriding of existing
* attributes is allowed.
* <p>The implementation avoids to unnecessarily create the attributes
* Map, to minimize serialization size.
* @param key the attribute key
* @param value the attribute value
* @throws IllegalStateException if the key is already bound
*/
public void addAttribute(String key, Serializable value) throws IllegalStateException {
if (this.attributes == null) {
this.attributes = new HashMap<String, Serializable>();
}
if (this.attributes.containsKey(key)) {
throw new IllegalStateException("There is already an attribute with key '" + key + "' bound");
}
this.attributes.put(key, value);
}
/**
* Retrieve the attribute for the given key, if any.
* <p>The implementation avoids to unnecessarily create the attributes
* Map, to minimize serialization size.
* @param key the attribute key
* @return the attribute value, or <code>null</code> if not defined
*/
public Serializable getAttribute(String key) {
if (this.attributes == null) {
return null;
}
return this.attributes.get(key);
}
/**
* Set the attributes Map. Only here for special purposes:
* Preferably, use {@link #addAttribute} and {@link #getAttribute}.
* @param attributes the attributes Map
* @see #addAttribute
* @see #getAttribute
*/
public void setAttributes(Map<String, Serializable> attributes) {
this.attributes = attributes;
}
/**
* Return the attributes Map. Mainly here for debugging purposes:
* Preferably, use {@link #addAttribute} and {@link #getAttribute}.
* @return the attributes Map, or <code>null</code> if none created
* @see #addAttribute
* @see #getAttribute
*/
public Map<String, Serializable> getAttributes() {
return this.attributes;
}
/**
* Perform this invocation on the given target object.
* Typically called when a RemoteInvocation is received on the server.
* @param targetObject the target object to apply the invocation to
* @return the invocation result
* @throws NoSuchMethodException if the method name could not be resolved
* @throws IllegalAccessException if the method could not be accessed
* @throws InvocationTargetException if the method invocation resulted in an exception
* @see java.lang.reflect.Method#invoke
*/
public Object invoke(Object targetObject)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Method method = targetObject.getClass().getMethod(this.methodName, this.parameterTypes);
return method.invoke(targetObject, this.arguments);
}
@Override
public String toString() {
return "RemoteInvocation: method name '" + this.methodName + "'; parameter types " +
ClassUtils.classNamesToString(this.parameterTypes);
}
}
|