| Method from sun.rmi.server.UnicastServerRef Detail: |
public static void clearStackTraces(Throwable t) {
StackTraceElement[] empty = new StackTraceElement[0];
while (t != null) {
t.setStackTrace(empty);
t = t.getCause();
}
}
Clear the stack trace of the given Throwable by replacing it with
an empty StackTraceElement array, and do the same for all of its
chained causative exceptions. |
public void dispatch(Remote obj,
RemoteCall call) throws IOException {
// positive operation number in 1.1 stubs;
// negative version number in 1.2 stubs and beyond...
int num;
long op;
try {
// read remote call header
ObjectInput in;
try {
in = call.getInputStream();
num = in.readInt();
if (num >= 0) {
if (skel != null) {
oldDispatch(obj, call, num);
return;
} else {
throw new UnmarshalException(
"skeleton class not found but required " +
"for client version");
}
}
op = in.readLong();
} catch (Exception readEx) {
throw new UnmarshalException("error unmarshalling call header",
readEx);
}
/*
* Since only system classes (with null class loaders) will be on
* the execution stack during parameter unmarshalling for the 1.2
* stub protocol, tell the MarshalInputStream not to bother trying
* to resolve classes using its superclasses's default method of
* consulting the first non-null class loader on the stack.
*/
MarshalInputStream marshalStream = (MarshalInputStream) in;
marshalStream.skipDefaultResolveClass();
Method method = hashToMethod_Map.get(op);
if (method == null) {
throw new UnmarshalException("unrecognized method hash: " +
"method not supported by remote object");
}
// if calls are being logged, write out object id and operation
logCall(obj, method);
// unmarshal parameters
Class[] types = method.getParameterTypes();
Object[] params = new Object[types.length];
try {
unmarshalCustomCallData(in);
for (int i = 0; i < types.length; i++) {
params[i] = unmarshalValue(types[i], in);
}
} catch (java.io.IOException e) {
throw new UnmarshalException(
"error unmarshalling arguments", e);
} catch (ClassNotFoundException e) {
throw new UnmarshalException(
"error unmarshalling arguments", e);
} finally {
call.releaseInputStream();
}
// make upcall on remote object
Object result;
try {
result = method.invoke(obj, params);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
// marshal return value
try {
ObjectOutput out = call.getResultStream(true);
Class rtype = method.getReturnType();
if (rtype != void.class) {
marshalValue(rtype, result, out);
}
} catch (IOException ex) {
throw new MarshalException("error marshalling return", ex);
/*
* This throw is problematic because when it is caught below,
* we attempt to marshal it back to the client, but at this
* point, a "normal return" has already been indicated,
* so marshalling an exception will corrupt the stream.
* This was the case with skeletons as well; there is no
* immediately obvious solution without a protocol change.
*/
}
} catch (Throwable e) {
logCallException(e);
ObjectOutput out = call.getResultStream(false);
if (e instanceof Error) {
e = new ServerError(
"Error occurred in server thread", (Error) e);
} else if (e instanceof RemoteException) {
e = new ServerException(
"RemoteException occurred in server thread",
(Exception) e);
}
if (suppressStackTraces) {
clearStackTraces(e);
}
out.writeObject(e);
} finally {
call.releaseInputStream(); // in case skeleton doesn't
call.releaseOutputStream();
}
}
Call to dispatch to the remote object (on the server side).
The up-call to the server and the marshalling of return result
(or exception) should be handled before returning from this
method. |
public RemoteStub exportObject(Remote impl,
Object data) throws RemoteException {
forceStubUse = true;
return (RemoteStub) exportObject(impl, data, false);
}
With the addition of support for dynamic proxies as stubs, this
method is obsolete because it returns RemoteStub instead of the more
general Remote. It should not be called. It sets the
'forceStubUse' flag to true so that the stub for the exported object
is forced to be an instance of the pregenerated stub class, which
extends RemoteStub.
Export this object, create the skeleton and stubs for this
dispatcher. Create a stub based on the type of the impl,
initialize it with the appropriate remote reference. Create the
target defined by the impl, dispatcher (this) and stub.
Export that target via the Ref. |
public Remote exportObject(Remote impl,
Object data,
boolean permanent) throws RemoteException {
Class implClass = impl.getClass();
Remote stub;
try {
stub = Util.createProxy(implClass, getClientRef(), forceStubUse);
} catch (IllegalArgumentException e) {
throw new ExportException(
"remote object implements illegal remote interface", e);
}
if (stub instanceof RemoteStub) {
setSkeleton(impl);
}
Target target =
new Target(impl, this, stub, ref.getObjID(), permanent);
ref.exportObject(target);
hashToMethod_Map = hashToMethod_Maps.get(implClass);
return stub;
}
Export this object, create the skeleton and stubs for this
dispatcher. Create a stub based on the type of the impl,
initialize it with the appropriate remote reference. Create the
target defined by the impl, dispatcher (this) and stub.
Export that target via the Ref. |
public String getClientHost() throws ServerNotActiveException {
return TCPTransport.getClientHost();
}
Return the hostname of the current client. When called from a
thread actively handling a remote method invocation the
hostname of the client is returned. |
protected RemoteRef getClientRef() {
return new UnicastRef(ref);
}
Return the client remote reference for this remoteRef.
In the case of a client RemoteRef "this" is the answer.
For a server remote reference, a client side one will have to
found or created. |
public String getRefClass(ObjectOutput out) {
return "UnicastServerRef";
}
Returns the class of the ref type to be serialized. |
public void oldDispatch(Remote obj,
RemoteCall call,
int op) throws IOException {
long hash; // hash for matching stub with skeleton
try {
// read remote call header
ObjectInput in;
try {
in = call.getInputStream();
hash = in.readLong();
} catch (Exception readEx) {
throw new UnmarshalException("error unmarshalling call header",
readEx);
}
// if calls are being logged, write out object id and operation
logCall(obj, skel.getOperations()[op]);
unmarshalCustomCallData(in);
// dispatch to skeleton for remote object
skel.dispatch(obj, call, op, hash);
} catch (Throwable e) {
logCallException(e);
ObjectOutput out = call.getResultStream(false);
if (e instanceof Error) {
e = new ServerError(
"Error occurred in server thread", (Error) e);
} else if (e instanceof RemoteException) {
e = new ServerException(
"RemoteException occurred in server thread",
(Exception) e);
}
if (suppressStackTraces) {
clearStackTraces(e);
}
out.writeObject(e);
} finally {
call.releaseInputStream(); // in case skeleton doesn't
call.releaseOutputStream();
}
}
Handle server-side dispatch using the RMI 1.1 stub/skeleton
protocol, given a non-negative operation number that has
already been read from the call stream. |
public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException {
// object is re-exported elsewhere (e.g., by UnicastRemoteObject)
ref = null;
skel = null;
}
Read in external representation for remote ref. |
public void setSkeleton(Remote impl) throws RemoteException {
if (!withoutSkeletons.containsKey(impl.getClass())) {
try {
skel = Util.createSkeleton(impl);
} catch (SkeletonNotFoundException e) {
/*
* Ignore exception for skeleton class not found, because a
* skeleton class is not necessary with the 1.2 stub protocol.
* Remember that this impl's class does not have a skeleton
* class so we don't waste time searching for it again.
*/
withoutSkeletons.put(impl.getClass(), null);
}
}
}
Discovers and sets the appropriate skeleton for the impl. |
protected void unmarshalCustomCallData(ObjectInput in) throws ClassNotFoundException, IOException {
}
|
public void writeExternal(ObjectOutput out) throws IOException {
}
Write out external representation for remote ref. |