CorbaClientDelegateImpl.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2001, 2004, 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.protocol;
27
28import java.util.Iterator;
29import java.util.HashMap;
30
31import javax.rmi.CORBA.Tie;
32
33import org.omg.CORBA.CompletionStatus;
34import org.omg.CORBA.Context;
35import org.omg.CORBA.ContextList;
36import org.omg.CORBA.ExceptionList;
37import org.omg.CORBA.NamedValue;
38import org.omg.CORBA.NVList;
39import org.omg.CORBA.Request;
40import org.omg.CORBA.TypeCode;
41
42import org.omg.CORBA.portable.ApplicationException;
43import org.omg.CORBA.portable.Delegate;
44import org.omg.CORBA.portable.InputStream;
45import org.omg.CORBA.portable.OutputStream;
46import org.omg.CORBA.portable.RemarshalException;
47import org.omg.CORBA.portable.ServantObject;
48
49import com.sun.corba.se.pept.broker.Broker;
50import com.sun.corba.se.pept.encoding.InputObject;
51import com.sun.corba.se.pept.encoding.OutputObject;
52import com.sun.corba.se.pept.protocol.ClientInvocationInfo;
53import com.sun.corba.se.pept.protocol.ClientRequestDispatcher;
54import com.sun.corba.se.pept.transport.ContactInfo;
55import com.sun.corba.se.pept.transport.ContactInfoList;
56import com.sun.corba.se.pept.transport.ContactInfoListIterator;
57
58import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
59import com.sun.corba.se.spi.ior.IOR;
60import com.sun.corba.se.spi.logging.CORBALogDomains;
61import com.sun.corba.se.spi.orb.ORB;
62import com.sun.corba.se.spi.protocol.CorbaClientDelegate ;
63import com.sun.corba.se.spi.transport.CorbaContactInfo;
64import com.sun.corba.se.spi.transport.CorbaContactInfoList;
65import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator;
66
67import com.sun.corba.se.impl.corba.RequestImpl;
68import com.sun.corba.se.impl.protocol.CorbaInvocationInfo;
69import com.sun.corba.se.impl.transport.CorbaContactInfoListImpl;
70import com.sun.corba.se.impl.util.JDKBridge;
71import com.sun.corba.se.impl.logging.ORBUtilSystemException;
72
73// implements com.sun.corba.se.impl.core.ClientRequestDispatcher
74// so RMI-IIOP Util.isLocal can call ClientRequestDispatcher.useLocalInvocation.
75
76/**
77 * @author Harold Carr
78 */
79public class CorbaClientDelegateImpl extends CorbaClientDelegate
80{
81    private ORB orb;
82    private ORBUtilSystemException wrapper ;
83
84    private CorbaContactInfoList contactInfoList;
85
86    public CorbaClientDelegateImpl(ORB orb,
87                                   CorbaContactInfoList contactInfoList)
88    {
89        this.orb = orb;
90        this.wrapper = ORBUtilSystemException.get( orb,
91            CORBALogDomains.RPC_PROTOCOL ) ;
92        this.contactInfoList = contactInfoList;
93    }
94
95    //
96    // framework.subcontract.Delegate
97    //
98
99    public Broker getBroker()
100    {
101        return orb;
102    }
103
104    public ContactInfoList getContactInfoList()
105    {
106        return contactInfoList;
107    }
108
109    //
110    // CORBA_2_3.portable.Delegate
111    //
112
113    public OutputStream request(org.omg.CORBA.Object self,
114                                String operation,
115                                boolean responseExpected)
116    {
117        ClientInvocationInfo invocationInfo =
118            orb.createOrIncrementInvocationInfo();
119        Iterator contactInfoListIterator =
120            invocationInfo.getContactInfoListIterator();
121        if (contactInfoListIterator == null) {
122            contactInfoListIterator = contactInfoList.iterator();
123            invocationInfo.setContactInfoListIterator(contactInfoListIterator);
124        }
125        if (! contactInfoListIterator.hasNext()) {
126            throw ((CorbaContactInfoListIterator)contactInfoListIterator)
127                .getFailureException();
128        }
129        CorbaContactInfo contactInfo = (CorbaContactInfo) contactInfoListIterator.next();
130        ClientRequestDispatcher subcontract = contactInfo.getClientRequestDispatcher();
131        // Remember chosen subcontract for invoke and releaseReply.
132        // NOTE: This is necessary since a stream is not available in
133        // releaseReply if there is a client marshaling error or an
134        // error in _invoke.
135        invocationInfo.setClientRequestDispatcher(subcontract);
136        return (OutputStream)
137            subcontract.beginRequest(self, operation,
138                                     !responseExpected, contactInfo);
139    }
140
141    public InputStream invoke(org.omg.CORBA.Object self, OutputStream output)
142        throws
143            ApplicationException,
144            RemarshalException
145    {
146        ClientRequestDispatcher subcontract = getClientRequestDispatcher();
147        return (InputStream)
148            subcontract.marshalingComplete((Object)self, (OutputObject)output);
149    }
150
151    public void releaseReply(org.omg.CORBA.Object self, InputStream input)
152    {
153        // NOTE: InputStream may be null (e.g., exception request from PI).
154        ClientRequestDispatcher subcontract = getClientRequestDispatcher();
155        subcontract.endRequest(orb, self, (InputObject)input);
156        orb.releaseOrDecrementInvocationInfo();
157    }
158
159    private ClientRequestDispatcher getClientRequestDispatcher()
160    {
161        return (ClientRequestDispatcher)
162            ((CorbaInvocationInfo)orb.getInvocationInfo())
163            .getClientRequestDispatcher();
164    }
165
166    public org.omg.CORBA.Object get_interface_def(org.omg.CORBA.Object obj)
167    {
168        InputStream is = null;
169        // instantiate the stub
170        org.omg.CORBA.Object stub = null ;
171
172        try {
173            OutputStream os = request(null, "_interface", true);
174            is = (InputStream) invoke((org.omg.CORBA.Object)null, os);
175
176            org.omg.CORBA.Object objimpl =
177                (org.omg.CORBA.Object) is.read_Object();
178
179            // check if returned object is of correct type
180            if ( !objimpl._is_a("IDL:omg.org/CORBA/InterfaceDef:1.0") )
181                throw wrapper.wrongInterfaceDef(CompletionStatus.COMPLETED_MAYBE);
182
183            try {
184                stub = (org.omg.CORBA.Object)
185                    JDKBridge.loadClass("org.omg.CORBA._InterfaceDefStub").
186                        newInstance();
187            } catch (Exception ex) {
188                throw wrapper.noInterfaceDefStub( ex ) ;
189            }
190
191            org.omg.CORBA.portable.Delegate del =
192                StubAdapter.getDelegate( objimpl ) ;
193            StubAdapter.setDelegate( stub, del ) ;
194        } catch (ApplicationException e) {
195            // This cannot happen.
196            throw wrapper.applicationExceptionInSpecialMethod( e ) ;
197        } catch (RemarshalException e) {
198            return get_interface_def(obj);
199        } finally {
200            releaseReply((org.omg.CORBA.Object)null, (InputStream)is);
201        }
202
203        return stub;
204    }
205
206    public boolean is_a(org.omg.CORBA.Object obj, String dest)
207    {
208        // dest is the typeId of the interface to compare against.
209        // repositoryIds is the list of typeIds that the stub knows about.
210
211        // First we look for an answer using local information.
212
213        String [] repositoryIds = StubAdapter.getTypeIds( obj ) ;
214        String myid = contactInfoList.getTargetIOR().getTypeId();
215        if ( dest.equals(myid) ) {
216            return true;
217        }
218        for ( int i=0; i<repositoryIds.length; i++ ) {
219            if ( dest.equals(repositoryIds[i]) ) {
220                return true;
221            }
222        }
223
224        // But repositoryIds may not be complete, so it may be necessary to
225        // go to server.
226
227        InputStream is = null;
228        try {
229            OutputStream os = request(null, "_is_a", true);
230            os.write_string(dest);
231            is = (InputStream) invoke((org.omg.CORBA.Object) null, os);
232
233            return is.read_boolean();
234
235        } catch (ApplicationException e) {
236            // This cannot happen.
237            throw wrapper.applicationExceptionInSpecialMethod( e ) ;
238        } catch (RemarshalException e) {
239            return is_a(obj, dest);
240        } finally {
241            releaseReply((org.omg.CORBA.Object)null, (InputStream)is);
242        }
243    }
244
245    public boolean non_existent(org.omg.CORBA.Object obj)
246    {
247        InputStream is = null;
248        try {
249            OutputStream os = request(null, "_non_existent", true);
250            is = (InputStream) invoke((org.omg.CORBA.Object)null, os);
251
252            return is.read_boolean();
253
254        } catch (ApplicationException e) {
255            // This cannot happen.
256            throw wrapper.applicationExceptionInSpecialMethod( e ) ;
257        } catch (RemarshalException e) {
258            return non_existent(obj);
259        } finally {
260            releaseReply((org.omg.CORBA.Object)null, (InputStream)is);
261        }
262    }
263
264    public org.omg.CORBA.Object duplicate(org.omg.CORBA.Object obj)
265    {
266        return obj;
267    }
268
269    public void release(org.omg.CORBA.Object obj)
270    {
271        // DO NOT clear out internal variables to release memory
272        // This delegate may be pointed-to by other objrefs.
273    }
274
275    // obj._get_delegate() == this due to the argument passing conventions in
276    // portable.ObjectImpl, so we just ignore obj here.
277    public boolean is_equivalent(org.omg.CORBA.Object obj,
278                                 org.omg.CORBA.Object ref)
279    {
280        if ( ref == null )
281            return false;
282
283        // If ref is a local object, it is not a Stub!
284        if (!StubAdapter.isStub(ref))
285            return false ;
286
287        Delegate del = StubAdapter.getDelegate(ref) ;
288        if (del == null)
289            return false ;
290
291        // Optimize the x.is_equivalent( x ) case
292        if (del == this)
293            return true;
294
295        // If delegate was created by a different ORB, return false
296        if (!(del instanceof CorbaClientDelegateImpl))
297            return false ;
298
299        CorbaClientDelegateImpl corbaDelegate = (CorbaClientDelegateImpl)del ;
300        CorbaContactInfoList ccil =
301            (CorbaContactInfoList)corbaDelegate.getContactInfoList() ;
302        return this.contactInfoList.getTargetIOR().isEquivalent(
303            ccil.getTargetIOR() );
304    }
305
306    /**
307     * This method overrides the org.omg.CORBA.portable.Delegate.equals method,
308     * and does the equality check based on IOR equality.
309     */
310    public boolean equals(org.omg.CORBA.Object self, java.lang.Object other)
311    {
312        if (other == null)
313            return false ;
314
315        if (!StubAdapter.isStub(other)) {
316            return false;
317        }
318
319        Delegate delegate = StubAdapter.getDelegate( other ) ;
320        if (delegate == null)
321            return false ;
322
323        if (delegate instanceof CorbaClientDelegateImpl) {
324            CorbaClientDelegateImpl otherDel = (CorbaClientDelegateImpl)
325                delegate ;
326            IOR otherIor = otherDel.contactInfoList.getTargetIOR();
327            return this.contactInfoList.getTargetIOR().equals(otherIor);
328        }
329
330        // Come here if other is not implemented by our ORB.
331        return false;
332    }
333
334    public int hashCode(org.omg.CORBA.Object obj)
335    {
336        return this.hashCode() ;
337    }
338
339    public int hash(org.omg.CORBA.Object obj, int maximum)
340    {
341        int h = this.hashCode();
342        if ( h > maximum )
343            return 0;
344        return h;
345    }
346
347    public Request request(org.omg.CORBA.Object obj, String operation)
348    {
349        return new RequestImpl(orb, obj, null, operation, null, null, null,
350                               null);
351    }
352
353    public Request create_request(org.omg.CORBA.Object obj,
354                                  Context ctx,
355                                  String operation,
356                                  NVList arg_list,
357                                  NamedValue result)
358    {
359        return new RequestImpl(orb, obj, ctx, operation, arg_list,
360                               result, null, null);
361    }
362
363    public Request create_request(org.omg.CORBA.Object obj,
364                                  Context ctx,
365                                  String operation,
366                                  NVList arg_list,
367                                  NamedValue result,
368                                  ExceptionList exclist,
369                                  ContextList ctxlist)
370    {
371        return new RequestImpl(orb, obj, ctx, operation, arg_list, result,
372                               exclist, ctxlist);
373    }
374
375    public org.omg.CORBA.ORB orb(org.omg.CORBA.Object obj)
376    {
377        return this.orb;
378    }
379
380    /**
381     * Returns true if this object is implemented by a local servant.
382     *
383     * REVISIT: locatedIOR should be replaced with a method call that
384     *      returns the current IOR for this request (e.g. ContactInfoChooser).
385     *
386     * @param self The object reference which delegated to this delegate.
387     * @return true only if the servant incarnating this object is located in
388     * this ORB.
389     */
390    public boolean is_local(org.omg.CORBA.Object self)
391    {
392        // XXX this need to check isNextCallValid
393        return contactInfoList.getEffectiveTargetIOR().getProfile().
394            isLocal();
395    }
396
397    public ServantObject servant_preinvoke(org.omg.CORBA.Object self,
398                                           String operation,
399                                           Class expectedType)
400    {
401        return
402            contactInfoList.getLocalClientRequestDispatcher()
403            .servant_preinvoke(self, operation, expectedType);
404    }
405
406    public void servant_postinvoke(org.omg.CORBA.Object self,
407                                   ServantObject servant)
408    {
409        contactInfoList.getLocalClientRequestDispatcher()
410            .servant_postinvoke(self, servant);
411    }
412
413    // XXX Should this be public?
414    /* Returns the codebase for object reference provided.
415     * @param self the object reference whose codebase needs to be returned.
416     * @return the codebase as a space delimited list of url strings or
417     * null if none.
418     */
419    public String get_codebase(org.omg.CORBA.Object self)
420    {
421        if (contactInfoList.getTargetIOR() != null) {
422            return contactInfoList.getTargetIOR().getProfile().getCodebase();
423        }
424        return null;
425    }
426
427    public String toString(org.omg.CORBA.Object self)
428    {
429        return contactInfoList.getTargetIOR().stringify();
430    }
431
432    ////////////////////////////////////////////////////
433    //
434    // java.lang.Object
435    //
436
437    public int hashCode()
438    {
439        return this.contactInfoList.hashCode();
440    }
441}
442
443// End of file.
444