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