RequestImpl.java revision 667:d0315150c39d
1/*
2 * Copyright (c) 1996, 2015, 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 * Licensed Materials - Property of IBM
27 * RMI-IIOP v1.0
28 * Copyright IBM Corp. 1998 1999  All Rights Reserved
29 *
30 */
31
32package com.sun.corba.se.impl.corba;
33
34
35import org.omg.CORBA.Any;
36import org.omg.CORBA.ARG_IN;
37import org.omg.CORBA.ARG_OUT;
38import org.omg.CORBA.ARG_INOUT;
39import org.omg.CORBA.Context;
40import org.omg.CORBA.ContextList;
41import org.omg.CORBA.Environment;
42import org.omg.CORBA.ExceptionList;
43import org.omg.CORBA.NVList;
44import org.omg.CORBA.NamedValue;
45import org.omg.CORBA.Request;
46import org.omg.CORBA.SystemException;
47import org.omg.CORBA.TCKind;
48import org.omg.CORBA.TypeCode;
49import org.omg.CORBA.TypeCodePackage.BadKind;
50import org.omg.CORBA.UnknownUserException;
51import org.omg.CORBA.Bounds;
52import org.omg.CORBA.UNKNOWN;
53import org.omg.CORBA.INTERNAL;
54import org.omg.CORBA.NO_IMPLEMENT;
55import org.omg.CORBA.CompletionStatus;
56import org.omg.CORBA.WrongTransaction;
57
58import org.omg.CORBA.portable.ApplicationException ;
59import org.omg.CORBA.portable.RemarshalException ;
60import org.omg.CORBA.portable.InputStream ;
61import org.omg.CORBA.portable.OutputStream ;
62
63import com.sun.corba.se.spi.orb.ORB;
64import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
65import com.sun.corba.se.spi.logging.CORBALogDomains;
66import com.sun.corba.se.impl.logging.ORBUtilSystemException;
67import com.sun.corba.se.impl.corba.AsynchInvoke;
68import com.sun.corba.se.impl.transport.ManagedLocalsThread;
69
70public class RequestImpl
71    extends Request
72{
73    ///////////////////////////////////////////////////////////////////////////
74    // data members
75
76    protected org.omg.CORBA.Object _target;
77    protected String             _opName;
78    protected NVList             _arguments;
79    protected ExceptionList      _exceptions;
80    private NamedValue           _result;
81    protected Environment        _env;
82    private Context              _ctx;
83    private ContextList          _ctxList;
84    protected ORB                _orb;
85    private ORBUtilSystemException _wrapper;
86
87    // invocation-specific stuff
88    protected boolean            _isOneWay      = false;
89    private int[]                _paramCodes;
90    private long[]               _paramLongs;
91    private java.lang.Object[]   _paramObjects;
92
93    // support for deferred invocations.
94    // protected instead of private since it needs to be set by the
95    // thread object doing the asynchronous invocation.
96    protected boolean            gotResponse    = false;
97
98    ///////////////////////////////////////////////////////////////////////////
99    // constructor
100
101    // REVISIT - used to be protected.  Now public so it can be
102    // accessed from xgiop.
103    public RequestImpl (ORB orb,
104                        org.omg.CORBA.Object targetObject,
105                        Context ctx,
106                        String operationName,
107                        NVList argumentList,
108                        NamedValue resultContainer,
109                        ExceptionList exceptionList,
110                        ContextList ctxList)
111    {
112
113        // initialize the orb
114        _orb    = orb;
115        _wrapper = ORBUtilSystemException.get( orb,
116            CORBALogDomains.OA_INVOCATION ) ;
117
118        // initialize target, context and operation name
119        _target     = targetObject;
120        _ctx    = ctx;
121        _opName = operationName;
122
123        // initialize argument list if not passed in
124        if (argumentList == null)
125            _arguments = new NVListImpl(_orb);
126        else
127            _arguments = argumentList;
128
129        // set result container.
130        _result = resultContainer;
131
132        // initialize exception list if not passed in
133        if (exceptionList == null)
134            _exceptions = new ExceptionListImpl();
135        else
136            _exceptions = exceptionList;
137
138        // initialize context list if not passed in
139        if (ctxList == null)
140            _ctxList = new ContextListImpl(_orb);
141        else
142            _ctxList = ctxList;
143
144        // initialize environment
145        _env    = new EnvironmentImpl();
146
147    }
148
149    public org.omg.CORBA.Object target()
150    {
151        return _target;
152    }
153
154    public String operation()
155    {
156        return _opName;
157    }
158
159    public NVList arguments()
160    {
161        return _arguments;
162    }
163
164    public NamedValue result()
165    {
166        return _result;
167    }
168
169    public Environment env()
170    {
171        return _env;
172    }
173
174    public ExceptionList exceptions()
175    {
176        return _exceptions;
177    }
178
179    public ContextList contexts()
180    {
181        return _ctxList;
182    }
183
184    public synchronized Context ctx()
185    {
186        if (_ctx == null)
187            _ctx = new ContextImpl(_orb);
188        return _ctx;
189    }
190
191    public synchronized void ctx(Context newCtx)
192    {
193        _ctx = newCtx;
194    }
195
196    public synchronized Any add_in_arg()
197    {
198        return _arguments.add(org.omg.CORBA.ARG_IN.value).value();
199    }
200
201    public synchronized Any add_named_in_arg(String name)
202    {
203        return _arguments.add_item(name, org.omg.CORBA.ARG_IN.value).value();
204    }
205
206    public synchronized Any add_inout_arg()
207    {
208        return _arguments.add(org.omg.CORBA.ARG_INOUT.value).value();
209    }
210
211    public synchronized Any add_named_inout_arg(String name)
212    {
213        return _arguments.add_item(name, org.omg.CORBA.ARG_INOUT.value).value();
214    }
215
216    public synchronized Any add_out_arg()
217    {
218        return _arguments.add(org.omg.CORBA.ARG_OUT.value).value();
219    }
220
221    public synchronized Any add_named_out_arg(String name)
222    {
223        return _arguments.add_item(name, org.omg.CORBA.ARG_OUT.value).value();
224    }
225
226    public synchronized void set_return_type(TypeCode tc)
227    {
228        if (_result == null)
229            _result = new NamedValueImpl(_orb);
230        _result.value().type(tc);
231    }
232
233    public synchronized Any return_value()
234    {
235        if (_result == null)
236            _result = new NamedValueImpl(_orb);
237        return _result.value();
238    }
239
240    public synchronized void add_exception(TypeCode exceptionType)
241    {
242        _exceptions.add(exceptionType);
243    }
244
245    public synchronized void invoke()
246    {
247        doInvocation();
248    }
249
250    public synchronized void send_oneway()
251    {
252        _isOneWay = true;
253        doInvocation();
254    }
255
256    public synchronized void send_deferred()
257    {
258        AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false);
259        new ManagedLocalsThread(invokeObject).start();
260    }
261
262    public synchronized boolean poll_response()
263    {
264        // this method has to be synchronized even though it seems
265        // "readonly" since the thread object doing the asynchronous
266        // invocation can potentially update this variable in parallel.
267        // updates are currently simply synchronized againt the request
268        // object.
269        return gotResponse;
270    }
271
272    public synchronized void get_response()
273        throws org.omg.CORBA.WrongTransaction
274    {
275        while (gotResponse == false) {
276            // release the lock. wait to be notified by the thread that is
277            // doing the asynchronous invocation.
278            try {
279                wait();
280            }
281            catch (InterruptedException e) {}
282        }
283    }
284
285    ///////////////////////////////////////////////////////////////////////////
286    // private helper methods
287
288    /*
289     * The doInvocation operation is where the real mechanics of
290     * performing the request invocation is done.
291     */
292    protected void doInvocation()
293    {
294        org.omg.CORBA.portable.Delegate delegate = StubAdapter.getDelegate(
295            _target ) ;
296
297        // Initiate Client Portable Interceptors.  Inform the PIHandler that
298        // this is a DII request so that it knows to ignore the second
299        // inevitable call to initiateClientPIRequest in createRequest.
300        // Also, save the RequestImpl object for later use.
301        _orb.getPIHandler().initiateClientPIRequest( true );
302        _orb.getPIHandler().setClientPIInfo( this );
303
304        InputStream $in = null;
305        try {
306            OutputStream $out = delegate.request(null, _opName, !_isOneWay);
307            // Marshal args
308            try {
309                for (int i=0; i<_arguments.count() ; i++) {
310                    NamedValue nv = _arguments.item(i);
311                    switch (nv.flags()) {
312                    case ARG_IN.value:
313                        nv.value().write_value($out);
314                        break;
315                    case ARG_OUT.value:
316                        break;
317                    case ARG_INOUT.value:
318                        nv.value().write_value($out);
319                        break;
320                    }
321                }
322            } catch ( org.omg.CORBA.Bounds ex ) {
323                throw _wrapper.boundsErrorInDiiRequest( ex ) ;
324            }
325
326            $in = delegate.invoke(null, $out);
327        } catch (ApplicationException e) {
328            // REVISIT - minor code.
329            // This is already handled in subcontract.
330            // REVISIT - uncomment.
331            //throw new INTERNAL();
332        } catch (RemarshalException e) {
333            doInvocation();
334        } catch( SystemException ex ) {
335            _env.exception(ex);
336            // NOTE: The exception should not be thrown.
337            // However, JDK 1.4 and earlier threw the exception,
338            // so we keep the behavior to be compatible.
339            throw ex;
340        } finally {
341            delegate.releaseReply(null, $in);
342        }
343    }
344
345    // REVISIT -  make protected after development - so xgiop can get it.
346    public void unmarshalReply(InputStream is)
347    {
348        // First unmarshal the return value if it is not void
349        if ( _result != null ) {
350            Any returnAny = _result.value();
351            TypeCode returnType = returnAny.type();
352            if ( returnType.kind().value() != TCKind._tk_void )
353                returnAny.read_value(is, returnType);
354        }
355
356        // Now unmarshal the out/inout args
357        try {
358            for ( int i=0; i<_arguments.count() ; i++) {
359                NamedValue nv = _arguments.item(i);
360                switch( nv.flags() ) {
361                case ARG_IN.value:
362                    break;
363                case ARG_OUT.value:
364                case ARG_INOUT.value:
365                    Any any = nv.value();
366                    any.read_value(is, any.type());
367                    break;
368                }
369            }
370        }
371        catch ( org.omg.CORBA.Bounds ex ) {
372            // Cannot happen since we only iterate till _arguments.count()
373        }
374    }
375}
376