IORImpl.java revision 608:7e06bf1dcb09
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
26package com.sun.corba.se.impl.ior;
27
28import java.util.ListIterator ;
29import java.util.Iterator ;
30import java.util.Map ;
31import java.util.HashMap ;
32
33import java.io.StringWriter;
34import java.io.IOException;
35
36import javax.rmi.CORBA.Util;
37
38import org.omg.CORBA_2_3.portable.InputStream ;
39import org.omg.CORBA_2_3.portable.OutputStream ;
40
41import org.omg.IOP.TAG_INTERNET_IOP ;
42
43import com.sun.corba.se.spi.ior.ObjectId ;
44import com.sun.corba.se.spi.ior.TaggedProfileTemplate ;
45import com.sun.corba.se.spi.ior.TaggedProfile ;
46import com.sun.corba.se.spi.ior.IOR ;
47import com.sun.corba.se.spi.ior.IORTemplate ;
48import com.sun.corba.se.spi.ior.IORTemplateList ;
49import com.sun.corba.se.spi.ior.IdentifiableFactoryFinder ;
50import com.sun.corba.se.spi.ior.IdentifiableContainerBase ;
51import com.sun.corba.se.spi.ior.ObjectKeyTemplate ;
52import com.sun.corba.se.spi.ior.IORFactories ;
53
54import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
55
56import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry;
57
58import com.sun.corba.se.spi.orb.ORB;
59
60import com.sun.corba.se.spi.logging.CORBALogDomains;
61
62import com.sun.corba.se.impl.encoding.MarshalOutputStream;
63
64import com.sun.corba.se.impl.encoding.EncapsOutputStream;
65
66import com.sun.corba.se.impl.orbutil.HexOutputStream;
67import com.sun.corba.se.impl.orbutil.ORBConstants;
68
69import com.sun.corba.se.impl.logging.IORSystemException ;
70
71// XXX remove this once getProfile is gone
72import com.sun.corba.se.spi.ior.iiop.IIOPProfile ;
73
74/** An IOR is represented as a list of profiles.
75* Only objects that extend TaggedProfile should be added to an IOR.
76* However, enforcing this restriction requires overriding all
77* of the addXXX methods inherited from List, so no check
78* is included here.
79* @author Ken Cavanaugh
80*/
81public class IORImpl extends IdentifiableContainerBase implements IOR
82{
83    private String typeId;
84    private ORB factory = null ;
85    private boolean isCachedHashValue = false;
86    private int cachedHashValue;
87    IORSystemException wrapper ;
88
89    public ORB getORB()
90    {
91        return factory ;
92    }
93
94    /* This variable is set directly from the constructors that take
95     * an IORTemplate or IORTemplateList as arguments; otherwise it
96     * is derived from the list of TaggedProfile instances on the first
97     * call to getIORTemplates.  Note that we assume that an IOR with
98     * mutiple TaggedProfile instances has the same ObjectId in each
99     * TaggedProfile, as otherwise the IOR could never be created through
100     * an ObjectReferenceFactory.
101     */
102    private IORTemplateList iortemps = null ;
103
104    public boolean equals( Object obj )
105    {
106        if (obj == null)
107            return false ;
108
109        if (!(obj instanceof IOR))
110            return false ;
111
112        IOR other = (IOR)obj ;
113
114        return super.equals( obj ) && typeId.equals( other.getTypeId() ) ;
115    }
116
117    public synchronized int hashCode()
118    {
119        if (! isCachedHashValue) {
120              cachedHashValue =  (super.hashCode() ^ typeId.hashCode());
121              isCachedHashValue = true;
122        }
123        return cachedHashValue;
124    }
125
126    /** Construct an empty IOR.  This is needed for null object references.
127    */
128    public IORImpl( ORB orb )
129    {
130        this( orb, "" ) ;
131    }
132
133    public IORImpl( ORB orb, String typeid )
134    {
135        factory = orb ;
136        wrapper = IORSystemException.get( orb,
137            CORBALogDomains.OA_IOR ) ;
138        this.typeId = typeid ;
139    }
140
141    /** Construct an IOR from an IORTemplate by applying the same
142    * object id to each TaggedProfileTemplate in the IORTemplate.
143    */
144    public IORImpl( ORB orb, String typeId, IORTemplate iortemp, ObjectId id)
145    {
146        this( orb, typeId ) ;
147
148        this.iortemps = IORFactories.makeIORTemplateList() ;
149        this.iortemps.add( iortemp ) ;
150
151        addTaggedProfiles( iortemp, id ) ;
152
153        makeImmutable() ;
154    }
155
156    private void addTaggedProfiles( IORTemplate iortemp, ObjectId id )
157    {
158        ObjectKeyTemplate oktemp = iortemp.getObjectKeyTemplate() ;
159        Iterator templateIterator = iortemp.iterator() ;
160
161        while (templateIterator.hasNext()) {
162            TaggedProfileTemplate ptemp =
163                (TaggedProfileTemplate)(templateIterator.next()) ;
164
165            TaggedProfile profile = ptemp.create( oktemp, id ) ;
166
167            add( profile ) ;
168        }
169    }
170
171    /** Construct an IOR from an IORTemplate by applying the same
172    * object id to each TaggedProfileTemplate in the IORTemplate.
173    */
174    public IORImpl( ORB orb, String typeId, IORTemplateList iortemps, ObjectId id)
175    {
176        this( orb, typeId ) ;
177
178        this.iortemps = iortemps ;
179
180        Iterator iter = iortemps.iterator() ;
181        while (iter.hasNext()) {
182            IORTemplate iortemp = (IORTemplate)(iter.next()) ;
183            addTaggedProfiles( iortemp, id ) ;
184        }
185
186        makeImmutable() ;
187    }
188
189    public IORImpl(InputStream is)
190    {
191        this( (ORB)(is.orb()), is.read_string() ) ;
192
193        IdentifiableFactoryFinder finder =
194            factory.getTaggedProfileFactoryFinder() ;
195
196        EncapsulationUtility.readIdentifiableSequence( this, finder, is ) ;
197
198        makeImmutable() ;
199    }
200
201    public String getTypeId()
202    {
203        return typeId ;
204    }
205
206    public void write(OutputStream os)
207    {
208        os.write_string( typeId ) ;
209        EncapsulationUtility.writeIdentifiableSequence( this, os ) ;
210    }
211
212    public String stringify()
213    {
214        StringWriter bs;
215
216        MarshalOutputStream s =
217            sun.corba.OutputStreamFactory.newEncapsOutputStream(factory);
218        s.putEndian();
219        write( (OutputStream)s );
220        bs = new StringWriter();
221        try {
222            s.writeTo(new HexOutputStream(bs));
223        } catch (IOException ex) {
224            throw wrapper.stringifyWriteError( ex ) ;
225        }
226
227        return ORBConstants.STRINGIFY_PREFIX + bs;
228    }
229
230    public synchronized void makeImmutable()
231    {
232        makeElementsImmutable() ;
233
234        if (iortemps != null)
235            iortemps.makeImmutable() ;
236
237        super.makeImmutable() ;
238    }
239
240    public org.omg.IOP.IOR getIOPIOR() {
241        EncapsOutputStream os =
242            sun.corba.OutputStreamFactory.newEncapsOutputStream(factory);
243        write(os);
244        InputStream is = (InputStream) (os.create_input_stream());
245        return org.omg.IOP.IORHelper.read(is);
246    }
247
248    public boolean isNil()
249    {
250        //
251        // The check for typeId length of 0 below is commented out
252        // as a workaround for a bug in ORBs which send a
253        // null objref with a non-empty typeId string.
254        //
255        return ((size() == 0) /* && (typeId.length() == 0) */);
256    }
257
258    public boolean isEquivalent(IOR ior)
259    {
260        Iterator myIterator = iterator() ;
261        Iterator otherIterator = ior.iterator() ;
262        while (myIterator.hasNext() && otherIterator.hasNext()) {
263            TaggedProfile myProfile = (TaggedProfile)(myIterator.next()) ;
264            TaggedProfile otherProfile = (TaggedProfile)(otherIterator.next()) ;
265            if (!myProfile.isEquivalent( otherProfile ))
266                return false ;
267        }
268
269        return myIterator.hasNext() == otherIterator.hasNext() ;
270    }
271
272    private void initializeIORTemplateList()
273    {
274        // Maps ObjectKeyTemplate to IORTemplate
275        Map oktempToIORTemplate = new HashMap() ;
276
277        iortemps = IORFactories.makeIORTemplateList() ;
278        Iterator iter = iterator() ;
279        ObjectId oid = null ; // used to check that all profiles have the same oid.
280        while (iter.hasNext()) {
281            TaggedProfile prof = (TaggedProfile)(iter.next()) ;
282            TaggedProfileTemplate ptemp = prof.getTaggedProfileTemplate() ;
283            ObjectKeyTemplate oktemp = prof.getObjectKeyTemplate() ;
284
285            // Check that all oids for all profiles are the same: if they are not,
286            // throw exception.
287            if (oid == null)
288                oid = prof.getObjectId() ;
289            else if (!oid.equals( prof.getObjectId() ))
290                throw wrapper.badOidInIorTemplateList() ;
291
292            // Find or create the IORTemplate for oktemp.
293            IORTemplate iortemp = (IORTemplate)(oktempToIORTemplate.get( oktemp )) ;
294            if (iortemp == null) {
295                iortemp = IORFactories.makeIORTemplate( oktemp ) ;
296                oktempToIORTemplate.put( oktemp, iortemp ) ;
297                iortemps.add( iortemp ) ;
298            }
299
300            iortemp.add( ptemp ) ;
301        }
302
303        iortemps.makeImmutable() ;
304    }
305
306    /** Return the IORTemplateList for this IOR.  Will throw
307     * exception if it is not possible to generate an IOR
308     * from the IORTemplateList that is equal to this IOR,
309     * which can only happen if not every TaggedProfile in the
310     * IOR has the same ObjectId.
311     */
312    public synchronized IORTemplateList getIORTemplates()
313    {
314        if (iortemps == null)
315            initializeIORTemplateList() ;
316
317        return iortemps ;
318    }
319
320    /** Return the first IIOPProfile in this IOR.
321     * XXX THIS IS TEMPORARY FOR BACKWARDS COMPATIBILITY AND WILL BE REMOVED
322     * SOON!
323     */
324    public IIOPProfile getProfile()
325    {
326        IIOPProfile iop = null ;
327        Iterator iter = iteratorById( TAG_INTERNET_IOP.value ) ;
328        if (iter.hasNext())
329            iop = (IIOPProfile)(iter.next()) ;
330
331        if (iop != null)
332            return iop ;
333
334        // if we come to this point then no IIOP Profile
335        // is present.  Therefore, throw an exception.
336        throw wrapper.iorMustHaveIiopProfile() ;
337    }
338}
339