View Javadoc
1   /*
2    * Copyright (c) 1999, 2011, 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  package com.sun.jndi.toolkit.corba;
27  
28  // Needed for RMI/IIOP
29  import java.rmi.Remote;
30  
31  import java.lang.reflect.Method;
32  import java.lang.reflect.InvocationTargetException;
33  import java.util.Hashtable;
34  import java.util.Properties;
35  import java.util.Enumeration;
36  
37  import org.omg.CORBA.ORB;
38  
39  import javax.naming.Context;
40  import javax.naming.ConfigurationException;
41  
42  /**
43    * Contains utilities for performing CORBA-related tasks:
44    * 1. Get the org.omg.CORBA.Object for a java.rmi.Remote object.
45    * 2. Create an ORB to use for a given host/port, and environment properties.
46    *
47    * @author Simon Nash
48    * @author Bryan Atsatt
49    */
50  
51  public class CorbaUtils {
52      /**
53        * Returns the CORBA object reference associated with a Remote
54        * object by using the javax.rmi.CORBA package.
55        *<p>
56        * Use reflection to avoid hard dependencies on javax.rmi.CORBA package.
57        * This method effective does the following:
58        *<blockquote><pre>
59        * java.lang.Object stub;
60        * try {
61        *     stub = PortableRemoteObject.toStub(remoteObj);
62        * } catch (Exception e) {
63        *     throw new ConfigurationException("Object not exported or not found");
64        * }
65        * if (!(stub instanceof javax.rmi.CORBA.Stub)) {
66        *     return null; // JRMP impl or JRMP stub
67        * }
68        * try {
69        *     ((javax.rmi.CORBA.Stub)stub).connect(orb);  // try to connect IIOP stub
70        * } catch (RemoteException e) {
71        *     // ignore 'already connected' error
72        * }
73        * return (javax.rmi.CORBA.Stub)stub;
74        *
75        * @param remoteObj The non-null remote object for
76        * @param orb       The non-null ORB to connect the remote object to
77        * @return The CORBA Object for remoteObj; null if <tt>remoteObj</tt>
78        *                 is a JRMP implementation or JRMP stub.
79        * @exception ClassNotFoundException The RMI-IIOP package is not available
80        * @exception ConfigurationException The CORBA Object cannot be obtained
81        *         because of configuration problems.
82        */
83      public static org.omg.CORBA.Object remoteToCorba(Remote remoteObj, ORB orb)
84          throws ClassNotFoundException, ConfigurationException {
85              synchronized (CorbaUtils.class) {
86                  if (toStubMethod == null) {
87                      initMethodHandles();
88                  }
89              }
90  
91  // First, get remoteObj's stub
92  
93              // javax.rmi.CORBA.Stub stub = PortableRemoteObject.toStub(remoteObj);
94  
95              java.lang.Object stub;
96  
97              try {
98                  stub = toStubMethod.invoke(null, new java.lang.Object[]{remoteObj});
99  
100             } catch (InvocationTargetException e) {
101                 Throwable realException = e.getTargetException();
102                 // realException.printStackTrace();
103 
104                 ConfigurationException ce = new ConfigurationException(
105     "Problem with PortableRemoteObject.toStub(); object not exported or stub not found");
106                 ce.setRootCause(realException);
107                 throw ce;
108 
109             } catch (IllegalAccessException e) {
110                 ConfigurationException ce = new ConfigurationException(
111     "Cannot invoke javax.rmi.PortableRemoteObject.toStub(java.rmi.Remote)");
112 
113                 ce.setRootCause(e);
114                 throw ce;
115             }
116 
117 // Next, make sure that the stub is javax.rmi.CORBA.Stub
118 
119             if (!corbaStubClass.isInstance(stub)) {
120                 return null;  // JRMP implementation or JRMP stub
121             }
122 
123 // Next, make sure that the stub is connected
124             // Invoke stub.connect(orb)
125             try {
126                 connectMethod.invoke(stub, new java.lang.Object[]{orb});
127 
128             } catch (InvocationTargetException e) {
129                 Throwable realException = e.getTargetException();
130                 // realException.printStackTrace();
131 
132                 if (!(realException instanceof java.rmi.RemoteException)) {
133                     ConfigurationException ce = new ConfigurationException(
134                         "Problem invoking javax.rmi.CORBA.Stub.connect()");
135                     ce.setRootCause(realException);
136                     throw ce;
137                 }
138                 // ignore RemoteException because stub might have already
139                 // been connected
140             } catch (IllegalAccessException e) {
141                 ConfigurationException ce = new ConfigurationException(
142                     "Cannot invoke javax.rmi.CORBA.Stub.connect()");
143                 ce.setRootCause(e);
144                 throw ce;
145             }
146 // Finally, return stub
147             return (org.omg.CORBA.Object)stub;
148     }
149 
150     /**
151      * Get ORB using given server and port number, and properties from environment.
152      *
153      * @param server Possibly null server; if null means use default;
154      *               For applet, it is the applet host; for app, it is localhost.
155      * @param port   Port number, -1 means default port
156      * @param env    Possibly null environment. Contains environment properties.
157      *               Could contain ORB itself; or applet used for initializing ORB.
158      *               Use all String properties from env for initializing ORB
159      * @return A non-null ORB.
160      */
161     public static ORB getOrb(String server, int port, Hashtable<?,?> env) {
162         // See if we can get info from environment
163         Properties orbProp;
164 
165         // Extract any org.omg.CORBA properties from environment
166         if (env != null) {
167             if (env instanceof Properties) {
168                 // Already a Properties, just clone
169                 orbProp = (Properties) env.clone();
170             } else {
171                 // Get all String properties
172                 Enumeration<?> envProp;
173                 orbProp = new Properties();
174                 for (envProp = env.keys(); envProp.hasMoreElements();) {
175                     String key = (String)envProp.nextElement();
176                     Object val = env.get(key);
177                     if (val instanceof String) {
178                         orbProp.put(key, val);
179                     }
180                 }
181             }
182         } else {
183             orbProp = new Properties();
184         }
185 
186         if (server != null) {
187             orbProp.put("org.omg.CORBA.ORBInitialHost", server);
188         }
189         if (port >= 0) {
190             orbProp.put("org.omg.CORBA.ORBInitialPort", ""+port);
191         }
192 
193         // Get Applet from environment
194         if (env != null) {
195             Object applet = env.get(Context.APPLET);
196             if (applet != null) {
197                 // Create ORBs for an applet
198                 return initAppletORB(applet, orbProp);
199             }
200         }
201 
202         // Create ORBs using orbProp for a standalone application
203         return ORB.init(new String[0], orbProp);
204     }
205 
206     /**
207      * This method returns a new ORB instance for the given applet
208      * without creating a static dependency on java.applet.
209      */
210     private static ORB initAppletORB(Object applet, Properties orbProp) {
211         try {
212             Class<?> appletClass  = Class.forName("java.applet.Applet", true, null);
213             if (!appletClass.isInstance(applet)) {
214                 throw new ClassCastException(applet.getClass().getName());
215             }
216 
217             // invoke the static method ORB.init(applet, orbProp);
218             Method method = ORB.class.getMethod("init", appletClass, Properties.class);
219             return (ORB) method.invoke(null, applet, orbProp);
220         } catch (ClassNotFoundException e) {
221             // java.applet.Applet doesn't exist and the applet parameter is
222             // non-null; so throw CCE
223             throw new ClassCastException(applet.getClass().getName());
224         } catch (NoSuchMethodException e) {
225             throw new AssertionError(e);
226         } catch (InvocationTargetException e) {
227             Throwable cause = e.getCause();
228             if (cause instanceof RuntimeException) {
229                 throw (RuntimeException) cause;
230             } else if (cause instanceof Error) {
231                 throw (Error) cause;
232             }
233             throw new AssertionError(e);
234         } catch (IllegalAccessException iae) {
235             throw new AssertionError(iae);
236         }
237     }
238 
239     // Fields used for reflection of RMI-IIOP
240     private static Method toStubMethod = null;
241     private static Method connectMethod = null;
242     private static Class<?> corbaStubClass = null;
243     /**
244      * Initializes reflection method handles for RMI-IIOP.
245      * @exception ClassNotFoundException javax.rmi.CORBA.* not available
246      */
247     private static void initMethodHandles() throws ClassNotFoundException {
248         // Get javax.rmi.CORBA.Stub class
249         corbaStubClass = Class.forName("javax.rmi.CORBA.Stub");
250 
251         // Get javax.rmi.CORBA.Stub.connect(org.omg.CORBA.ORB) method
252 
253         try {
254             connectMethod = corbaStubClass.getMethod("connect",
255                 new Class<?>[] {org.omg.CORBA.ORB.class});
256         } catch (NoSuchMethodException e) {
257             throw new IllegalStateException(
258         "No method definition for javax.rmi.CORBA.Stub.connect(org.omg.CORBA.ORB)");
259         }
260 
261         // Get javax.rmi.PortableRemoteObject class
262         Class<?> proClass = Class.forName("javax.rmi.PortableRemoteObject");
263 
264         // Get javax.rmi.PortableRemoteObject.toStub(java.rmi.Remote) method
265         try {
266             toStubMethod = proClass.getMethod("toStub",
267                 new Class<?>[] {java.rmi.Remote.class});
268 
269         } catch (NoSuchMethodException e) {
270             throw new IllegalStateException(
271 "No method definition for javax.rmi.PortableRemoteObject.toStub(java.rmi.Remote)");
272         }
273     }
274 }