/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* UnicastServerRef implements the remote reference layer server-side
* behavior for remote objects exported with the "UnicastRef" reference
* type.
*
* @author Ann Wollrath
* @author Roger Riggs
* @author Peter Jones
*/
implements ServerRef, Dispatcher
{
/** value of server call log property */
new GetBooleanAction("java.rmi.server.logCalls"));
/** server call log */
// use serialVersionUID from JDK 1.2.2 for interoperability
/** flag to enable writing exceptions to System.err */
private static final boolean wantExceptionLog =
new GetBooleanAction("sun.rmi.server.exceptionTrace"));
private boolean forceStubUse = false;
/**
* flag to remove server-side stack traces before marshalling
* exceptions thrown by remote invocations to this VM
*/
private static final boolean suppressStackTraces =
new GetBooleanAction(
"sun.rmi.server.suppressStackTraces"));
/**
* skeleton to dispatch remote calls through, for 1.1 stub protocol
* (may be null if stub class only uses 1.2 stub protocol)
*/
/** maps method hash to Method object for each remote method */
/**
* A weak hash map, mapping classes to hash maps that map method
* hashes to method objects.
**/
new HashToMethod_Maps();
/** cache of impl classes that have no corresponding skeleton class */
/**
* Create a new (empty) Unicast server remote reference.
*/
public UnicastServerRef() {
}
/**
* Construct a Unicast server remote reference for a specified
* liveRef.
*/
super(ref);
}
/**
* Construct a Unicast server remote reference to be exported
* on the specified port.
*/
}
/**
* Constructs a UnicastServerRef to be exported on an
* anonymous port (i.e., 0) and that uses a pregenerated stub class
* (NOT a dynamic proxy instance) if 'forceStubUse' is 'true'.
*
* This constructor is only called by the method
* UnicastRemoteObject.exportObject(Remote) passing 'true' for
* 'forceStubUse'. The UnicastRemoteObject.exportObject(Remote) method
* returns RemoteStub, so it must ensure that the stub for the
* exported object is an instance of a pregenerated stub class that
* extends RemoteStub (instead of an instance of a dynamic proxy class
* which is not an instance of RemoteStub).
**/
this(0);
this.forceStubUse = forceStubUse;
}
/**
* 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.
**/
throws RemoteException
{
forceStubUse = true;
}
/**
* 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.
*/
boolean permanent)
throws RemoteException
{
try {
} catch (IllegalArgumentException e) {
throw new ExportException(
"remote object implements illegal remote interface", e);
}
if (stub instanceof RemoteStub) {
}
return stub;
}
/**
* 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.
* @exception ServerNotActiveException If called outside of servicing
* a remote method invocation.
*/
return TCPTransport.getClientHost();
}
/**
* Discovers and sets the appropriate skeleton for the impl.
*/
try {
} 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.
*/
}
}
}
/**
* 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.
* @param obj the target remote object for the call
* @param call the "remote call" from which operation and
* method arguments can be obtained.
* @exception IOException If unable to marshal return result or
* release input or output streams
*/
// 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
try {
if (num >= 0) {
return;
} else {
throw new UnmarshalException(
"skeleton class not found but required " +
"for client version");
}
}
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.
*/
throw new UnmarshalException("unrecognized method hash: " +
"method not supported by remote object");
}
// if calls are being logged, write out object id and operation
// unmarshal parameters
try {
}
throw new UnmarshalException(
"error unmarshalling arguments", e);
} catch (ClassNotFoundException e) {
throw new UnmarshalException(
"error unmarshalling arguments", e);
} finally {
}
// make upcall on remote object
try {
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
// marshal return value
try {
if (rtype != void.class) {
}
} catch (IOException 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);
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 {
}
}
throws IOException, ClassNotFoundException
{}
/**
* protocol, given a non-negative operation number that has
* already been read from the call stream.
*
* @param obj the target remote object for the call
* @param call the "remote call" from which operation and
* method arguments can be obtained.
* @param op the operation number
* @exception IOException if unable to marshal return result or
* release input or output streams
*/
throws IOException
{
long hash; // hash for matching stub with skeleton
try {
// read remote call header
try {
try {
}
} catch (ClassNotFoundException ignore) { }
throw new UnmarshalException("error unmarshalling call header",
readEx);
}
// if calls are being logged, write out object id and operation
// dispatch to skeleton for remote object
} catch (Throwable e) {
logCallException(e);
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 {
}
}
/**
* 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.
*/
while (t != null) {
t.setStackTrace(empty);
t = t.getCause();
}
}
/**
* Log the details of an incoming call. The method parameter is either of
* type java.lang.reflect.Method or java.rmi.server.Operation.
*/
try {
clientHost = getClientHost();
} catch (ServerNotActiveException snae) {
}
method + "]");
}
}
/**
* Log the exception detail of an incoming call.
*/
// if calls are being logged, log them
try {
} catch (ServerNotActiveException snae) {
}
}
// write exceptions (only) to System.err if desired
if (wantExceptionLog) {
synchronized (log) {
e.printStackTrace(log);
}
}
}
/**
* Returns the class of the ref type to be serialized.
*/
return "UnicastServerRef";
}
/**
* 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.
*/
return new UnicastRef(ref);
}
/**
* Write out external representation for remote ref.
*/
}
/**
* Read in external representation for remote ref.
* @exception ClassNotFoundException If the class for an object
* being restored cannot be found.
*/
throws IOException, ClassNotFoundException
{
// object is re-exported elsewhere (e.g., by UnicastRemoteObject)
}
/**
* A weak hash map, mapping classes to hash maps that map method
* hashes to method objects.
**/
private static class HashToMethod_Maps
{
HashToMethod_Maps() {}
{
/*
* Set this Method object to override language
* access checks so that the dispatcher can invoke
* methods from non-public remote interfaces.
*/
new PrivilegedAction<Void>() {
m.setAccessible(true);
return null;
}
});
}
}
}
}
return map;
}
}
}