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