PortableRemoteObject.java revision 608:7e06bf1dcb09
1202375Srdivacky/*
2202375Srdivacky * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
3202375Srdivacky * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4202375Srdivacky *
5202375Srdivacky * This code is free software; you can redistribute it and/or modify it
6202375Srdivacky * under the terms of the GNU General Public License version 2 only, as
7202375Srdivacky * published by the Free Software Foundation.  Oracle designates this
8202375Srdivacky * particular file as subject to the "Classpath" exception as provided
9202375Srdivacky * by Oracle in the LICENSE file that accompanied this code.
10202375Srdivacky *
11202375Srdivacky * This code is distributed in the hope that it will be useful, but WITHOUT
12202375Srdivacky * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13202375Srdivacky * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14202375Srdivacky * version 2 for more details (a copy is included in the LICENSE file that
15226633Sdim * accompanied this code).
16218893Sdim *
17249423Sdim * You should have received a copy of the GNU General Public License version
18202375Srdivacky * 2 along with this work; if not, write to the Free Software Foundation,
19202375Srdivacky * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20202375Srdivacky *
21202375Srdivacky * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22202375Srdivacky * or visit www.oracle.com if you need additional information or have any
23202375Srdivacky * questions.
24202375Srdivacky */
25202375Srdivacky/*
26202375Srdivacky * Licensed Materials - Property of IBM
27202375Srdivacky * RMI-IIOP v1.0
28202375Srdivacky * Copyright IBM Corp. 1998 1999  All Rights Reserved
29202375Srdivacky *
30202375Srdivacky */
31202375Srdivacky
32202375Srdivackypackage com.sun.corba.se.impl.javax.rmi;
33202375Srdivacky
34202375Srdivackyimport java.lang.reflect.Method ;
35202375Srdivacky
36202375Srdivackyimport javax.rmi.CORBA.Tie;
37202375Srdivackyimport javax.rmi.CORBA.Util;
38202375Srdivacky
39218893Sdimimport java.rmi.RemoteException;
40218893Sdimimport java.rmi.NoSuchObjectException;
41218893Sdimimport java.rmi.Remote;
42218893Sdim
43218893Sdimimport java.util.Properties;
44218893Sdim
45218893Sdimimport org.omg.CORBA.ORB;
46218893Sdimimport org.omg.CORBA.portable.Delegate;
47218893Sdimimport org.omg.CORBA.SystemException;
48218893Sdim
49218893Sdimimport java.rmi.server.UnicastRemoteObject;
50218893Sdimimport java.rmi.server.RemoteStub;
51218893Sdimimport java.rmi.server.ExportException;
52249423Sdim
53202375Srdivackyimport java.net.URL;
54202375Srdivacky
55202375Srdivackyimport com.sun.corba.se.impl.util.JDKBridge;
56212904Sdimimport com.sun.corba.se.impl.util.Utility;
57212904Sdimimport com.sun.corba.se.impl.util.RepositoryId;
58212904Sdim
59212904Sdimimport com.sun.corba.se.spi.presentation.rmi.StubAdapter;
60212904Sdim
61212904Sdimimport java.security.AccessController;
62212904Sdimimport com.sun.corba.se.impl.orbutil.GetPropertyAction;
63212904Sdim
64212904Sdim/**
65212904Sdim * Server implementation objects may either inherit from
66212904Sdim * javax.rmi.PortableRemoteObject or they may implement a remote interface
67212904Sdim * and then use the exportObject method to register themselves as a server object.
68212904Sdim * The toStub method takes a server implementation and returns a stub that
69212904Sdim * can be used to access that server object.
70212904Sdim * The connect method makes a Remote object ready for remote communication.
71212904Sdim * The unexportObject method is used to deregister a server object, allowing it to become
72212904Sdim * available for garbage collection.
73249423Sdim * The narrow method takes an object reference or abstract interface type and
74212904Sdim * attempts to narrow it to conform to
75212904Sdim * the given interface. If the operation is successful the result will be an
76249423Sdim * object of the specified type, otherwise an exception will be thrown.
77212904Sdim */
78212904Sdimpublic class PortableRemoteObject
79212904Sdim        implements javax.rmi.CORBA.PortableRemoteObjectDelegate {
80212904Sdim
81218893Sdim    /**
82212904Sdim     * Makes a server object ready to receive remote calls. Note
83212904Sdim     * that subclasses of PortableRemoteObject do not need to call this
84212904Sdim     * method, as it is called by the constructor.
85212904Sdim     * @param obj the server object to export.
86212904Sdim     * @exception RemoteException if export fails.
87212904Sdim     */
88212904Sdim    public void exportObject(Remote obj)
89212904Sdim        throws RemoteException {
90212904Sdim
91212904Sdim        if (obj == null) {
92212904Sdim            throw new NullPointerException("invalid argument");
93212904Sdim        }
94212904Sdim
95212904Sdim        // Has this object already been exported to IIOP?
96212904Sdim
97212904Sdim        if (Util.getTie(obj) != null) {
98249423Sdim
99212904Sdim            // Yes, so this is an error...
100212904Sdim
101249423Sdim            throw new ExportException (obj.getClass().getName() + " already exported");
102212904Sdim        }
103212904Sdim
104212904Sdim        // Can we load a Tie?
105249423Sdim
106212904Sdim        Tie theTie = Utility.loadTie(obj);
107212904Sdim
108212904Sdim        if (theTie != null) {
109212904Sdim
110212904Sdim            // Yes, so export it to IIOP...
111212904Sdim
112212904Sdim            Util.registerTarget(theTie,obj);
113212904Sdim
114249423Sdim        } else {
115212904Sdim
116212904Sdim            // No, so export to JRMP. If this is called twice for the
117212904Sdim            // same object, it will throw an ExportException...
118212904Sdim
119212904Sdim            UnicastRemoteObject.exportObject(obj);
120212904Sdim        }
121212904Sdim    }
122249423Sdim
123212904Sdim    /**
124212904Sdim     * Returns a stub for the given server object.
125249423Sdim     * @param obj the server object for which a stub is required. Must either be a subclass
126212904Sdim     * of PortableRemoteObject or have been previously the target of a call to
127212904Sdim     * {@link #exportObject}.
128212904Sdim     * @return the most derived stub for the object.
129212904Sdim     * @exception NoSuchObjectException if a stub cannot be located for the given server object.
130212904Sdim     */
131218893Sdim    public Remote toStub (Remote obj)
132212904Sdim        throws NoSuchObjectException
133218893Sdim    {
134212904Sdim        Remote result = null;
135212904Sdim        if (obj == null) {
136249423Sdim            throw new NullPointerException("invalid argument");
137212904Sdim        }
138212904Sdim
139212904Sdim        // If the class is already an IIOP stub then return it.
140212904Sdim        if (StubAdapter.isStub( obj )) {
141212904Sdim            return obj;
142212904Sdim        }
143249423Sdim
144212904Sdim        // If the class is already a JRMP stub then return it.
145212904Sdim        if (obj instanceof java.rmi.server.RemoteStub) {
146249423Sdim            return obj;
147212904Sdim        }
148212904Sdim
149249423Sdim        // Has it been exported to IIOP?
150212904Sdim        Tie theTie = Util.getTie(obj);
151212904Sdim
152212904Sdim        if (theTie != null) {
153212904Sdim            result = Utility.loadStub(theTie,null,null,true);
154239462Sdim        } else {
155212904Sdim            if (Utility.loadTie(obj) == null) {
156212904Sdim                result = java.rmi.server.RemoteObject.toStub(obj);
157218893Sdim            }
158212904Sdim        }
159212904Sdim
160249423Sdim        if (result == null) {
161212904Sdim            throw new NoSuchObjectException("object not exported");
162212904Sdim        }
163212904Sdim
164212904Sdim        return result;
165212904Sdim    }
166212904Sdim
167212904Sdim    /**
168212904Sdim     * Deregisters a server object from the runtime, allowing the object to become
169212904Sdim     * available for garbage collection.
170212904Sdim     * @param obj the object to unexport.
171212904Sdim     * @exception NoSuchObjectException if the remote object is not
172212904Sdim     * currently exported.
173212904Sdim     */
174212904Sdim    public void unexportObject(Remote obj)
175212904Sdim        throws NoSuchObjectException {
176212904Sdim
177212904Sdim        if (obj == null) {
178249423Sdim            throw new NullPointerException("invalid argument");
179212904Sdim        }
180212904Sdim
181212904Sdim        if (StubAdapter.isStub(obj) ||
182212904Sdim            obj instanceof java.rmi.server.RemoteStub) {
183212904Sdim            throw new NoSuchObjectException(
184212904Sdim                "Can only unexport a server object.");
185212904Sdim        }
186212904Sdim
187212904Sdim        Tie theTie = Util.getTie(obj);
188212904Sdim        if (theTie != null) {
189212904Sdim            Util.unexportObject(obj);
190212904Sdim        } else {
191212904Sdim            if (Utility.loadTie(obj) == null) {
192212904Sdim                UnicastRemoteObject.unexportObject(obj,true);
193243830Sdim            } else {
194234353Sdim                throw new NoSuchObjectException("Object not exported.");
195212904Sdim            }
196212904Sdim        }
197249423Sdim    }
198212904Sdim
199212904Sdim    /**
200212904Sdim     * Checks to ensure that an object of a remote or abstract interface type
201212904Sdim     * can be cast to a desired type.
202234353Sdim     * @param narrowFrom the object to check.
203212904Sdim     * @param narrowTo the desired type.
204212904Sdim     * @return an object which can be cast to the desired type.
205212904Sdim     * @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
206212904Sdim     */
207212904Sdim    public java.lang.Object narrow ( java.lang.Object narrowFrom,
208212904Sdim        java.lang.Class narrowTo) throws ClassCastException
209212904Sdim    {
210249423Sdim        java.lang.Object result = null;
211212904Sdim
212226633Sdim        if (narrowFrom == null)
213226633Sdim            return null;
214212904Sdim
215212904Sdim        if (narrowTo == null)
216226633Sdim            throw new NullPointerException("invalid argument");
217226633Sdim
218212904Sdim        try {
219212904Sdim            if (narrowTo.isAssignableFrom(narrowFrom.getClass()))
220212904Sdim                return narrowFrom;
221212904Sdim
222212904Sdim            // Is narrowTo an interface that might be
223212904Sdim            // implemented by a servant running on iiop?
224212904Sdim            if (narrowTo.isInterface() &&
225226633Sdim                narrowTo != java.io.Serializable.class &&
226226633Sdim                narrowTo != java.io.Externalizable.class) {
227226633Sdim
228212904Sdim                org.omg.CORBA.Object narrowObj
229212904Sdim                    = (org.omg.CORBA.Object) narrowFrom;
230249423Sdim
231212904Sdim                // Create an id from the narrowTo type...
232212904Sdim                String id = RepositoryId.createForAnyType(narrowTo);
233212904Sdim
234212904Sdim                if (narrowObj._is_a(id)) {
235226633Sdim                    return Utility.loadStub(narrowObj,narrowTo);
236226633Sdim                } else {
237212904Sdim                    throw new ClassCastException( "Object is not of remote type " +
238226633Sdim                        narrowTo.getName() ) ;
239226633Sdim                }
240212904Sdim            } else {
241212904Sdim                throw new ClassCastException( "Class " + narrowTo.getName() +
242212904Sdim                    " is not a valid remote interface" ) ;
243249423Sdim            }
244212904Sdim        } catch(Exception error) {
245212904Sdim            ClassCastException cce = new ClassCastException() ;
246212904Sdim            cce.initCause( error ) ;
247226633Sdim            throw cce ;
248226633Sdim        }
249226633Sdim    }
250226633Sdim
251226633Sdim    /**
252212904Sdim     * Makes a Remote object ready for remote communication. This normally
253212904Sdim     * happens implicitly when the object is sent or received as an argument
254226633Sdim     * on a remote method call, but in some circumstances it is useful to
255226633Sdim     * perform this action by making an explicit call.  See the
256212904Sdim     * {@link Stub#connect} method for more information.
257226633Sdim     * @param target the object to connect.
258249423Sdim     * @param source a previously connected object.
259212904Sdim     * @throws RemoteException if <code>source</code> is not connected
260212904Sdim     * or if <code>target</code> is already connected to a different ORB than
261212904Sdim     * <code>source</code>.
262212904Sdim     */
263212904Sdim    public void connect (Remote target, Remote source)
264226633Sdim        throws RemoteException
265249423Sdim    {
266226633Sdim        if (target == null || source == null) {
267226633Sdim            throw new NullPointerException("invalid argument");
268212904Sdim        }
269212904Sdim
270249423Sdim        ORB orb = null;
271212904Sdim        try {
272212904Sdim            if (StubAdapter.isStub( source )) {
273212904Sdim                orb = StubAdapter.getORB( source ) ;
274212904Sdim            } else {
275212904Sdim                // Is this a servant that was exported to iiop?
276226633Sdim                Tie tie = Util.getTie(source);
277212904Sdim                if (tie == null) {
278212904Sdim                    /* loadTie always succeeds for dynamic RMI-IIOP
279212904Sdim                    // No, can we get a tie for it?  If not,
280212904Sdim                    // assume that source is a JRMP object...
281212904Sdim                    if (Utility.loadTie(source) != null) {
282212904Sdim                        // Yes, so it is an iiop object which
283249423Sdim                        // has not been exported...
284212904Sdim                        throw new RemoteException(
285212904Sdim                            "'source' object not exported");
286212904Sdim                    }
287226633Sdim                    */
288226633Sdim                } else {
289226633Sdim                    orb = tie.orb();
290226633Sdim                }
291212904Sdim            }
292249423Sdim        } catch (SystemException e) {
293212904Sdim            throw new RemoteException("'source' object not connected", e );
294212904Sdim        }
295212904Sdim
296212904Sdim        boolean targetIsIIOP = false ;
297212904Sdim        Tie targetTie = null;
298212904Sdim        if (StubAdapter.isStub(target)) {
299212904Sdim            targetIsIIOP = true;
300212904Sdim        } else {
301212904Sdim            targetTie = Util.getTie(target);
302212904Sdim            if (targetTie != null) {
303212904Sdim                targetIsIIOP = true;
304212904Sdim            } else {
305212904Sdim                /* loadTie always succeeds for dynamic RMI-IIOP
306212904Sdim                if (Utility.loadTie(target) != null) {
307249423Sdim                    throw new RemoteException("'target' servant not exported");
308212904Sdim                }
309212904Sdim                */
310212904Sdim            }
311212904Sdim        }
312202375Srdivacky
313202375Srdivacky        if (!targetIsIIOP) {
314202375Srdivacky            // Yes. Do we have an ORB from the source object?
315249423Sdim            // If not, we're done - there is nothing to do to
316249423Sdim            // connect a JRMP object. If so, it is an error because
317212904Sdim            // the caller mixed JRMP and IIOP...
318212904Sdim            if (orb != null) {
319212904Sdim                throw new RemoteException(
320212904Sdim                    "'source' object exported to IIOP, 'target' is JRMP");
321212904Sdim            }
322212904Sdim        } else {
323249423Sdim            // The target object is IIOP. Make sure we have a
324249423Sdim            // valid ORB from the source object...
325212904Sdim            if (orb == null) {
326212904Sdim                throw new RemoteException(
327249423Sdim                    "'source' object is JRMP, 'target' is IIOP");
328249423Sdim            }
329249423Sdim
330202375Srdivacky            // And, finally, connect it up...
331202375Srdivacky            try {
332249423Sdim                if (targetTie != null) {
333202375Srdivacky                    // Is the tie already connected?
334202375Srdivacky                    try {
335202375Srdivacky                        ORB existingOrb = targetTie.orb();
336202375Srdivacky
337202375Srdivacky                        // Yes. Is it the same orb?
338202375Srdivacky                        if (existingOrb == orb) {
339203954Srdivacky
340203954Srdivacky                            // Yes, so nothing to do...
341203954Srdivacky                            return;
342202375Srdivacky                        } else {
343249423Sdim                            // No, so this is an error...
344202375Srdivacky                            throw new RemoteException(
345202375Srdivacky                                "'target' object was already connected");
346202375Srdivacky                        }
347202375Srdivacky                    } catch (SystemException e) {}
348202375Srdivacky
349202375Srdivacky                    // No, so do it...
350249423Sdim                    targetTie.orb(orb);
351202375Srdivacky                } else {
352202375Srdivacky                    StubAdapter.connect( target, orb ) ;
353202375Srdivacky                }
354202375Srdivacky            } catch (SystemException e) {
355202375Srdivacky
356202375Srdivacky                // The stub or tie was already connected...
357202375Srdivacky                throw new RemoteException(
358249423Sdim                    "'target' object was already connected", e );
359202375Srdivacky            }
360202375Srdivacky        }
361202375Srdivacky    }
362202375Srdivacky}
363202375Srdivacky