Merge from mainline.
[official-gcc.git] / libjava / classpath / gnu / java / rmi / server / UnicastRef.java
blobdef1acdcfc1e02aac1a3913fddbc0972be5bcd61
1 /* UnicastRef.java --
2 Copyright (c) 1996, 1997, 1998, 1999, 2002, 2005, 2006
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
40 package gnu.java.rmi.server;
42 import gnu.java.rmi.dgc.LeaseRenewingTask;
44 import java.io.DataInputStream;
45 import java.io.DataOutputStream;
46 import java.io.IOException;
47 import java.io.ObjectInput;
48 import java.io.ObjectInputStream;
49 import java.io.ObjectOutput;
50 import java.io.ObjectOutputStream;
51 import java.lang.reflect.InvocationTargetException;
52 import java.lang.reflect.Method;
53 import java.rmi.ConnectException;
54 import java.rmi.Remote;
55 import java.rmi.RemoteException;
56 import java.rmi.dgc.Lease;
57 import java.rmi.server.ObjID;
58 import java.rmi.server.Operation;
59 import java.rmi.server.RMIClientSocketFactory;
60 import java.rmi.server.RemoteCall;
61 import java.rmi.server.RemoteObject;
62 import java.rmi.server.RemoteRef;
63 import java.rmi.server.UID;
65 public class UnicastRef
66 implements RemoteRef, ProtocolConstants
69 /**
70 * Use serial version UID for iteroperability
72 private static final long serialVersionUID = 1;
74 public ObjID objid;
76 UnicastConnectionManager manager;
78 /**
79 * Used by serialization, and let subclass capable of having default
80 * constructor
82 // must be public otherwise java.rmi.RemoteObject cannot instantiate this
83 // class
84 // -- iP
85 public UnicastRef()
89 public UnicastRef(ObjID objid, String host, int port,
90 RMIClientSocketFactory csf)
92 this(objid);
93 manager = UnicastConnectionManager.getInstance(host, port, csf);
96 public UnicastRef(ObjID objid)
98 this.objid = objid;
101 public Object invoke(Remote obj, Method method, Object[] params, long opnum)
102 throws Exception
104 // Check if client and server are in the same VM, then local call can be
105 // used to
106 // replace remote call, but it's somewhat violating remote semantic.
107 Object svrobj = manager.serverobj;
109 // Make sure that the server object is compatible. It could be loaded from a
110 // different
111 // classloader --iP
112 if (svrobj != null && method.getDeclaringClass().isInstance(svrobj))
114 // local call
115 Object ret = null;
118 ret = method.invoke(svrobj, params);
120 catch (InvocationTargetException e)
122 throw (Exception) e.getTargetException();
124 // System.out.println("\n\n ***** local call: " + method + "\nreturn: "
125 // + ret + "\n\n");
126 return ret;
128 // System.out.println("***************** remote call:" +
129 // manager.serverPort);
130 return (invokeCommon(obj, method, params, - 1, opnum));
134 * The ordinary number of the DGC messages.
136 static long dgcSequence;
139 * The DGC object id, also serves as a synchronization target to increment the
140 * dgcSequence safely.
142 static final ObjID dgcId = new ObjID(ObjID.DGC_ID);
144 ObjID[] this_id;
147 * The number of the method "dirty" in the DGC.
149 static int DIRTY = 1;
152 * The DGC interface hash code.
154 static final long dgcInterfaceHash = - 669196253586618813L;
157 * Notify the DGC of the remote side that we still hold this object.
159 public Lease notifyDGC(Lease lease) throws Exception
161 long seq;
162 synchronized (dgcId)
164 seq = dgcSequence++;
167 if (this_id == null)
168 this_id = new ObjID[] { objid };
170 UnicastConnection conn;
173 conn = manager.getConnection();
175 catch (IOException e1)
177 throw new RemoteException("connection failed to host: "
178 + manager.serverName, e1);
181 ObjectOutputStream out;
182 DataOutputStream dout;
185 dout = conn.getDataOutputStream();
186 dout.writeByte(MESSAGE_CALL);
188 out = conn.startObjectOutputStream(); // (re)start ObjectOutputStream
190 dgcId.write(out);
191 // The number of the operation is 1 ("dirty")
192 out.writeInt(DIRTY);
193 out.writeLong(dgcInterfaceHash);
195 RMIObjectOutputStream rout = (RMIObjectOutputStream) out;
197 rout.writeValue(this_id, this_id.getClass());
198 rout.writeLong(seq);
199 rout.writeValue(lease, lease.getClass());
201 out.flush();
203 catch (IOException e2)
205 throw new RemoteException("DGC call failed: ", e2);
208 int returncode;
209 Object returnval;
210 DataInputStream din;
211 ObjectInputStream in;
212 UID ack;
215 din = conn.getDataInputStream();
217 if ((returncode = din.readUnsignedByte()) != MESSAGE_CALL_ACK)
219 conn.disconnect();
220 throw new RemoteException("DGC Call not acked:" + returncode);
223 in = conn.startObjectInputStream(); // (re)start ObjectInputStream
224 returncode = in.readUnsignedByte();
225 ack = UID.read(in);
227 if (returncode == RETURN_NACK)
229 returnval = in.readObject(); // get Exception
232 else
234 returnval = ((RMIObjectInputStream) in).readValue(Lease.class);
237 catch (IOException e3)
239 throw new RemoteException("DGC call return failed: ", e3);
242 manager.discardConnection(conn);
244 if (returncode != RETURN_ACK && returnval != null)
246 if (returncode == RETURN_NACK)
247 throw (Exception) returnval;
248 else
249 throw new RemoteException("DGC unexpected returncode: " + returncode);
252 return (Lease) returnval;
255 * Invoke the remote method on the given object. This part is overridden by
256 * the activatable objects.
258 protected Object invokeCommon(Remote obj, Method method, Object[] params,
259 int opnum, long hash) throws Exception
261 UnicastConnection conn;
264 conn = manager.getConnection();
265 return invokeCommon(conn, obj, method, params, opnum, hash);
267 catch (IOException e1)
269 throw new RemoteException("connection failed to host: "
270 + manager.serverName, e1);
275 * Invoke the remote method on the given object when connection is already
276 * established.
278 protected Object invokeCommon(UnicastConnection conn, Remote obj,
279 Method method, Object[] params, int opnum,
280 long hash) throws Exception
282 ObjectOutputStream out;
283 DataOutputStream dout;
286 dout = conn.getDataOutputStream();
287 dout.writeByte(MESSAGE_CALL);
289 out = conn.startObjectOutputStream(); // (re)start ObjectOutputStream
291 objid.write(out);
292 out.writeInt(opnum);
293 out.writeLong(hash);
295 // must handle primitive class and their wrapper classes
296 Class clss[] = method.getParameterTypes();
297 for (int i = 0; i < clss.length; i++)
298 ((RMIObjectOutputStream) out).writeValue(params[i], clss[i]);
300 out.flush();
302 catch (IOException e2)
304 throw new RemoteException("call failed: ", e2);
307 int returncode;
308 Object returnval;
309 DataInputStream din;
310 ObjectInputStream in;
311 UID ack;
314 din = conn.getDataInputStream();
316 if ((returncode = din.readUnsignedByte()) != MESSAGE_CALL_ACK)
318 conn.disconnect();
319 throw new RemoteException("Call not acked:" + returncode);
322 in = conn.startObjectInputStream(); // (re)start ObjectInputStream
323 returncode = in.readUnsignedByte();
324 ack = UID.read(in);
326 Class cls = method.getReturnType();
328 if (returncode == RETURN_NACK)
330 returnval = in.readObject(); // get Exception
333 else if (cls == Void.TYPE)
335 returnval = null;
336 // in.readObject() // not required! returntype 'void' means no field
337 // is returned.
339 else
341 returnval = ((RMIObjectInputStream) in).readValue(cls); // get
342 // returnvalue
345 catch (IOException e3)
347 // for debug: e3.printStackTrace();
348 throw new RemoteException("call return failed: ", e3);
352 * if DGCAck is necessary?? //According to RMI wire protocol, send a DGCAck //
353 * to indicate receiving return value dout.writeByte(MESSAGE_DGCACK);
354 * ack.write(dout); out.flush();
357 manager.discardConnection(conn);
359 if (returncode != RETURN_ACK && returnval != null)
361 if (returncode == RETURN_NACK)
362 throw (Exception) returnval;
363 else
364 throw new RemoteException("unexpected returncode: " + returncode);
367 return (returnval);
371 * @deprecated
373 public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum,
374 long hash) throws RemoteException
376 UnicastConnection conn;
380 conn = manager.getConnection();
382 catch (IOException e1)
384 throw new ConnectException("connection failed to host: "
385 + manager.serverName, e1);
388 // obj: useless?
390 return (new UnicastRemoteCall(conn, objid, opnum, hash));
394 * @deprecated
396 public void invoke(RemoteCall call) throws Exception
398 UnicastRemoteCall c = (UnicastRemoteCall) call;
399 call.executeCall();
403 * @deprecated
405 public void done(RemoteCall call) throws RemoteException
407 UnicastRemoteCall c = (UnicastRemoteCall) call;
410 c.done();
412 catch (IOException e)
415 UnicastConnection conn = c.getConnection();
416 manager.discardConnection(conn);
419 public void writeExternal(ObjectOutput out) throws IOException
421 if (manager == null)
423 throw new IOException("no connection");
425 manager.write(out);
426 objid.write(out);
427 // This byte is somewhat confusing when interoperating with JDK
428 out.writeByte(0); // RETURN_ACK);
431 public void readExternal(ObjectInput in) throws IOException,
432 ClassNotFoundException
434 manager = UnicastConnectionManager.read(in);
435 objid = ObjID.read(in);
436 byte ack = in.readByte();
437 // This byte is somewhat confusing when interoperating with JDK
438 if (ack != RETURN_ACK && ack != 0/* jdk ack value */)
440 throw new IOException("no ack found");
443 // Notify the DGC of the remote side that we hold the reference to the
444 // received object. Do not notify if the client and server are on the
445 // same virtual machine.
446 if (manager.serverobj == null)
447 LeaseRenewingTask.scheduleLeases(this);
450 public boolean remoteEquals(RemoteRef ref)
452 throw new Error("Not implemented");
455 public int remoteHashCode()
457 throw new Error("Not implemented");
460 public String getRefClass(ObjectOutput out)
462 return ("UnicastRef");
466 * Return the string representing the remote reference information.
468 public String remoteToString()
470 if (manager!=null)
471 return manager.toString();
472 else
473 return "null manager";
476 public void dump(UnicastConnection conn)
480 DataInputStream din = conn.getDataInputStream();
481 for (;;)
483 int b = din.readUnsignedByte();
484 System.out.print(Integer.toHexString(b));
485 if (b >= 32 && b < 128)
487 System.out.print(": " + (char) b);
489 System.out.println();
492 catch (IOException _)
498 * Check if this UnicastRef points to the object as the passed UnicastRef.
499 * Both the object Id and manager must be the same.
501 * @return true if the passed reference points to the same remote object as
502 * this reference, false otherwise.
504 public boolean equals(Object other)
506 if (other instanceof UnicastRef)
508 UnicastRef r = (UnicastRef) other;
509 return r.manager.equals(manager) && r.objid.equals(objid);
511 else
512 return false;
516 * Get the hash code of this UnicastRef, combining hash code of the manager
517 * with hash code of the object id.
519 public int hashCode()
521 return manager.hashCode() ^ objid.hashCode();