PortableRemoteObject.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25/*
26 * Licensed Materials - Property of IBM
27 * RMI-IIOP v1.0
28 * Copyright IBM Corp. 1998 1999  All Rights Reserved
29 *
30 */
31
32package com.sun.corba.se.impl.javax.rmi;
33
34import java.lang.reflect.Method ;
35
36import javax.rmi.CORBA.Tie;
37import javax.rmi.CORBA.Util;
38
39import java.rmi.RemoteException;
40import java.rmi.NoSuchObjectException;
41import java.rmi.Remote;
42
43import java.util.Properties;
44
45import org.omg.CORBA.ORB;
46import org.omg.CORBA.portable.Delegate;
47import org.omg.CORBA.SystemException;
48
49import java.rmi.server.UnicastRemoteObject;
50import java.rmi.server.RemoteStub;
51import java.rmi.server.ExportException;
52
53import java.net.URL;
54
55import com.sun.corba.se.impl.util.JDKBridge;
56import com.sun.corba.se.impl.util.Utility;
57import com.sun.corba.se.impl.util.RepositoryId;
58
59import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
60
61import java.security.AccessController;
62import com.sun.corba.se.impl.orbutil.GetPropertyAction;
63
64/**
65 * Server implementation objects may either inherit from
66 * javax.rmi.PortableRemoteObject or they may implement a remote interface
67 * and then use the exportObject method to register themselves as a server object.
68 * The toStub method takes a server implementation and returns a stub that
69 * can be used to access that server object.
70 * The connect method makes a Remote object ready for remote communication.
71 * The unexportObject method is used to deregister a server object, allowing it to become
72 * available for garbage collection.
73 * The narrow method takes an object reference or abstract interface type and
74 * attempts to narrow it to conform to
75 * the given interface. If the operation is successful the result will be an
76 * object of the specified type, otherwise an exception will be thrown.
77 */
78public class PortableRemoteObject
79        implements javax.rmi.CORBA.PortableRemoteObjectDelegate {
80
81    /**
82     * Makes a server object ready to receive remote calls. Note
83     * that subclasses of PortableRemoteObject do not need to call this
84     * method, as it is called by the constructor.
85     * @param obj the server object to export.
86     * @exception RemoteException if export fails.
87     */
88    public void exportObject(Remote obj)
89        throws RemoteException {
90
91        if (obj == null) {
92            throw new NullPointerException("invalid argument");
93        }
94
95        // Has this object already been exported to IIOP?
96
97        if (Util.getTie(obj) != null) {
98
99            // Yes, so this is an error...
100
101            throw new ExportException (obj.getClass().getName() + " already exported");
102        }
103
104        // Can we load a Tie?
105
106        Tie theTie = Utility.loadTie(obj);
107
108        if (theTie != null) {
109
110            // Yes, so export it to IIOP...
111
112            Util.registerTarget(theTie,obj);
113
114        } else {
115
116            // No, so export to JRMP. If this is called twice for the
117            // same object, it will throw an ExportException...
118
119            UnicastRemoteObject.exportObject(obj);
120        }
121    }
122
123    /**
124     * Returns a stub for the given server object.
125     * @param obj the server object for which a stub is required. Must either be a subclass
126     * of PortableRemoteObject or have been previously the target of a call to
127     * {@link #exportObject}.
128     * @return the most derived stub for the object.
129     * @exception NoSuchObjectException if a stub cannot be located for the given server object.
130     */
131    public Remote toStub (Remote obj)
132        throws NoSuchObjectException
133    {
134        Remote result = null;
135        if (obj == null) {
136            throw new NullPointerException("invalid argument");
137        }
138
139        // If the class is already an IIOP stub then return it.
140        if (StubAdapter.isStub( obj )) {
141            return obj;
142        }
143
144        // If the class is already a JRMP stub then return it.
145        if (obj instanceof java.rmi.server.RemoteStub) {
146            return obj;
147        }
148
149        // Has it been exported to IIOP?
150        Tie theTie = Util.getTie(obj);
151
152        if (theTie != null) {
153            result = Utility.loadStub(theTie,null,null,true);
154        } else {
155            if (Utility.loadTie(obj) == null) {
156                result = java.rmi.server.RemoteObject.toStub(obj);
157            }
158        }
159
160        if (result == null) {
161            throw new NoSuchObjectException("object not exported");
162        }
163
164        return result;
165    }
166
167    /**
168     * Deregisters a server object from the runtime, allowing the object to become
169     * available for garbage collection.
170     * @param obj the object to unexport.
171     * @exception NoSuchObjectException if the remote object is not
172     * currently exported.
173     */
174    public void unexportObject(Remote obj)
175        throws NoSuchObjectException {
176
177        if (obj == null) {
178            throw new NullPointerException("invalid argument");
179        }
180
181        if (StubAdapter.isStub(obj) ||
182            obj instanceof java.rmi.server.RemoteStub) {
183            throw new NoSuchObjectException(
184                "Can only unexport a server object.");
185        }
186
187        Tie theTie = Util.getTie(obj);
188        if (theTie != null) {
189            Util.unexportObject(obj);
190        } else {
191            if (Utility.loadTie(obj) == null) {
192                UnicastRemoteObject.unexportObject(obj,true);
193            } else {
194                throw new NoSuchObjectException("Object not exported.");
195            }
196        }
197    }
198
199    /**
200     * Checks to ensure that an object of a remote or abstract interface type
201     * can be cast to a desired type.
202     * @param narrowFrom the object to check.
203     * @param narrowTo the desired type.
204     * @return an object which can be cast to the desired type.
205     * @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
206     */
207    public java.lang.Object narrow ( java.lang.Object narrowFrom,
208        java.lang.Class narrowTo) throws ClassCastException
209    {
210        java.lang.Object result = null;
211
212        if (narrowFrom == null)
213            return null;
214
215        if (narrowTo == null)
216            throw new NullPointerException("invalid argument");
217
218        try {
219            if (narrowTo.isAssignableFrom(narrowFrom.getClass()))
220                return narrowFrom;
221
222            // Is narrowTo an interface that might be
223            // implemented by a servant running on iiop?
224            if (narrowTo.isInterface() &&
225                narrowTo != java.io.Serializable.class &&
226                narrowTo != java.io.Externalizable.class) {
227
228                org.omg.CORBA.Object narrowObj
229                    = (org.omg.CORBA.Object) narrowFrom;
230
231                // Create an id from the narrowTo type...
232                String id = RepositoryId.createForAnyType(narrowTo);
233
234                if (narrowObj._is_a(id)) {
235                    return Utility.loadStub(narrowObj,narrowTo);
236                } else {
237                    throw new ClassCastException( "Object is not of remote type " +
238                        narrowTo.getName() ) ;
239                }
240            } else {
241                throw new ClassCastException( "Class " + narrowTo.getName() +
242                    " is not a valid remote interface" ) ;
243            }
244        } catch(Exception error) {
245            ClassCastException cce = new ClassCastException() ;
246            cce.initCause( error ) ;
247            throw cce ;
248        }
249    }
250
251    /**
252     * Makes a Remote object ready for remote communication. This normally
253     * happens implicitly when the object is sent or received as an argument
254     * on a remote method call, but in some circumstances it is useful to
255     * perform this action by making an explicit call.  See the
256     * {@link Stub#connect} method for more information.
257     * @param target the object to connect.
258     * @param source a previously connected object.
259     * @throws RemoteException if <code>source</code> is not connected
260     * or if <code>target</code> is already connected to a different ORB than
261     * <code>source</code>.
262     */
263    public void connect (Remote target, Remote source)
264        throws RemoteException
265    {
266        if (target == null || source == null) {
267            throw new NullPointerException("invalid argument");
268        }
269
270        ORB orb = null;
271        try {
272            if (StubAdapter.isStub( source )) {
273                orb = StubAdapter.getORB( source ) ;
274            } else {
275                // Is this a servant that was exported to iiop?
276                Tie tie = Util.getTie(source);
277                if (tie == null) {
278                    /* loadTie always succeeds for dynamic RMI-IIOP
279                    // No, can we get a tie for it?  If not,
280                    // assume that source is a JRMP object...
281                    if (Utility.loadTie(source) != null) {
282                        // Yes, so it is an iiop object which
283                        // has not been exported...
284                        throw new RemoteException(
285                            "'source' object not exported");
286                    }
287                    */
288                } else {
289                    orb = tie.orb();
290                }
291            }
292        } catch (SystemException e) {
293            throw new RemoteException("'source' object not connected", e );
294        }
295
296        boolean targetIsIIOP = false ;
297        Tie targetTie = null;
298        if (StubAdapter.isStub(target)) {
299            targetIsIIOP = true;
300        } else {
301            targetTie = Util.getTie(target);
302            if (targetTie != null) {
303                targetIsIIOP = true;
304            } else {
305                /* loadTie always succeeds for dynamic RMI-IIOP
306                if (Utility.loadTie(target) != null) {
307                    throw new RemoteException("'target' servant not exported");
308                }
309                */
310            }
311        }
312
313        if (!targetIsIIOP) {
314            // Yes. Do we have an ORB from the source object?
315            // If not, we're done - there is nothing to do to
316            // connect a JRMP object. If so, it is an error because
317            // the caller mixed JRMP and IIOP...
318            if (orb != null) {
319                throw new RemoteException(
320                    "'source' object exported to IIOP, 'target' is JRMP");
321            }
322        } else {
323            // The target object is IIOP. Make sure we have a
324            // valid ORB from the source object...
325            if (orb == null) {
326                throw new RemoteException(
327                    "'source' object is JRMP, 'target' is IIOP");
328            }
329
330            // And, finally, connect it up...
331            try {
332                if (targetTie != null) {
333                    // Is the tie already connected?
334                    try {
335                        ORB existingOrb = targetTie.orb();
336
337                        // Yes. Is it the same orb?
338                        if (existingOrb == orb) {
339
340                            // Yes, so nothing to do...
341                            return;
342                        } else {
343                            // No, so this is an error...
344                            throw new RemoteException(
345                                "'target' object was already connected");
346                        }
347                    } catch (SystemException e) {}
348
349                    // No, so do it...
350                    targetTie.orb(orb);
351                } else {
352                    StubAdapter.connect( target, orb ) ;
353                }
354            } catch (SystemException e) {
355
356                // The stub or tie was already connected...
357                throw new RemoteException(
358                    "'target' object was already connected", e );
359            }
360        }
361    }
362}
363