Stream-based implementation of the RemoteCall interface.
| Method from sun.rmi.transport.StreamRemoteCall Detail: |
public void done() throws IOException {
/* WARNING: Currently, the UnicastRef.java invoke methods rely
* upon this method not throwing an IOException.
*/
releaseInputStream();
}
|
protected void exceptionReceivedFromServer(Exception ex) throws Exception {
serverException = ex;
StackTraceElement[] serverTrace = ex.getStackTrace();
StackTraceElement[] clientTrace = (new Throwable()).getStackTrace();
StackTraceElement[] combinedTrace =
new StackTraceElement[serverTrace.length + clientTrace.length];
System.arraycopy(serverTrace, 0, combinedTrace, 0,
serverTrace.length);
System.arraycopy(clientTrace, 0, combinedTrace, serverTrace.length,
clientTrace.length);
ex.setStackTrace(combinedTrace);
/*
* Log the details of a server exception thrown as a result of a
* remote method invocation.
*/
if (UnicastRef.clientCallLog.isLoggable(Log.BRIEF)) {
/* log call exception returned from server before it is rethrown */
TCPEndpoint ep = (TCPEndpoint) conn.getChannel().getEndpoint();
UnicastRef.clientCallLog.log(Log.BRIEF, "outbound call " +
"received exception: [" + ep.getHost() + ":" +
ep.getPort() + "] exception: ", ex);
}
throw ex;
}
Routine that causes the stack traces of remote exceptions to be
filled in with the current stack trace on the client. Detail
exceptions are filled in iteratively. |
public void executeCall() throws Exception {
byte returnType;
// read result header
DGCAckHandler ackHandler = null;
try {
if (out != null) {
ackHandler = out.getDGCAckHandler();
}
releaseOutputStream();
DataInputStream rd = new DataInputStream(conn.getInputStream());
byte op = rd.readByte();
if (op != TransportConstants.Return) {
if (Transport.transportLog.isLoggable(Log.BRIEF)) {
Transport.transportLog.log(Log.BRIEF,
"transport return code invalid: " + op);
}
throw new UnmarshalException("Transport return code invalid");
}
getInputStream();
returnType = in.readByte();
in.readID(); // id for DGC acknowledgement
} catch (UnmarshalException e) {
throw e;
} catch (IOException e) {
throw new UnmarshalException("Error unmarshaling return header",
e);
} finally {
if (ackHandler != null) {
ackHandler.release();
}
}
// read return value
switch (returnType) {
case TransportConstants.NormalReturn:
break;
case TransportConstants.ExceptionalReturn:
Object ex;
try {
ex = in.readObject();
} catch (Exception e) {
throw new UnmarshalException("Error unmarshaling return", e);
}
// An exception should have been received,
// if so throw it, else flag error
if (ex instanceof Exception) {
exceptionReceivedFromServer((Exception) ex);
} else {
throw new UnmarshalException("Return type not Exception");
}
default:
if (Transport.transportLog.isLoggable(Log.BRIEF)) {
Transport.transportLog.log(Log.BRIEF,
"return code invalid: " + returnType);
}
throw new UnmarshalException("Return code invalid");
}
}
Do whatever it takes to execute the call. |
public Connection getConnection() {
return conn;
}
Return the connection associated with this call. |
public ObjectInput getInputStream() throws IOException {
if (in == null) {
Transport.transportLog.log(Log.VERBOSE, "getting input stream");
in = new ConnectionInputStream(conn.getInputStream());
}
return in;
}
Get the InputStream the stub/skeleton should get results/arguments
from. |
public ObjectOutput getOutputStream() throws IOException {
return getOutputStream(false);
}
Return the output stream the stub/skeleton should put arguments/results
into. |
public ObjectOutput getResultStream(boolean success) throws IOException {
/* make sure result code only marshaled once. */
if (resultStarted)
throw new StreamCorruptedException("result already in progress");
else
resultStarted = true;
// write out return header
// return header, part 1 (read by Transport)
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeByte(TransportConstants.Return);// transport op
getOutputStream(true); // creates a MarshalOutputStream
// return header, part 2 (read by client-side RemoteCall)
if (success) //
out.writeByte(TransportConstants.NormalReturn);
else
out.writeByte(TransportConstants.ExceptionalReturn);
out.writeID(); // write id for gcAck
return out;
}
Returns an output stream (may put out header information
relating to the success of the call). |
public Exception getServerException() {
return serverException;
}
|
public void releaseInputStream() throws IOException {
/* WARNING: Currently, the UnicastRef.java invoke methods rely
* upon this method not throwing an IOException.
*/
try {
if (in != null) {
// execute MarshalInputStream "done" callbacks
try {
in.done();
} catch (RuntimeException e) {
}
// add saved references to DGC table
in.registerRefs();
/* WARNING: The connection being passed to done may have
* already been freed.
*/
in.done(conn);
}
conn.releaseInputStream();
} finally {
in = null;
}
}
Release the input stream, this would allow some transports to release
the channel early. |
public void releaseOutputStream() throws IOException {
try {
if (out != null) {
try {
out.flush();
} finally {
out.done(); // always start DGC ack timer
}
}
conn.releaseOutputStream();
} finally {
out = null;
}
}
Release the outputStream Currently, will not complain if the
output stream is released more than once. |