package rmi;

import java.rmi.*;
import java.rmi.server.*;
import java.security.*;

/**
 * A remote object that knows how to use the Sf proof.Prover
 * to automatically find and send proofs of authorization for
 * RMI calls.
 *
 * @deprecated This was an attempt to replumb RMI as I did once in the
 * {@link sf.rmi} package; I eventually took the shortcut described
 * in {@link InvokeHack}.
 *
 * @todo NOT FOR DISTRIBUTION
 * The code in this class is based on Sun's
 * sun.rmi.server.UnicastRemoteObject class. I needed to tweak the
 * functionality of a specific method that Sun declared private.
 * To do so, I had to copy the method and tweak the code. There
 * are ways one could imagine rewriting the class binary to accomplish
 * the same task without distributing something very close to Sun's
 * code.
 * @classSummaryOnly true
 */
public class SfRemoteObject
	extends UnicastRemoteObject {

	public SfRemoteObject(int port,
		RMIClientSocketFactory csf,
		RMIServerSocketFactory ssf)
		throws RemoteException {
		// Stupid non-overridable static methods! Means I have to
		// replace the ctor to effect the replacement of exportObject().
		// Crud! Can't do that because of private variables!! AARGH!
		// Would it hurt to let super's exportObject run?
		super(port, csf, ssf);
		AccessControlContext acc = AccessController.getContext();
		exportObject((Remote) this, port, csf, ssf);
	}

    private static Class[] portFactoryParamTypes = {
		int.class, RMIClientSocketFactory.class, RMIServerSocketFactory.class
    };

	public static Remote exportObject(Remote obj, int port,
		RMIClientSocketFactory csf,
		RMIServerSocketFactory ssf)
		throws RemoteException {
		// prepare arguments for server ref constructor
		Object[] args = new Object[] { new Integer(port), csf, ssf };

		Class serverRefClass = SfServerRef.class;
		return exportObject(obj, serverRefClass,
			portFactoryParamTypes, args);
	}

    /*
     * Create instance of given server ref type with constructor chosen
     * by indicated paramters and supplied with given arguements, and
     * export remote object with it.<p>
	 * 
	 * [jonh] only relevant change from original Sun method
	 * was to pass the Class in directly. The original method
	 * passed in the name and looked it up under a Sun package
	 * name. Yuk! Why? That makes it hard to extend in another package!
     */
	private static Remote exportObject(Remote obj, Class refClass,
									   Class[] params, Object[] args)
		throws RemoteException
	{
		if (!ServerRef.class.isAssignableFrom(refClass)) {
			throw new ExportException(
				"Server ref class not instance of " +
				ServerRef.class.getName() + ": " + refClass.getName());
		}

		// create server ref instance using given constructor and arguments
		ServerRef serverRef;
		try {
			java.lang.reflect.Constructor cons =
				refClass.getConstructor(params);
			serverRef = (ServerRef) cons.newInstance(args);
			// if impl does extends UnicastRemoteObject, set its ref
			// if (obj instanceof SfServerRef)
			//	 ((SfServerRef)obj).setRef(serverRef);
			// if (obj instanceof UnicastRemoteObject)
			// 	((UnicastRemoteObject)obj).ref = serverRef;

		} catch (Exception e) {
			throw new ExportException(
				"Exception creating instance of server ref class: " +
				refClass.getName(), e);
		}

		return serverRef.exportObject(obj, null);
	}
}
