/* * @(#)IORImpl.java 1.32 05/05/27 * * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package com.sun.corba.se.impl.ior; import java.util.ListIterator ; import java.util.Iterator ; import java.util.Map ; import java.util.HashMap ; import java.io.StringWriter; import java.io.IOException; import javax.rmi.CORBA.Util; import org.omg.CORBA_2_3.portable.InputStream ; import org.omg.CORBA_2_3.portable.OutputStream ; import org.omg.IOP.TAG_INTERNET_IOP ; import com.sun.corba.se.spi.ior.ObjectId ; import com.sun.corba.se.spi.ior.TaggedProfileTemplate ; import com.sun.corba.se.spi.ior.TaggedProfile ; import com.sun.corba.se.spi.ior.IOR ; import com.sun.corba.se.spi.ior.IORTemplate ; import com.sun.corba.se.spi.ior.IORTemplateList ; import com.sun.corba.se.spi.ior.IdentifiableFactoryFinder ; import com.sun.corba.se.spi.ior.IdentifiableContainerBase ; import com.sun.corba.se.spi.ior.ObjectKeyTemplate ; import com.sun.corba.se.spi.ior.IORFactories ; import com.sun.corba.se.spi.ior.iiop.GIOPVersion; import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry; import com.sun.corba.se.spi.orb.ORB; import com.sun.corba.se.spi.logging.CORBALogDomains; import com.sun.corba.se.impl.encoding.MarshalOutputStream; import com.sun.corba.se.impl.encoding.EncapsOutputStream; import com.sun.corba.se.impl.orbutil.HexOutputStream; import com.sun.corba.se.impl.orbutil.ORBConstants; import com.sun.corba.se.impl.logging.IORSystemException ; // XXX remove this once getProfile is gone import com.sun.corba.se.spi.ior.iiop.IIOPProfile ; /** An IOR is represented as a list of profiles. * Only objects that extend TaggedProfile should be added to an IOR. * However, enforcing this restriction requires overriding all * of the addXXX methods inherited from List, so no check * is included here. * @author Ken Cavanaugh */ public class IORImpl extends IdentifiableContainerBase implements IOR { private String typeId; private ORB factory = null ; private boolean isCachedHashValue = false; private int cachedHashValue; IORSystemException wrapper ; public ORB getORB() { return factory ; } /* This variable is set directly from the constructors that take * an IORTemplate or IORTemplateList as arguments; otherwise it * is derived from the list of TaggedProfile instances on the first * call to getIORTemplates. Note that we assume that an IOR with * mutiple TaggedProfile instances has the same ObjectId in each * TaggedProfile, as otherwise the IOR could never be created through * an ObjectReferenceFactory. */ private IORTemplateList iortemps = null ; public boolean equals( Object obj ) { if (obj == null) return false ; if (!(obj instanceof IOR)) return false ; IOR other = (IOR)obj ; return super.equals( obj ) && typeId.equals( other.getTypeId() ) ; } public synchronized int hashCode() { if (! isCachedHashValue) { cachedHashValue = (super.hashCode() ^ typeId.hashCode()); isCachedHashValue = true; } return cachedHashValue; } /** Construct an empty IOR. This is needed for null object references. */ public IORImpl( ORB orb ) { this( orb, "" ) ; } public IORImpl( ORB orb, String typeid ) { factory = orb ; wrapper = IORSystemException.get( orb, CORBALogDomains.OA_IOR ) ; this.typeId = typeid ; } /** Construct an IOR from an IORTemplate by applying the same * object id to each TaggedProfileTemplate in the IORTemplate. */ public IORImpl( ORB orb, String typeId, IORTemplate iortemp, ObjectId id) { this( orb, typeId ) ; this.iortemps = IORFactories.makeIORTemplateList() ; this.iortemps.add( iortemp ) ; addTaggedProfiles( iortemp, id ) ; makeImmutable() ; } private void addTaggedProfiles( IORTemplate iortemp, ObjectId id ) { ObjectKeyTemplate oktemp = iortemp.getObjectKeyTemplate() ; Iterator templateIterator = iortemp.iterator() ; while (templateIterator.hasNext()) { TaggedProfileTemplate ptemp = (TaggedProfileTemplate)(templateIterator.next()) ; TaggedProfile profile = ptemp.create( oktemp, id ) ; add( profile ) ; } } /** Construct an IOR from an IORTemplate by applying the same * object id to each TaggedProfileTemplate in the IORTemplate. */ public IORImpl( ORB orb, String typeId, IORTemplateList iortemps, ObjectId id) { this( orb, typeId ) ; this.iortemps = iortemps ; Iterator iter = iortemps.iterator() ; while (iter.hasNext()) { IORTemplate iortemp = (IORTemplate)(iter.next()) ; addTaggedProfiles( iortemp, id ) ; } makeImmutable() ; } public IORImpl(InputStream is) { this( (ORB)(is.orb()), is.read_string() ) ; IdentifiableFactoryFinder finder = factory.getTaggedProfileFactoryFinder() ; EncapsulationUtility.readIdentifiableSequence( this, finder, is ) ; makeImmutable() ; } public String getTypeId() { return typeId ; } public void write(OutputStream os) { os.write_string( typeId ) ; EncapsulationUtility.writeIdentifiableSequence( this, os ) ; } public String stringify() { StringWriter bs; MarshalOutputStream s = new EncapsOutputStream(factory); s.putEndian(); write( (OutputStream)s ); bs = new StringWriter(); try { s.writeTo(new HexOutputStream(bs)); } catch (IOException ex) { throw wrapper.stringifyWriteError( ex ) ; } return ORBConstants.STRINGIFY_PREFIX + bs; } public synchronized void makeImmutable() { makeElementsImmutable() ; if (iortemps != null) iortemps.makeImmutable() ; super.makeImmutable() ; } public org.omg.IOP.IOR getIOPIOR() { EncapsOutputStream os = new EncapsOutputStream(factory); write(os); InputStream is = (InputStream) (os.create_input_stream()); return org.omg.IOP.IORHelper.read(is); } public boolean isNil() { // // The check for typeId length of 0 below is commented out // as a workaround for a bug in ORBs which send a // null objref with a non-empty typeId string. // return ((size() == 0) /* && (typeId.length() == 0) */); } public boolean isEquivalent(IOR ior) { Iterator myIterator = iterator() ; Iterator otherIterator = ior.iterator() ; while (myIterator.hasNext() && otherIterator.hasNext()) { TaggedProfile myProfile = (TaggedProfile)(myIterator.next()) ; TaggedProfile otherProfile = (TaggedProfile)(otherIterator.next()) ; if (!myProfile.isEquivalent( otherProfile )) return false ; } return myIterator.hasNext() == otherIterator.hasNext() ; } private void initializeIORTemplateList() { // Maps ObjectKeyTemplate to IORTemplate Map oktempToIORTemplate = new HashMap() ; iortemps = IORFactories.makeIORTemplateList() ; Iterator iter = iterator() ; ObjectId oid = null ; // used to check that all profiles have the same oid. while (iter.hasNext()) { TaggedProfile prof = (TaggedProfile)(iter.next()) ; TaggedProfileTemplate ptemp = prof.getTaggedProfileTemplate() ; ObjectKeyTemplate oktemp = prof.getObjectKeyTemplate() ; // Check that all oids for all profiles are the same: if they are not, // throw exception. if (oid == null) oid = prof.getObjectId() ; else if (!oid.equals( prof.getObjectId() )) throw wrapper.badOidInIorTemplateList() ; // Find or create the IORTemplate for oktemp. IORTemplate iortemp = (IORTemplate)(oktempToIORTemplate.get( oktemp )) ; if (iortemp == null) { iortemp = IORFactories.makeIORTemplate( oktemp ) ; oktempToIORTemplate.put( oktemp, iortemp ) ; iortemps.add( iortemp ) ; } iortemp.add( ptemp ) ; } iortemps.makeImmutable() ; } /** Return the IORTemplateList for this IOR. Will throw * exception if it is not possible to generate an IOR * from the IORTemplateList that is equal to this IOR, * which can only happen if not every TaggedProfile in the * IOR has the same ObjectId. */ public synchronized IORTemplateList getIORTemplates() { if (iortemps == null) initializeIORTemplateList() ; return iortemps ; } /** Return the first IIOPProfile in this IOR. * XXX THIS IS TEMPORARY FOR BACKWARDS COMPATIBILITY AND WILL BE REMOVED * SOON! */ public IIOPProfile getProfile() { IIOPProfile iop = null ; Iterator iter = iteratorById( TAG_INTERNET_IOP.value ) ; if (iter.hasNext()) iop = (IIOPProfile)(iter.next()) ; if (iop != null) return iop ; // if we come to this point then no IIOP Profile // is present. Therefore, throw an exception. throw wrapper.iorMustHaveIiopProfile() ; } }