1 /*
   2  * Copyright (c) 1998, 2016, 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.CORBA;
  33 
  34 import java.rmi.RemoteException;
  35 
  36 import org.omg.CORBA.ORB;
  37 import org.omg.CORBA.INITIALIZE;
  38 import org.omg.CORBA.SystemException;
  39 import org.omg.CORBA.Any;
  40 import org.omg.CORBA.portable.InputStream;
  41 import org.omg.CORBA.portable.OutputStream;
  42 import org.omg.CORBA.portable.ObjectImpl;
  43 
  44 import javax.rmi.CORBA.Tie;
  45 import java.rmi.Remote;
  46 import java.io.File;
  47 import java.io.FileInputStream;
  48 import java.io.SerializablePermission;
  49 import java.net.MalformedURLException ;
  50 import java.security.AccessController;
  51 import java.security.PrivilegedAction;
  52 import java.util.Properties;
  53 import java.rmi.server.RMIClassLoader;
  54 
  55 import com.sun.corba.se.impl.orbutil.GetPropertyAction;
  56 
  57 /**
  58  * Provides utility methods that can be used by stubs and ties to
  59  * perform common operations.
  60  */
  61 public class Util {
  62 
  63     // This can only be set at static initialization time (no sync necessary).
  64     private static final javax.rmi.CORBA.UtilDelegate utilDelegate;
  65     private static final String UtilClassKey = "javax.rmi.CORBA.UtilClass";
  66 
  67     static {
  68         utilDelegate = (javax.rmi.CORBA.UtilDelegate)createDelegate(UtilClassKey);
  69     }
  70 
  71     private Util(){}
  72 
  73     /**
  74      * Maps a SystemException to a RemoteException.
  75      * @param ex the SystemException to map.
  76      * @return the mapped exception.
  77      */
  78     public static RemoteException mapSystemException(SystemException ex) {
  79 
  80         if (utilDelegate != null) {
  81             return utilDelegate.mapSystemException(ex);
  82         }
  83         return null;
  84     }
  85 
  86     /**
  87      * Writes any java.lang.Object as a CORBA any.
  88      * @param out the stream in which to write the any.
  89      * @param obj the object to write as an any.
  90      */
  91     public static void writeAny(OutputStream out, Object obj) {
  92 
  93         if (utilDelegate != null) {
  94             utilDelegate.writeAny(out, obj);
  95         }
  96     }
  97 
  98     /**
  99      * Reads a java.lang.Object as a CORBA any.
 100      * @param in the stream from which to read the any.
 101      * @return the object read from the stream.
 102      */
 103     public static Object readAny(InputStream in) {
 104 
 105         if (utilDelegate != null) {
 106             return utilDelegate.readAny(in);
 107         }
 108         return null;
 109     }
 110 
 111     /**
 112      * Writes a java.lang.Object as a CORBA Object. If {@code obj} is
 113      * an exported RMI-IIOP server object, the tie is found
 114      * and wired to {@code obj}, then written to
 115      * {@code out.write_Object(org.omg.CORBA.Object)}.
 116      * If {@code obj} is a CORBA Object, it is written to
 117      * {@code out.write_Object(org.omg.CORBA.Object)}.
 118      * @param out the stream in which to write the object.
 119      * @param obj the object to write.
 120      */
 121     public static void writeRemoteObject(OutputStream out,
 122                                          java.lang.Object obj) {
 123 
 124         if (utilDelegate != null) {
 125             utilDelegate.writeRemoteObject(out, obj);
 126         }
 127 
 128     }
 129 
 130     /**
 131      * Writes a java.lang.Object as either a value or a CORBA Object.
 132      * If {@code obj} is a value object or a stub object, it is written to
 133      * {@code out.write_abstract_interface(java.lang.Object)}.
 134      * If {@code obj} is an exported
 135      * RMI-IIOP server object, the tie is found and wired to {@code obj},
 136      * then written to {@code out.write_abstract_interface(java.lang.Object)}.
 137      * @param out the stream in which to write the object.
 138      * @param obj the object to write.
 139      */
 140     public static void writeAbstractObject(OutputStream out,
 141                                            java.lang.Object obj) {
 142 
 143         if (utilDelegate != null) {
 144             utilDelegate.writeAbstractObject(out, obj);
 145         }
 146     }
 147 
 148     /**
 149      * Registers a target for a tie. Adds the tie to an internal table and calls
 150      * {@link Tie#setTarget} on the tie object.
 151      * @param tie the tie to register.
 152      * @param target the target for the tie.
 153      */
 154     public static void registerTarget(javax.rmi.CORBA.Tie tie,
 155                                       java.rmi.Remote target) {
 156 
 157         if (utilDelegate != null) {
 158             utilDelegate.registerTarget(tie, target);
 159         }
 160 
 161     }
 162 
 163     /**
 164      * Removes the associated tie from an internal table
 165      * and calls {@link Tie#deactivate}
 166      * to deactivate the object.
 167      * @param target the object to unexport.
 168      */
 169     public static void unexportObject(java.rmi.Remote target)
 170         throws java.rmi.NoSuchObjectException
 171     {
 172 
 173         if (utilDelegate != null) {
 174             utilDelegate.unexportObject(target);
 175         }
 176 
 177     }
 178 
 179     /**
 180      * Returns the tie (if any) for a given target object.
 181      * @return the tie or null if no tie is registered for the given target.
 182      */
 183     public static Tie getTie (Remote target) {
 184 
 185         if (utilDelegate != null) {
 186             return utilDelegate.getTie(target);
 187         }
 188         return null;
 189     }
 190 
 191 
 192     /**
 193      * Returns a singleton instance of a class that implements the
 194      * {@link ValueHandler} interface.
 195      * @return a class which implements the ValueHandler interface.
 196      */
 197     public static ValueHandler createValueHandler() {
 198 
 199         isCustomSerializationPermitted();
 200 
 201         if (utilDelegate != null) {
 202             return utilDelegate.createValueHandler();
 203         }
 204         return null;
 205     }
 206 
 207     /**
 208      * Returns the codebase, if any, for the given class.
 209      * @param clz the class to get a codebase for.
 210      * @return a space-separated list of URLs, or null.
 211      */
 212     public static String getCodebase(java.lang.Class clz) {
 213         if (utilDelegate != null) {
 214             return utilDelegate.getCodebase(clz);
 215         }
 216         return null;
 217     }
 218 
 219     /**
 220      * Returns a class instance for the specified class.
 221      * <P>The spec for this method is the "Java to IDL language
 222      * mapping", ptc/00-01-06.
 223      * <P>In Java SE Platform, this method works as follows:
 224      * <UL><LI>Find the first non-null {@code ClassLoader} on the
 225      * call stack and attempt to load the class using this
 226      * {@code ClassLoader}.
 227      * <LI>If the first step fails, and if {@code remoteCodebase}
 228      * is non-null and
 229      * {@code useCodebaseOnly} is false, then call
 230      * {@code java.rmi.server.RMIClassLoader.loadClass(remoteCodebase, className)}.
 231      * <LI>If {@code remoteCodebase} is null or {@code useCodebaseOnly}
 232      * is true, then call {@code java.rmi.server.RMIClassLoader.loadClass(className)}.
 233      * <LI>If a class was not successfully loaded by step 1, 2, or 3,
 234      * and {@code loader} is non-null, then call {@code loader.loadClass(className)}.
 235      * <LI>If a class was successfully loaded by step 1, 2, 3, or 4, then
 236      *  return the loaded class, else throw {@code ClassNotFoundException}.
 237      * </UL>
 238      *
 239      * @param className the name of the class.
 240      * @param remoteCodebase a space-separated list of URLs at which
 241      * the class might be found. May be null.
 242      * @param loader a {@code ClassLoader} that may be used to
 243      * load the class if all other methods fail.
 244      * @return the {@code Class} object representing the loaded class.
 245      * @exception ClassNotFoundException if class cannot be loaded.
 246      */
 247     public static Class loadClass(String className,
 248                                   String remoteCodebase,
 249                                   ClassLoader loader)
 250         throws ClassNotFoundException {
 251         if (utilDelegate != null) {
 252             return utilDelegate.loadClass(className,remoteCodebase,loader);
 253         }
 254         return null ;
 255     }
 256 
 257 
 258     /**
 259      * The {@code isLocal} method has the same semantics as the
 260      * {@code ObjectImpl._is_local}
 261      * method, except that it can throw a {@code RemoteException}.
 262      *
 263      * The {@code _is_local()} method is provided so that stubs may determine if a
 264      * particular object is implemented by a local servant and hence local
 265      * invocation APIs may be used.
 266      *
 267      * @param stub the stub to test.
 268      *
 269      * @return The {@code _is_local()} method returns true if
 270      * the servant incarnating the object is located in the same process as
 271      * the stub and they both share the same ORB instance.  The {@code _is_local()}
 272      * method returns false otherwise. The default behavior of {@code _is_local()} is
 273      * to return false.
 274      *
 275      * @throws RemoteException The Java to IDL specification does not
 276      * specify the conditions that cause a {@code RemoteException} to be thrown.
 277      */
 278     public static boolean isLocal(Stub stub) throws RemoteException {
 279 
 280         if (utilDelegate != null) {
 281             return utilDelegate.isLocal(stub);
 282         }
 283 
 284         return false;
 285     }
 286 
 287     /**
 288      * Wraps an exception thrown by an implementation
 289      * method.  It returns the corresponding client-side exception.
 290      * @param orig the exception to wrap.
 291      * @return the wrapped exception.
 292      */
 293     public static RemoteException wrapException(Throwable orig) {
 294 
 295         if (utilDelegate != null) {
 296             return utilDelegate.wrapException(orig);
 297         }
 298 
 299         return null;
 300     }
 301 
 302     /**
 303      * Copies or connects an array of objects. Used by local stubs
 304      * to copy any number of actual parameters, preserving sharing
 305      * across parameters as necessary to support RMI semantics.
 306      * @param obj the objects to copy or connect.
 307      * @param orb the ORB.
 308      * @return the copied or connected objects.
 309      * @exception RemoteException if any object could not be copied or connected.
 310      */
 311     public static Object[] copyObjects (Object[] obj, ORB orb)
 312         throws RemoteException {
 313 
 314         if (utilDelegate != null) {
 315             return utilDelegate.copyObjects(obj, orb);
 316         }
 317 
 318         return null;
 319     }
 320 
 321     /**
 322      * Copies or connects an object. Used by local stubs to copy
 323      * an actual parameter, result object, or exception.
 324      * @param obj the object to copy.
 325      * @param orb the ORB.
 326      * @return the copy or connected object.
 327      * @exception RemoteException if the object could not be copied or connected.
 328      */
 329     public static Object copyObject (Object obj, ORB orb)
 330         throws RemoteException {
 331 
 332         if (utilDelegate != null) {
 333             return utilDelegate.copyObject(obj, orb);
 334         }
 335         return null;
 336     }
 337 
 338     // Same code as in PortableRemoteObject. Can not be shared because they
 339     // are in different packages and the visibility needs to be package for
 340     // security reasons. If you know a better solution how to share this code
 341     // then remove it from PortableRemoteObject. Also in Stub.java
 342     private static Object createDelegate(String classKey) {
 343 
 344         String className = (String)
 345             AccessController.doPrivileged(new GetPropertyAction(classKey));
 346         if (className == null) {
 347             Properties props = getORBPropertiesFile();
 348             if (props != null) {
 349                 className = props.getProperty(classKey);
 350             }
 351         }
 352         if (className == null) {
 353             return new com.sun.corba.se.impl.javax.rmi.CORBA.Util();
 354         }
 355 
 356         try {
 357             return loadDelegateClass(className).newInstance();
 358         } catch (ClassNotFoundException ex) {
 359             INITIALIZE exc = new INITIALIZE( "Cannot instantiate " + className);
 360             exc.initCause( ex ) ;
 361             throw exc ;
 362         } catch (Exception ex) {
 363             INITIALIZE exc = new INITIALIZE( "Error while instantiating" + className);
 364             exc.initCause( ex ) ;
 365             throw exc ;
 366         }
 367     }
 368 
 369     private static Class loadDelegateClass( String className )  throws ClassNotFoundException
 370     {
 371         try {
 372             ClassLoader loader = Thread.currentThread().getContextClassLoader();
 373             return Class.forName(className, false, loader);
 374         } catch (ClassNotFoundException e) {
 375             // ignore, then try RMIClassLoader
 376         }
 377 
 378         try {
 379             return RMIClassLoader.loadClass(className);
 380         } catch (MalformedURLException e) {
 381             String msg = "Could not load " + className + ": " + e.toString();
 382             ClassNotFoundException exc = new ClassNotFoundException( msg ) ;
 383             throw exc ;
 384         }
 385     }
 386     /**
 387      * Load the orb.properties file.
 388      */
 389     private static Properties getORBPropertiesFile ()
 390     {
 391         return (Properties) AccessController.doPrivileged(
 392             new GetORBPropertiesFileAction());
 393     }
 394 
 395     private static void isCustomSerializationPermitted() {
 396         SecurityManager sm = System.getSecurityManager();
 397         if ( sm != null) {
 398             // check that a serialization permission has been
 399             // set to allow the loading of the Util delegate
 400             // which provides access to custom ValueHandler
 401             sm.checkPermission(new SerializablePermission(
 402                     "enableCustomValueHandler"));
 403 }
 404     }
 405 }