2 Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu
.java
.rmi
.server
;
40 import java
.io
.DataInputStream
;
41 import java
.io
.DataOutputStream
;
42 import java
.io
.IOException
;
43 import java
.io
.ObjectInput
;
44 import java
.io
.ObjectInputStream
;
45 import java
.io
.ObjectOutput
;
46 import java
.io
.ObjectOutputStream
;
47 import java
.lang
.reflect
.InvocationTargetException
;
48 import java
.lang
.reflect
.Method
;
49 import java
.rmi
.Remote
;
50 import java
.rmi
.RemoteException
;
51 import java
.rmi
.server
.ObjID
;
52 import java
.rmi
.server
.Operation
;
53 import java
.rmi
.server
.RMIClientSocketFactory
;
54 import java
.rmi
.server
.RemoteCall
;
55 import java
.rmi
.server
.RemoteObject
;
56 import java
.rmi
.server
.RemoteRef
;
57 import java
.rmi
.server
.UID
;
59 public class UnicastRef
60 implements RemoteRef
, ProtocolConstants
{
63 UnicastConnectionManager manager
;
66 * Used by serialization, and let subclass capable of having default constructor
68 // must be public otherwise java.rmi.RemoteObject cannot instantiate this class
73 public UnicastRef(ObjID objid
, String host
, int port
, RMIClientSocketFactory csf
) {
75 manager
= UnicastConnectionManager
.getInstance(host
, port
, csf
);
78 public UnicastRef(ObjID objid
) {
82 public Object
invoke(Remote obj
, Method method
, Object
[] params
, long opnum
) throws Exception
{
83 // Check if client and server are in the same VM, then local call can be used to
84 // replace remote call, but it's somewhat violating remote semantic.
85 Object svrobj
= manager
.serverobj
;
87 // Make sure that the server object is compatible. It could be loaded from a different
89 if(svrobj
!= null && method
.getDeclaringClass().isInstance(svrobj
)){
93 ret
= method
.invoke(svrobj
, params
);
94 }catch(InvocationTargetException e
){
95 throw (Exception
)e
.getTargetException();
97 //System.out.println("\n\n ***** local call: " + method + "\nreturn: " + ret + "\n\n");
100 //System.out.println("***************** remote call:" + manager.serverPort);
101 return (invokeCommon(obj
, method
, params
, -1, opnum
));
104 private Object
invokeCommon(Remote obj
, Method method
, Object
[] params
, int opnum
, long hash
) throws Exception
{
105 UnicastConnection conn
;
107 conn
= manager
.getConnection();
109 catch (IOException e1
) {
110 throw new RemoteException("connection failed to host: " + manager
.serverName
, e1
);
113 ObjectOutputStream out
;
114 DataOutputStream dout
;
116 dout
= conn
.getDataOutputStream();
117 dout
.writeByte(MESSAGE_CALL
);
119 out
= conn
.getObjectOutputStream();
125 // must handle primitive class and their wrapper classes
126 Class clss
[] = method
.getParameterTypes();
127 for(int i
= 0; i
< clss
.length
; i
++)
128 ((RMIObjectOutputStream
)out
).writeValue(params
[i
], clss
[i
]);
132 catch (IOException e2
) {
133 throw new RemoteException("call failed: ", e2
);
139 ObjectInputStream in
;
142 din
= conn
.getDataInputStream();
144 if ((returncode
= din
.readUnsignedByte()) != MESSAGE_CALL_ACK
) {
146 throw new RemoteException("Call not acked:" + returncode
);
149 in
= conn
.getObjectInputStream();
150 returncode
= in
.readUnsignedByte();
153 Class cls
= method
.getReturnType();
154 if(cls
== Void
.TYPE
){
158 returnval
= ((RMIObjectInputStream
)in
).readValue(cls
);
161 catch (IOException e3
) {
162 //for debug: e3.printStackTrace();
163 throw new RemoteException("call return failed: ", e3
);
166 /* if DGCAck is necessary??
167 //According to RMI wire protocol, send a DGCAck
168 // to indicate receiving return value
169 dout.writeByte(MESSAGE_DGCACK);
174 manager
.discardConnection(conn
);
176 if (returncode
!= RETURN_ACK
&& returnval
!= null) {
177 throw (Exception
)returnval
;
186 public RemoteCall
newCall(RemoteObject obj
, Operation
[] op
, int opnum
, long hash
) throws RemoteException
{
187 UnicastConnection conn
;
190 conn
= manager
.getConnection();
192 catch (IOException e1
) {
193 throw new RemoteException("connection failed to host: " + manager
.serverName
, e1
);
198 return (new UnicastRemoteCall(conn
, objid
, opnum
, hash
));
204 public void invoke(RemoteCall call
) throws Exception
{
205 UnicastRemoteCall c
= (UnicastRemoteCall
)call
;
212 public void done(RemoteCall call
) throws RemoteException
{
213 UnicastRemoteCall c
= (UnicastRemoteCall
)call
;
216 } catch(IOException e
){}
217 UnicastConnection conn
= c
.getConnection();
218 manager
.discardConnection(conn
);
221 public void writeExternal(ObjectOutput out
) throws IOException
{
222 if (manager
== null) {
223 throw new IOException("no connection");
227 // This byte is somewhat confusing when interoperating with JDK
228 out
.writeByte(0); //RETURN_ACK);
231 public void readExternal(ObjectInput in
) throws IOException
, ClassNotFoundException
{
232 manager
= UnicastConnectionManager
.read(in
);
233 objid
= ObjID
.read(in
);
234 byte ack
= in
.readByte();
235 // This byte is somewhat confusing when interoperating with JDK
236 if (ack
!= RETURN_ACK
&& ack
!= 0/*jdk ack value*/) {
237 throw new IOException("no ack found");
241 public boolean remoteEquals(RemoteRef ref
) {
242 throw new Error("Not implemented");
245 public int remoteHashCode() {
246 throw new Error("Not implemented");
249 public String
getRefClass(ObjectOutput out
) {
250 return ("UnicastRef");
253 public String
remoteToString() {
254 throw new Error("Not implemented");
257 public void dump(UnicastConnection conn
) {
259 DataInputStream din
= conn
.getDataInputStream();
261 int b
= din
.readUnsignedByte();
262 System
.out
.print(Integer
.toHexString(b
));
263 if (b
>= 32 && b
< 128) {
264 System
.out
.print(": " + (char)b
);
266 System
.out
.println();
269 catch (IOException _
) {