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 }