1 /*
   2  * Copyright (c) 2000, 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 package com.sun.corba.se.impl.ior.iiop;
  27 
  28 import java.util.List ;
  29 import java.util.Iterator ;
  30 
  31 import org.omg.CORBA.SystemException ;
  32 
  33 import org.omg.CORBA_2_3.portable.OutputStream ;
  34 import org.omg.CORBA_2_3.portable.InputStream ;
  35 
  36 import org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS ;
  37 import org.omg.IOP.TAG_INTERNET_IOP;
  38 import org.omg.IOP.TAG_JAVA_CODEBASE;
  39 
  40 import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry ;
  41 
  42 import com.sun.corba.se.spi.oa.ObjectAdapter ;
  43 import com.sun.corba.se.spi.oa.ObjectAdapterFactory ;
  44 
  45 import com.sun.corba.se.spi.ior.ObjectId ;
  46 import com.sun.corba.se.spi.ior.ObjectAdapterId ;
  47 import com.sun.corba.se.spi.ior.TaggedProfile ;
  48 import com.sun.corba.se.spi.ior.TaggedProfileTemplate ;
  49 import com.sun.corba.se.spi.ior.ObjectKey ;
  50 import com.sun.corba.se.spi.ior.ObjectKeyTemplate ;
  51 import com.sun.corba.se.spi.ior.TaggedComponent ;
  52 import com.sun.corba.se.spi.ior.IdentifiableBase ;
  53 import com.sun.corba.se.spi.ior.IORFactories ;
  54 import com.sun.corba.se.spi.ior.ObjectKeyFactory ;
  55 
  56 import com.sun.corba.se.spi.ior.iiop.IIOPAddress ;
  57 import com.sun.corba.se.spi.ior.iiop.IIOPProfile ;
  58 import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ;
  59 import com.sun.corba.se.spi.ior.iiop.IIOPFactories ;
  60 import com.sun.corba.se.spi.ior.iiop.GIOPVersion ;
  61 import com.sun.corba.se.spi.ior.iiop.JavaCodebaseComponent ;
  62 
  63 import com.sun.corba.se.spi.orb.ORB ;
  64 import com.sun.corba.se.spi.orb.ORBVersion ;
  65 
  66 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  67 
  68 import com.sun.corba.se.impl.ior.EncapsulationUtility ;
  69 
  70 import com.sun.corba.se.impl.encoding.EncapsInputStream ;
  71 import com.sun.corba.se.impl.encoding.EncapsOutputStream ;
  72 
  73 import sun.corba.EncapsInputStreamFactory;
  74 
  75 import com.sun.corba.se.impl.util.JDKBridge;
  76 
  77 import com.sun.corba.se.impl.logging.IORSystemException;
  78 
  79 public class IIOPProfileImpl extends IdentifiableBase implements IIOPProfile
  80 {
  81     private ORB orb ;
  82     private IORSystemException wrapper ;
  83     private ObjectId oid;
  84     private IIOPProfileTemplate proftemp;
  85     private ObjectKeyTemplate oktemp ;
  86 
  87     // Cached lookups
  88     protected String codebase = null ;
  89     protected boolean cachedCodebase = false;
  90 
  91     private boolean checkedIsLocal = false ;
  92     private boolean cachedIsLocal = false ;
  93 
  94     // initialize-on-demand holder
  95     private static class LocalCodeBaseSingletonHolder {
  96         public static JavaCodebaseComponent comp ;
  97 
  98         static {
  99             String localCodebase = JDKBridge.getLocalCodebase() ;
 100             if (localCodebase == null)
 101                 comp = null ;
 102             else
 103                 comp = IIOPFactories.makeJavaCodebaseComponent(
 104                     localCodebase ) ;
 105         }
 106     }
 107 
 108     private GIOPVersion giopVersion = null;
 109 
 110     public boolean equals( Object obj )
 111     {
 112         if (!(obj instanceof IIOPProfileImpl))
 113             return false ;
 114 
 115         IIOPProfileImpl other = (IIOPProfileImpl)obj ;
 116 
 117         return oid.equals( other.oid ) && proftemp.equals( other.proftemp ) &&
 118             oktemp.equals( other.oktemp ) ;
 119     }
 120 
 121     public int hashCode()
 122     {
 123         return oid.hashCode() ^ proftemp.hashCode() ^ oktemp.hashCode() ;
 124     }
 125 
 126     public ObjectId getObjectId()
 127     {
 128         return oid ;
 129     }
 130 
 131     public TaggedProfileTemplate getTaggedProfileTemplate()
 132     {
 133         return proftemp ;
 134     }
 135 
 136     public ObjectKeyTemplate getObjectKeyTemplate()
 137     {
 138         return oktemp ;
 139     }
 140 
 141     private IIOPProfileImpl( ORB orb )
 142     {
 143         this.orb = orb ;
 144         wrapper = IORSystemException.get( orb,
 145             CORBALogDomains.OA_IOR ) ;
 146     }
 147 
 148     public IIOPProfileImpl( ORB orb, ObjectKeyTemplate oktemp, ObjectId oid,
 149         IIOPProfileTemplate proftemp )
 150     {
 151         this( orb ) ;
 152         this.oktemp = oktemp ;
 153         this.oid = oid ;
 154         this.proftemp = proftemp ;
 155     }
 156 
 157     public IIOPProfileImpl( InputStream is )
 158     {
 159         this( (ORB)(is.orb()) ) ;
 160         init( is ) ;
 161     }
 162 
 163     public IIOPProfileImpl( ORB orb, org.omg.IOP.TaggedProfile profile)
 164     {
 165         this( orb ) ;
 166 
 167         if (profile == null || profile.tag != TAG_INTERNET_IOP.value ||
 168             profile.profile_data == null) {
 169             throw wrapper.invalidTaggedProfile() ;
 170         }
 171 
 172         EncapsInputStream istr = EncapsInputStreamFactory.newEncapsInputStream((ORB)orb, profile.profile_data,
 173                 profile.profile_data.length);
 174         istr.consumeEndian();
 175         init( istr ) ;
 176     }
 177 
 178     private void init( InputStream istr )
 179     {
 180         // First, read all of the IIOP IOR data
 181         GIOPVersion version = new GIOPVersion() ;
 182         version.read( istr ) ;
 183         IIOPAddress primary = new IIOPAddressImpl( istr ) ;
 184         byte[] key = EncapsulationUtility.readOctets( istr ) ;
 185 
 186         ObjectKey okey = orb.getObjectKeyFactory().create( key ) ;
 187         oktemp = okey.getTemplate() ;
 188         oid = okey.getId() ;
 189 
 190         proftemp = IIOPFactories.makeIIOPProfileTemplate( orb,
 191             version, primary ) ;
 192 
 193         // Handle any tagged components (if applicable)
 194         if (version.getMinor() > 0)
 195             EncapsulationUtility.readIdentifiableSequence( proftemp,
 196                 orb.getTaggedComponentFactoryFinder(), istr ) ;
 197 
 198         // If there is no codebase in this IOR and there IS a
 199         // java.rmi.server.codebase property set, we need to
 200         // update the IOR with the local codebase.  Note that
 201         // there is only one instance of the local codebase, but it
 202         // can be safely shared in multiple IORs since it is immutable.
 203         if (uncachedGetCodeBase() == null) {
 204             JavaCodebaseComponent jcc = LocalCodeBaseSingletonHolder.comp ;
 205 
 206             if (jcc != null) {
 207                 if (version.getMinor() > 0)
 208                     proftemp.add( jcc ) ;
 209 
 210                 codebase = jcc.getURLs() ;
 211             }
 212 
 213             // Whether codebase is null or not, we have it,
 214             // and so getCodebase ned never call uncachedGetCodebase.
 215             cachedCodebase = true;
 216         }
 217     }
 218 
 219     public void writeContents(OutputStream os)
 220     {
 221         proftemp.write( oktemp, oid, os ) ;
 222     }
 223 
 224     public int getId()
 225     {
 226         return proftemp.getId() ;
 227     }
 228 
 229     public boolean isEquivalent( TaggedProfile prof )
 230     {
 231         if (!(prof instanceof IIOPProfile))
 232             return false ;
 233 
 234         IIOPProfile other = (IIOPProfile)prof ;
 235 
 236         return oid.equals( other.getObjectId() ) &&
 237                proftemp.isEquivalent( other.getTaggedProfileTemplate() ) &&
 238                oktemp.equals( other.getObjectKeyTemplate() ) ;
 239     }
 240 
 241     public ObjectKey getObjectKey()
 242     {
 243         ObjectKey result = IORFactories.makeObjectKey( oktemp, oid ) ;
 244         return result ;
 245     }
 246 
 247     public org.omg.IOP.TaggedProfile getIOPProfile()
 248     {
 249         EncapsOutputStream os =
 250             sun.corba.OutputStreamFactory.newEncapsOutputStream(orb);
 251         os.write_long( getId() ) ;
 252         write( os ) ;
 253         InputStream is = (InputStream)(os.create_input_stream()) ;
 254         return org.omg.IOP.TaggedProfileHelper.read( is ) ;
 255     }
 256 
 257     private String uncachedGetCodeBase() {
 258         Iterator iter = proftemp.iteratorById( TAG_JAVA_CODEBASE.value ) ;
 259 
 260         if (iter.hasNext()) {
 261             JavaCodebaseComponent jcbc = (JavaCodebaseComponent)(iter.next()) ;
 262             return jcbc.getURLs() ;
 263         }
 264 
 265         return null ;
 266     }
 267 
 268     public synchronized String getCodebase() {
 269         if (!cachedCodebase) {
 270             cachedCodebase = true ;
 271             codebase = uncachedGetCodeBase() ;
 272         }
 273 
 274         return codebase ;
 275     }
 276 
 277     /**
 278      * @return the ORBVersion associated with the object key in the IOR.
 279      */
 280     public ORBVersion getORBVersion() {
 281         return oktemp.getORBVersion();
 282     }
 283 
 284     public synchronized boolean isLocal()
 285     {
 286         if (!checkedIsLocal) {
 287             checkedIsLocal = true ;
 288             String host = proftemp.getPrimaryAddress().getHost() ;
 289 
 290             cachedIsLocal = orb.isLocalHost(host) &&
 291                 orb.isLocalServerId(oktemp.getSubcontractId(),
 292                                            oktemp.getServerId()) &&
 293                 orb.getLegacyServerSocketManager()
 294                     .legacyIsLocalServerPort(
 295                         proftemp.getPrimaryAddress().getPort());
 296         }
 297 
 298         return cachedIsLocal ;
 299     }
 300 
 301     /** Return the servant for this IOR, if it is local AND if the OA that
 302      * implements this objref supports direct access to servants outside of an
 303      * invocation.
 304      * XXX revisit: do we want this at all?  If we do, it might move to the
 305      * ObjectKeyTemplate instead.
 306      */
 307     public java.lang.Object getServant()
 308     {
 309         if (!isLocal())
 310             return null ;
 311 
 312         RequestDispatcherRegistry scr = orb.getRequestDispatcherRegistry() ;
 313         ObjectAdapterFactory oaf = scr.getObjectAdapterFactory(
 314             oktemp.getSubcontractId() ) ;
 315 
 316         ObjectAdapterId oaid = oktemp.getObjectAdapterId() ;
 317         ObjectAdapter oa = null ;
 318 
 319         try {
 320             oa = oaf.find( oaid ) ;
 321         } catch (SystemException exc) {
 322             // Could not find the OA, so just return null.
 323             // This usually happens when POAs are being deleted,
 324             // and the POA always return null for getLocalServant anyway.
 325             wrapper.getLocalServantFailure( exc, oaid.toString() ) ;
 326             return null ;
 327         }
 328 
 329         byte[] boid = oid.getId() ;
 330         java.lang.Object servant = oa.getLocalServant( boid ) ;
 331         return servant ;
 332     }
 333 
 334     /**
 335      * Return GIOPVersion for this IOR.
 336      * Requests created against this IOR will be of the
 337      * return Version.
 338      */
 339     public synchronized GIOPVersion getGIOPVersion()
 340     {
 341         return proftemp.getGIOPVersion() ;
 342     }
 343 
 344     public void makeImmutable()
 345     {
 346         proftemp.makeImmutable() ;
 347     }
 348 }