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 /*
  27  * Licensed Materials - Property of IBM
  28  * RMI-IIOP v1.0
  29  * Copyright IBM Corp. 1998 1999  All Rights Reserved
  30  *
  31  */
  32 
  33 package javax.rmi.CORBA;
  34 
  35 import org.omg.CORBA.ORB;
  36 import org.omg.CORBA.INITIALIZE;
  37 import org.omg.CORBA_2_3.portable.ObjectImpl;
  38 
  39 import java.io.IOException;
  40 import java.rmi.RemoteException;
  41 import java.io.File;
  42 import java.io.FileInputStream;
  43 import java.net.MalformedURLException ;
  44 import java.security.AccessController;
  45 import java.security.PrivilegedAction;
  46 import java.util.Properties;
  47 import java.rmi.server.RMIClassLoader;
  48 
  49 import com.sun.corba.se.impl.orbutil.GetPropertyAction;
  50 
  51 
  52 /**
  53  * Base class from which all RMI-IIOP stubs must inherit.
  54  */
  55 public abstract class Stub extends ObjectImpl
  56     implements java.io.Serializable {
  57 
  58     private static final long serialVersionUID = 1087775603798577179L;
  59 
  60     // This can only be set at object construction time (no sync necessary).
  61     private transient StubDelegate stubDelegate = null;
  62     private static Class stubDelegateClass = null;
  63     private static final String StubClassKey = "javax.rmi.CORBA.StubClass";
  64 
  65     static {
  66         Object stubDelegateInstance = createDelegate(StubClassKey);
  67         if (stubDelegateInstance != null)
  68             stubDelegateClass = stubDelegateInstance.getClass();
  69     }
  70 
  71 
  72     /**
  73      * Returns a hash code value for the object which is the same for all stubs
  74      * that represent the same remote object.
  75      * @return the hash code value.
  76      */
  77     public int hashCode() {
  78 
  79         if (stubDelegate == null) {
  80             setDefaultDelegate();
  81         }
  82 
  83         if (stubDelegate != null) {
  84             return stubDelegate.hashCode(this);
  85         }
  86 
  87         return 0;
  88     }
  89 
  90     /**
  91      * Compares two stubs for equality. Returns <code>true</code> when used to compare stubs
  92      * that represent the same remote object, and <code>false</code> otherwise.
  93      * @param obj the reference object with which to compare.
  94      * @return <code>true</code> if this object is the same as the <code>obj</code>
  95      *          argument; <code>false</code> otherwise.
  96      */
  97     public boolean equals(java.lang.Object obj) {
  98 
  99         if (stubDelegate == null) {
 100             setDefaultDelegate();
 101         }
 102 
 103         if (stubDelegate != null) {
 104             return stubDelegate.equals(this, obj);
 105         }
 106 
 107         return false;
 108     }
 109 
 110     /**
 111      * Returns a string representation of this stub. Returns the same string
 112      * for all stubs that represent the same remote object.
 113      * @return a string representation of this stub.
 114      */
 115     public String toString() {
 116 
 117 
 118         if (stubDelegate == null) {
 119             setDefaultDelegate();
 120         }
 121 
 122         String ior;
 123         if (stubDelegate != null) {
 124             ior = stubDelegate.toString(this);
 125             if (ior == null) {
 126                 return super.toString();
 127             } else {
 128                 return ior;
 129             }
 130         }
 131         return super.toString();
 132     }
 133 
 134     /**
 135      * Connects this stub to an ORB. Required after the stub is deserialized
 136      * but not after it is demarshalled by an ORB stream. If an unconnected
 137      * stub is passed to an ORB stream for marshalling, it is implicitly
 138      * connected to that ORB. Application code should not call this method
 139      * directly, but should call the portable wrapper method
 140      * {@link javax.rmi.PortableRemoteObject#connect}.
 141      * @param orb the ORB to connect to.
 142      * @exception RemoteException if the stub is already connected to a different
 143      * ORB, or if the stub does not represent an exported remote or local object.
 144      */
 145     public void connect(ORB orb) throws RemoteException {
 146 
 147         if (stubDelegate == null) {
 148             setDefaultDelegate();
 149         }
 150 
 151         if (stubDelegate != null) {
 152             stubDelegate.connect(this, orb);
 153         }
 154 
 155     }
 156 
 157     /**
 158      * Serialization method to restore the IOR state.
 159      */
 160     private void readObject(java.io.ObjectInputStream stream)
 161         throws IOException, ClassNotFoundException {
 162 
 163         if (stubDelegate == null) {
 164             setDefaultDelegate();
 165         }
 166 
 167         if (stubDelegate != null) {
 168             stubDelegate.readObject(this, stream);
 169         }
 170 
 171     }
 172 
 173     /**
 174      * Serialization method to save the IOR state.
 175      * @serialData The length of the IOR type ID (int), followed by the IOR type ID
 176      * (byte array encoded using ISO8859-1), followed by the number of IOR profiles
 177      * (int), followed by the IOR profiles.  Each IOR profile is written as a
 178      * profile tag (int), followed by the length of the profile data (int), followed
 179      * by the profile data (byte array).
 180      */
 181     private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
 182 
 183         if (stubDelegate == null) {
 184             setDefaultDelegate();
 185         }
 186 
 187         if (stubDelegate != null) {
 188             stubDelegate.writeObject(this, stream);
 189         }
 190     }
 191 
 192     private void setDefaultDelegate() {
 193         if (stubDelegateClass != null) {
 194             try {
 195                  stubDelegate = (javax.rmi.CORBA.StubDelegate) stubDelegateClass.newInstance();
 196             } catch (Exception ex) {
 197             // what kind of exception to throw
 198             // delegate not set therefore it is null and will return default
 199             // values
 200             }
 201         }
 202     }
 203 
 204     // Same code as in PortableRemoteObject. Can not be shared because they
 205     // are in different packages and the visibility needs to be package for
 206     // security reasons. If you know a better solution how to share this code
 207     // then remove it from PortableRemoteObject. Also in Util.java
 208     private static Object createDelegate(String classKey) {
 209         String className = (String)
 210             AccessController.doPrivileged(new GetPropertyAction(classKey));
 211         if (className == null) {
 212             Properties props = getORBPropertiesFile();
 213             if (props != null) {
 214                 className = props.getProperty(classKey);
 215             }
 216         }
 217 
 218         if (className == null) {
 219             return new com.sun.corba.se.impl.javax.rmi.CORBA.StubDelegateImpl();
 220         }
 221 
 222         try {
 223             return loadDelegateClass(className).newInstance();
 224         } catch (ClassNotFoundException ex) {
 225             INITIALIZE exc = new INITIALIZE( "Cannot instantiate " + className);
 226             exc.initCause( ex ) ;
 227             throw exc ;
 228         } catch (Exception ex) {
 229             INITIALIZE exc = new INITIALIZE( "Error while instantiating" + className);
 230             exc.initCause( ex ) ;
 231             throw exc ;
 232         }
 233 
 234     }
 235 
 236     private static Class loadDelegateClass( String className )  throws ClassNotFoundException
 237     {
 238         try {
 239             ClassLoader loader = Thread.currentThread().getContextClassLoader();
 240             return Class.forName(className, false, loader);
 241         } catch (ClassNotFoundException e) {
 242             // ignore, then try RMIClassLoader
 243         }
 244 
 245         try {
 246             return RMIClassLoader.loadClass(className);
 247         } catch (MalformedURLException e) {
 248             String msg = "Could not load " + className + ": " + e.toString();
 249             ClassNotFoundException exc = new ClassNotFoundException( msg ) ;
 250             throw exc ;
 251         }
 252     }
 253 
 254     /**
 255      * Load the orb.properties file.
 256      */
 257     private static Properties getORBPropertiesFile () {
 258         return (Properties) AccessController.doPrivileged(new GetORBPropertiesFileAction());
 259     }
 260 
 261 }