Source for gnu.java.rmi.server.UnicastRef

   1: /* UnicastRef.java --
   2:    Copyright (c) 1996, 1997, 1998, 1999, 2002, 2005
   3:    Free Software Foundation, Inc.
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11:  
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: independent module, the terms and conditions of the license of that
  33: module.  An independent module is a module which is not derived from
  34: or based on this library.  If you modify this library, you may extend
  35: this exception to your version of the library, but you are not
  36: obligated to do so.  If you do not wish to do so, delete this
  37: exception statement from your version. */
  38: 
  39: package gnu.java.rmi.server;
  40: 
  41: import java.io.DataInputStream;
  42: import java.io.DataOutputStream;
  43: import java.io.IOException;
  44: import java.io.ObjectInput;
  45: import java.io.ObjectInputStream;
  46: import java.io.ObjectOutput;
  47: import java.io.ObjectOutputStream;
  48: import java.lang.reflect.InvocationTargetException;
  49: import java.lang.reflect.Method;
  50: import java.rmi.Remote;
  51: import java.rmi.RemoteException;
  52: import java.rmi.server.ObjID;
  53: import java.rmi.server.Operation;
  54: import java.rmi.server.RMIClientSocketFactory;
  55: import java.rmi.server.RemoteCall;
  56: import java.rmi.server.RemoteObject;
  57: import java.rmi.server.RemoteRef;
  58: import java.rmi.server.UID;
  59: 
  60: public class UnicastRef
  61:     implements RemoteRef, ProtocolConstants {
  62: 
  63: public ObjID objid;
  64: UnicastConnectionManager manager;
  65: 
  66: /**
  67:  * Used by serialization, and let subclass capable of having default constructor
  68:  */
  69: // must be public otherwise java.rmi.RemoteObject cannot instantiate this class
  70: // -- iP
  71: public UnicastRef() {
  72: }
  73: 
  74: public UnicastRef(ObjID objid, String host, int port, RMIClientSocketFactory csf) {
  75:     this(objid);
  76:     manager = UnicastConnectionManager.getInstance(host, port, csf);
  77: }
  78: 
  79: public UnicastRef(ObjID objid) {
  80:     this.objid = objid;
  81: }
  82: 
  83: public Object invoke(Remote obj, Method method, Object[] params, long opnum) throws Exception {
  84:     // Check if client and server are in the same VM, then local call can be used to
  85:     // replace remote call, but it's somewhat violating remote semantic.
  86:     Object svrobj = manager.serverobj;
  87:     
  88:     // Make sure that the server object is compatible. It could be loaded from a different
  89:     // classloader --iP
  90:     if(svrobj != null && method.getDeclaringClass().isInstance(svrobj)){
  91:         //local call
  92:         Object ret = null;
  93:         try{
  94:             ret = method.invoke(svrobj, params);
  95:         }catch(InvocationTargetException e){
  96:             throw (Exception)e.getTargetException();
  97:         }
  98:         //System.out.println("\n\n ***** local call: " + method + "\nreturn: " + ret + "\n\n");
  99:         return ret;
 100:     }
 101:     //System.out.println("***************** remote call:" + manager.serverPort);
 102:     return (invokeCommon(obj, method, params, -1, opnum));
 103: }
 104: 
 105: private Object invokeCommon(Remote obj, Method method, Object[] params, int opnum, long hash) throws Exception {
 106:     UnicastConnection conn;
 107:     try {
 108:         conn = manager.getConnection();
 109:     }
 110:     catch (IOException e1) {
 111:         throw new RemoteException("connection failed to host: " + manager.serverName, e1);
 112:     }
 113: 
 114:     ObjectOutputStream out;
 115:     DataOutputStream dout;
 116:     try {
 117:         dout = conn.getDataOutputStream();
 118:         dout.writeByte(MESSAGE_CALL);
 119: 
 120:         out = conn.startObjectOutputStream(); // (re)start ObjectOutputStream
 121:         
 122:         objid.write(out);
 123:         out.writeInt(opnum);
 124:         out.writeLong(hash);
 125:         
 126:         // must handle primitive class and their wrapper classes
 127:         Class clss[] = method.getParameterTypes();
 128:         for(int i = 0; i < clss.length; i++)
 129:             ((RMIObjectOutputStream)out).writeValue(params[i], clss[i]);
 130: 
 131:         out.flush();
 132:     }
 133:     catch (IOException e2) {
 134:         throw new RemoteException("call failed: ", e2);
 135:     }
 136: 
 137:     int returncode;
 138:     Object returnval;
 139:     DataInputStream din;
 140:     ObjectInputStream in;
 141:     UID ack;
 142:     try {
 143:         din = conn.getDataInputStream();
 144:         
 145:         if ((returncode = din.readUnsignedByte()) != MESSAGE_CALL_ACK) {
 146:             conn.disconnect();
 147:             throw new RemoteException("Call not acked:" + returncode);
 148:         }
 149: 
 150:         in = conn.startObjectInputStream(); // (re)start ObjectInputStream
 151:         returncode = in.readUnsignedByte();
 152:         ack = UID.read(in);
 153: 
 154:         Class cls = method.getReturnType();
 155: 
 156:     if (returncode == RETURN_NACK) { 
 157:         returnval = in.readObject();  // get Exception
 158: 
 159:         } else if(cls == Void.TYPE) { 
 160:             returnval = null;
 161:             // in.readObject() // not required! returntype 'void' means no field is returned.
 162:         } else {
 163:             returnval = ((RMIObjectInputStream)in).readValue(cls); // get returnvalue
 164:     }
 165:     } catch (IOException e3) {
 166:         //for debug: e3.printStackTrace();
 167:         throw new RemoteException("call return failed: ", e3);
 168:     }
 169: 
 170:     /* if DGCAck is necessary??
 171:     //According to RMI wire protocol, send a DGCAck 
 172:     // to indicate receiving return value
 173:     dout.writeByte(MESSAGE_DGCACK);
 174:     ack.write(dout);
 175:     out.flush();
 176:     */
 177:     
 178:     manager.discardConnection(conn);
 179: 
 180:     if (returncode != RETURN_ACK && returnval != null) {
 181:         if (returncode == RETURN_NACK) throw (Exception)returnval;
 182:         else throw new RemoteException("unexpected returncode: " + returncode);
 183:     }
 184: 
 185:     return (returnval);
 186: }
 187: 
 188: /**
 189:  * @deprecated
 190:  */
 191: public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash) throws RemoteException {
 192:     UnicastConnection conn;
 193:     
 194:     try {
 195:         conn = manager.getConnection();
 196:     }
 197:     catch (IOException e1) {
 198:         throw new RemoteException("connection failed to host: " + manager.serverName, e1);
 199:     }
 200: 
 201:     //obj: useless?
 202: 
 203:     return (new UnicastRemoteCall(conn, objid, opnum, hash));
 204: }
 205: 
 206: /**
 207:  * @deprecated
 208:  */
 209: public void invoke(RemoteCall call) throws Exception {
 210:     UnicastRemoteCall c = (UnicastRemoteCall)call;
 211:     call.executeCall();
 212: }
 213: 
 214: /**
 215:  * @deprecated
 216:  */
 217: public void done(RemoteCall call) throws RemoteException {
 218:     UnicastRemoteCall c = (UnicastRemoteCall)call;
 219:     try{
 220:         c.done();
 221:     } catch(IOException e){}
 222:     UnicastConnection conn = c.getConnection();
 223:     manager.discardConnection(conn);
 224: }
 225: 
 226: public void writeExternal(ObjectOutput out) throws IOException {
 227:     if (manager == null) {
 228:         throw new IOException("no connection");
 229:     }
 230:     manager.write(out);
 231:     objid.write(out);
 232:     // This byte is somewhat confusing when interoperating with JDK
 233:     out.writeByte(0); //RETURN_ACK);
 234: }
 235: 
 236: public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 237:     manager = UnicastConnectionManager.read(in);
 238:     objid = ObjID.read(in);
 239:     byte ack = in.readByte();
 240:     // This byte is somewhat confusing when interoperating with JDK
 241:     if (ack != RETURN_ACK && ack != 0/*jdk ack value*/) {
 242:         throw new IOException("no ack found");
 243:     }
 244: }
 245: 
 246: public boolean remoteEquals(RemoteRef ref) {
 247:     throw new Error("Not implemented");
 248: }
 249: 
 250: public int remoteHashCode() {
 251:     throw new Error("Not implemented");
 252: }
 253: 
 254: public String getRefClass(ObjectOutput out) {
 255:     return ("UnicastRef");
 256: }
 257: 
 258: public String remoteToString() {
 259:     throw new Error("Not implemented");
 260: }
 261: 
 262: public void dump(UnicastConnection conn) {
 263:     try {
 264:         DataInputStream din = conn.getDataInputStream();
 265:         for (;;) {
 266:             int b = din.readUnsignedByte();
 267:             System.out.print(Integer.toHexString(b));
 268:             if (b >= 32 && b < 128) {
 269:                 System.out.print(": " + (char)b);
 270:             }
 271:             System.out.println();
 272:         }
 273:     }
 274:     catch (IOException _) {
 275:     }
 276: }
 277: 
 278: }