/************************************************************************** * Copyright (c) 2001 by Punch Telematix. All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Punch Telematix nor the names of * * other contributors may be used to endorse or promote products * * derived from this software without specific prior written permission.* * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL PUNCH TELEMATIX OR OTHER CONTRIBUTORS BE LIABLE * * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ package java.rmi.server; import java.io.IOException; import java.lang.reflect.Constructor; import java.net.InetAddress; import java.net.ServerSocket; import java.rmi.NoSuchObjectException; import java.rmi.Remote; import java.rmi.RemoteException; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Hashtable; import wonka.rmi.ObjIDData; import wonka.rmi.RMIAcceptThread; import wonka.rmi.RMIConnection; import wonka.rmi.UnicastRef; public class UnicastRemoteObject extends RemoteServer { private static final long serialVersionUID = 4974527148936298033L; static final Hashtable exports; static { exports = new Hashtable(13); AccessController.doPrivileged(new PrivilegedAction(){ public Object run(){ RMIConnection.setupTable(exports); return null; } }); } // MODIFIED: Has to be transient //private transient int port; private transient RMIClientSocketFactory csf; private transient RMIServerSocketFactory ssf; protected UnicastRemoteObject() throws RemoteException { this(0,null,null); } protected UnicastRemoteObject(int port) throws RemoteException { this(port,null,null); } protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { this.csf = (csf == null ? RMISocketFactory.getRMISocketFactory() : csf); this.ssf = (ssf == null ? RMISocketFactory.getRMISocketFactory() : ssf); exportObject(this, port,this.csf, this.ssf); //this.port = ((ObjIDData)exports.get(this)).server.getLocalPort(); } public Object clone() throws CloneNotSupportedException { try { UnicastRemoteObject myClone=(UnicastRemoteObject)super.clone(); exportObject(myClone); return myClone; } catch (RemoteException e) { throw new ServerCloneException("Couldn't clone UnicastRemoteObject: "+this, e); } } public static RemoteStub exportObject(Remote obj) throws RemoteException { return (RemoteStub)exportObject(obj, 0, null, null); } public static Remote exportObject(Remote obj, int port) throws RemoteException { return exportObject(obj, port, null, null); } public static Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { csf = (csf == null ? RMISocketFactory.getRMISocketFactory() : csf); ssf = (ssf == null ? RMISocketFactory.getRMISocketFactory() : ssf); ServerSocket ss = null; do { try { ss = ssf.createServerSocket(port); } catch(IOException ioe){ //ask FailureHandler ... RMIFailureHandler fh = RMISocketFactory.theFailureHandler; if(fh != null){ if(!fh.failure(ioe)){ throw new RemoteException("failed to create ServerSocket",ioe); } } //if no FailureHandler we keep trying to create a serversocket !!! } } while(ss == null); if(exports.containsKey(obj)){ ObjIDData data = (ObjIDData)exports.get(obj); try { data.server.close(); new RegisterAction(data.id, null); } catch(IOException ioe){ throw new RemoteException("exportObject failed",ioe); } } try { Class remoteClass = obj.getClass(); String name = remoteClass.getName() + "_Stub"; RemoteStub stub = null; Class cl = Class.forName(name,true, remoteClass.getClassLoader()); ObjID id = new ObjID(); // MODIFIED: In the remote object that was passed as argument the // unicastRef has to be set as remote reference. Otherwise export of // remote classes that inherit from UnicastRemoteObject will not // work. They call super(), and in constructor of UnicastRemoteObject // exportObject is called. // Secondly the API of exportObject specs that the remoteobj passed as // argument will be exported. So its internal remoteref must be set. RemoteRef ref = new UnicastRef(getAddress(ss), ss.getLocalPort(), id, csf); RemoteObject myRemoteObj = (RemoteObject)obj; myRemoteObj.ref = ref; try { Constructor constr = cl.getDeclaredConstructor(new Class[]{java.rmi.server.RemoteRef.class}); stub = (RemoteStub)constr.newInstance(new Object[]{ref}); } catch(NoSuchMethodException nsme){ stub = (RemoteStub)cl.newInstance(); stub.ref = ref; } ObjIDData idData = new ObjIDData(ss,obj,stub,id); exports.put(obj,idData); new RegisterAction(id, idData); new RMIAcceptThread(ss); return stub; } catch(Exception e){ throw new RemoteException("export failed", e); } } public static boolean unexportObject(Remote obj, boolean force) throws NoSuchObjectException { ObjIDData data = (ObjIDData)exports.get(obj); if(data == null){ throw new NoSuchObjectException("object "+obj+" not found"); } try { data.server.close(); new RegisterAction(data.id, null); } catch(IOException ioe){ return false; } exports.remove(obj); return true; } /* private static RemoteStub exportObject(Remote obj, ServerSocket ss) throws RemoteException { if(exports.containsKey(obj)){ ObjIDData data = (ObjIDData)exports.get(obj); try { data.server.close(); new RegisterAction(id, null); } catch(IOException ioe){ throw new RemoteException("exportObject failed",ioe); } } try { Class remoteClass = obj.getClass(); String name = remoteClass.getName() + "_Stub"; RemoteStub stub = null; Class cl = Class.forName(name,true, remoteClass.getClassLoader()); //ObjID id = new ObjID(0x0L, new UID(0x07f5ea7, System.currentTimeMillis(),(short)0x8000)); ObjID id = new ObjID(); try { Constructor constr = cl.getDeclaredConstructor(new Class[]{java.rmi.server.RemoteRef.class}); RemoteRef ref = new UnicastRef(getAddress(ss), ss.getLocalPort(), id); stub = (RemoteStub)constr.newInstance(new Object[]{ref}); } catch(NoSuchMethodException nsme){ stub = (RemoteStub)cl.newInstance(); stub.ref = new UnicastRef(getAddress(ss), ss.getLocalPort(), id); } //TODO ... check creation ... ObjIDData idData = new ObjIDData(ss,obj,stub,id); exports.put(obj,idData); new RegisterAction(id, idData); new RMIAcceptThread(ss); return stub; } catch(Exception e){ throw new RemoteException("export failed", e); } } */ private static String getAddress(ServerSocket ss){ String address = ss.getInetAddress().getHostAddress(); if(address.equals("0.0.0.0")){ try { address = InetAddress.getLocalHost().getHostAddress(); } catch(java.net.UnknownHostException uhe){ address = "127.0.0.1"; } } return address; } static final class RegisterAction implements PrivilegedExceptionAction { private ObjID id; private ObjIDData data; RegisterAction(ObjID id, ObjIDData data) throws RemoteException { this.id = id; this.data = data; try { AccessController.doPrivileged(this); } catch(PrivilegedActionException pae){ throw (RemoteException)pae.getException(); } } public Object run() throws RemoteException { if(data == null){ RMIConnection.deregisterObjIDData(id); } else { RMIConnection.registerObjIDData(id, data); } return null; } } }