package org.springmodules.javaspaces;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Serializable representation of a method and invocation id, solving the
* problem of java.lang.reflect.Method not being serializable.
*
* @author Rod Johnson
*/
public class MethodIdentifier implements Serializable {
private transient static final Log log = LogFactory.getLog(MethodIdentifier.class);
// TODO do properly
private transient Method method;
/** Fully qualified class name */
public String className;
public String methodString;
/**
* Unique identifier. Has to be set up externally depending on the chosen
* strategy (id unique on the same machine generated very fast or ids unique
* across a cluster or worldwide which have more expensive creation
* process).
*/
public Serializable uid;
public MethodIdentifier(Method method) {
this.method = method;
if (method != null) {
methodToString(method);
}
}
public MethodIdentifier() {
}
public synchronized Method getMethod() {
// The method resolving has moved to readObject
//Lior b:(27.8.2006) - Gigaspaces serializes other
//entry data structure and not the AbstractMethodCallEntry.
//That means the readObject()/writeObject() will never be called.
//
if (method == null) {
method = stringToMethod();
}
return method;
}
/*
* public Method getMethod() { return method; }
*/
/**
* Method to String conversion.
*
* @param m
*/
private void methodToString(Method m) {
this.className = method.getDeclaringClass().getName();
this.methodString = method.toString();
}
/**
* String to method conversion.
*
* @return
* @throws ClassNotFoundException
*/
private Method stringToMethod(String className) {
if (className == null || methodString == null)
return null;
if (log.isDebugEnabled())
log.debug("Fqn='" + className + "'; methodName='" + methodString + "'");
Class clazz;
try {
clazz = Class.forName(className);
}
catch (ClassNotFoundException e) {
throw new IllegalArgumentException(e.getMessage());
}
Method methods[] = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.toString().equals(methodString)) {
return m;
}
}
throw new IllegalArgumentException("Can't resolve method from '" + className + "." + methodString + "'");
}
private Method stringToMethod() {
return stringToMethod(className);
}
public String toString() {
return this.getClass().getName() + "uid='" + uid + "': method=" + method + "; className=" + className
+ "; methodString=" + methodString;
}
// TODO: check the logic of these methods and see why they break the tests.
// It would be good to put the method resolving here
// and keep the getter unsynchronized.
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
System.out.println("writeObject called!");
// oos.writeObject(className);
// oos.writeObject(methodString); // oos.writeObject();
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
System.out.println("readObject called!");
this.method = stringToMethod(this.className);
System.out.println("determined method " + this.method);
}
}