1 /* 2 * Copyright (c) 1998, 2013, 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 32 package javax.rmi; 33 34 import java.lang.reflect.Method ; 35 36 import org.omg.CORBA.INITIALIZE; 37 import javax.rmi.CORBA.Util; 38 39 import java.rmi.RemoteException; 40 import java.rmi.NoSuchObjectException; 41 import java.rmi.Remote; 42 import java.io.File; 43 import java.io.FileInputStream; 44 import java.util.Properties; 45 import java.net.MalformedURLException ; 46 import java.security.AccessController; 47 import java.security.PrivilegedAction; 48 import java.rmi.server.RMIClassLoader; 49 50 import com.sun.corba.se.impl.orbutil.GetPropertyAction; 51 52 /** 53 * Server implementation objects may either inherit from 54 * javax.rmi.PortableRemoteObject or they may implement a remote interface 55 * and then use the exportObject method to register themselves as a server object. 56 * The toStub method takes a server implementation and returns a stub that 57 * can be used to access that server object. 58 * The connect method makes a Remote object ready for remote communication. 59 * The unexportObject method is used to deregister a server object, allowing it to become 60 * available for garbage collection. 61 * The narrow method takes an object reference or abstract interface type and 62 * attempts to narrow it to conform to 63 * the given interface. If the operation is successful the result will be an 64 * object of the specified type, otherwise an exception will be thrown. 65 * 66 * <p>See also {@extLink rmi_iiop_guides RMI-IIOP developer's guides}.</p> 67 */ 68 public class PortableRemoteObject { 69 70 private static final javax.rmi.CORBA.PortableRemoteObjectDelegate proDelegate; 71 72 private static final String PortableRemoteObjectClassKey = 73 "javax.rmi.CORBA.PortableRemoteObjectClass"; 74 75 static { 76 proDelegate = (javax.rmi.CORBA.PortableRemoteObjectDelegate) 77 createDelegate(PortableRemoteObjectClassKey); 78 } 79 80 /** 81 * Initializes the object by calling <code>exportObject(this)</code>. 82 * @exception RemoteException if export fails. 83 */ 84 protected PortableRemoteObject() throws RemoteException { 85 if (proDelegate != null) { 86 PortableRemoteObject.exportObject((Remote)this); 87 } 88 } 89 90 /** 91 * Makes a server object ready to receive remote calls. Note 92 * that subclasses of PortableRemoteObject do not need to call this 93 * method, as it is called by the constructor. 94 * @param obj the server object to export. 95 * @exception RemoteException if export fails. 96 */ 97 public static void exportObject(Remote obj) 98 throws RemoteException { 99 100 // Let the delegate do everything, including error handling. 101 if (proDelegate != null) { 102 proDelegate.exportObject(obj); 103 } 104 } 105 106 /** 107 * Returns a stub for the given server object. 108 * @param obj the server object for which a stub is required. Must either be a subclass 109 * of PortableRemoteObject or have been previously the target of a call to 110 * {@link #exportObject}. 111 * @return the most derived stub for the object. 112 * @exception NoSuchObjectException if a stub cannot be located for the given server object. 113 */ 114 public static Remote toStub (Remote obj) 115 throws NoSuchObjectException { 116 117 if (proDelegate != null) { 118 return proDelegate.toStub(obj); 119 } 120 return null; 121 } 122 123 /** 124 * Deregisters a server object from the runtime, allowing the object to become 125 * available for garbage collection. 126 * @param obj the object to unexport. 127 * @exception NoSuchObjectException if the remote object is not 128 * currently exported. 129 */ 130 public static void unexportObject(Remote obj) 131 throws NoSuchObjectException { 132 133 if (proDelegate != null) { 134 proDelegate.unexportObject(obj); 135 } 136 137 } 138 139 /** 140 * Checks to ensure that an object of a remote or abstract interface type 141 * can be cast to a desired type. 142 * @param narrowFrom the object to check. 143 * @param narrowTo the desired type. 144 * @return an object which can be cast to the desired type. 145 * @throws ClassCastException if narrowFrom cannot be cast to narrowTo. 146 */ 147 public static java.lang.Object narrow ( java.lang.Object narrowFrom, 148 java.lang.Class narrowTo) 149 throws ClassCastException { 150 151 if (proDelegate != null) { 152 return proDelegate.narrow(narrowFrom, narrowTo); 153 } 154 return null; 155 156 } 157 158 /** 159 * Makes a Remote object ready for remote communication. This normally 160 * happens implicitly when the object is sent or received as an argument 161 * on a remote method call, but in some circumstances it is useful to 162 * perform this action by making an explicit call. See the 163 * {@link javax.rmi.CORBA.Stub#connect} method for more information. 164 * @param target the object to connect. 165 * @param source a previously connected object. 166 * @throws RemoteException if <code>source</code> is not connected 167 * or if <code>target</code> is already connected to a different ORB than 168 * <code>source</code>. 169 */ 170 public static void connect (Remote target, Remote source) 171 throws RemoteException { 172 173 if (proDelegate != null) { 174 proDelegate.connect(target, source); 175 } 176 177 } 178 179 // Same code as in javax.rmi.CORBA.Util. Can not be shared because they 180 // are in different packages and the visibility needs to be package for 181 // security reasons. If you know a better solution how to share this code 182 // then remove it from here. 183 private static Object createDelegate(String classKey) { 184 String className = (String) 185 AccessController.doPrivileged(new GetPropertyAction(classKey)); 186 if (className == null) { 187 Properties props = getORBPropertiesFile(); 188 if (props != null) { 189 className = props.getProperty(classKey); 190 } 191 } 192 if (className == null) { 193 return new com.sun.corba.se.impl.javax.rmi.PortableRemoteObject(); 194 } 195 196 try { 197 return (Object) loadDelegateClass(className).newInstance(); 198 } catch (ClassNotFoundException ex) { 199 INITIALIZE exc = new INITIALIZE( "Cannot instantiate " + className); 200 exc.initCause( ex ) ; 201 throw exc ; 202 } catch (Exception ex) { 203 INITIALIZE exc = new INITIALIZE( "Error while instantiating" + className); 204 exc.initCause( ex ) ; 205 throw exc ; 206 } 207 208 } 209 210 private static Class loadDelegateClass( String className ) throws ClassNotFoundException 211 { 212 try { 213 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 214 return Class.forName(className, false, loader); 215 } catch (ClassNotFoundException e) { 216 // ignore, then try RMIClassLoader 217 } 218 219 try { 220 return RMIClassLoader.loadClass(className); 221 } catch (MalformedURLException e) { 222 String msg = "Could not load " + className + ": " + e.toString(); 223 ClassNotFoundException exc = new ClassNotFoundException( msg ) ; 224 throw exc ; 225 } 226 } 227 228 /** 229 * Load the orb.properties file. 230 */ 231 private static Properties getORBPropertiesFile () { 232 return (Properties) AccessController.doPrivileged(new GetORBPropertiesFileAction()); 233 } 234 } 235 236 class GetORBPropertiesFileAction implements PrivilegedAction { 237 private boolean debug = false ; 238 239 public GetORBPropertiesFileAction () { 240 } 241 242 private String getSystemProperty(final String name) { 243 // This will not throw a SecurityException because this 244 // class was loaded from rt.jar using the bootstrap classloader. 245 String propValue = (String) AccessController.doPrivileged( 246 new PrivilegedAction() { 247 public java.lang.Object run() { 248 return System.getProperty(name); 249 } 250 } 251 ); 252 253 return propValue; 254 } 255 256 private void getPropertiesFromFile( Properties props, String fileName ) 257 { 258 try { 259 File file = new File( fileName ) ; 260 if (!file.exists()) 261 return ; 262 263 FileInputStream in = new FileInputStream( file ) ; 264 265 try { 266 props.load( in ) ; 267 } finally { 268 in.close() ; 269 } 270 } catch (Exception exc) { 271 if (debug) 272 System.out.println( "ORB properties file " + fileName + 273 " not found: " + exc) ; 274 } 275 } 276 277 public Object run() 278 { 279 Properties defaults = new Properties() ; 280 281 String javaHome = getSystemProperty( "java.home" ) ; 282 String fileName = javaHome + File.separator + "lib" + File.separator + 283 "orb.properties" ; 284 285 getPropertiesFromFile( defaults, fileName ) ; 286 287 Properties results = new Properties( defaults ) ; 288 289 String userHome = getSystemProperty( "user.home" ) ; 290 fileName = userHome + File.separator + "orb.properties" ; 291 292 getPropertiesFromFile( results, fileName ) ; 293 return results ; 294 } 295 }