/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.jboss.com.sun.corba.se.impl.ior;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.jboss.com.sun.corba.se.impl.encoding.EncapsOutputStream;
import org.jboss.com.sun.corba.se.impl.encoding.MarshalOutputStream;
import org.jboss.com.sun.corba.se.impl.logging.IORSystemException;
import org.jboss.com.sun.corba.se.impl.orbutil.HexOutputStream;
import org.jboss.com.sun.corba.se.impl.orbutil.ORBConstants;
import org.jboss.com.sun.corba.se.spi.ior.IOR;
import org.jboss.com.sun.corba.se.spi.ior.IORFactories;
import org.jboss.com.sun.corba.se.spi.ior.IORTemplate;
import org.jboss.com.sun.corba.se.spi.ior.IORTemplateList;
import org.jboss.com.sun.corba.se.spi.ior.IdentifiableContainerBase;
import org.jboss.com.sun.corba.se.spi.ior.IdentifiableFactoryFinder;
import org.jboss.com.sun.corba.se.spi.ior.ObjectId;
import org.jboss.com.sun.corba.se.spi.ior.ObjectKeyTemplate;
import org.jboss.com.sun.corba.se.spi.ior.TaggedProfile;
import org.jboss.com.sun.corba.se.spi.ior.TaggedProfileTemplate;
import org.jboss.com.sun.corba.se.spi.ior.iiop.IIOPProfile;
import org.jboss.com.sun.corba.se.spi.logging.CORBALogDomains;
import org.jboss.com.sun.corba.se.spi.orb.ORB;
import org.omg.CORBA_2_3.portable.InputStream;
import org.omg.CORBA_2_3.portable.OutputStream;
import org.omg.IOP.TAG_INTERNET_IOP;
/**
* 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<Object> 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<Object> 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<Object> myIterator = iterator();
Iterator<Object> 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<ObjectKeyTemplate, IORTemplate> oktempToIORTemplate = new HashMap<ObjectKeyTemplate, IORTemplate>();
iortemps = IORFactories.makeIORTemplateList();
Iterator<Object> 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 = 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<Object> 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();
}
}