package org.jacorb.orb.dii; /* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.util.Iterator; import org.jacorb.orb.ORB; import org.jacorb.orb.giop.ClientConnection; import org.jacorb.orb.giop.RequestOutputStream; import org.jacorb.orb.portableInterceptor.ClientInterceptorIterator; import org.jacorb.orb.portableInterceptor.ClientRequestInfoImpl; import org.jacorb.orb.portableInterceptor.InterceptorManager; import org.omg.CORBA.Any; import org.omg.CORBA.CompletionStatus; import org.omg.CORBA.INTERNAL; import org.omg.CORBA.NVList; import org.omg.CORBA.NamedValue; import org.omg.CORBA.TCKind; import org.omg.CORBA.UNKNOWN; import org.omg.CORBA.portable.ApplicationException; import org.omg.CORBA.portable.RemarshalException; import org.slf4j.Logger; /** * DII requests * * @author Gerald Brose, FU Berlin */ public class Request extends org.omg.CORBA.Request { public final org.omg.CORBA.Object target; public final ClientConnection connection; public final byte[] object_key; public final NVList arguments; public final String operation; public final org.omg.CORBA.Environment env = new Environment(); private final org.jacorb.orb.NamedValue result_value; private final org.omg.CORBA.ExceptionList exceptions; private final org.jacorb.orb.ORB orb; private final Logger logger; private final org.omg.CORBA.ContextList contexts = new ContextListImpl(); private org.omg.CORBA.Context context; private Caller deferred_caller; private org.omg.CORBA.portable.InputStream reply; /* state of request object */ private boolean immediate = false; private boolean deferred = false; private boolean finished = false; private ClientRequestInfoImpl info = null; public Request( org.omg.CORBA.Object target, ORB orb, ClientConnection connection, byte[] obj_key, String operationName) { this(target, orb, connection, obj_key, operationName, orb.create_list(10), null, createVoidResultValue(orb)); } private static final NamedValue createVoidResultValue(ORB orb) { Any any = orb.create_any(); any.type(orb.get_primitive_tc(TCKind.tk_void)); org.jacorb.orb.NamedValue namedValue = new org.jacorb.orb.NamedValue(1); namedValue.set_value(any); return namedValue; } public Request( org.omg.CORBA.Object target, ORB orb, ClientConnection connection, byte[] obj_key, String op, org.omg.CORBA.NVList args, org.omg.CORBA.Context context, org.omg.CORBA.NamedValue result) { super(); this.target = target; this.orb = orb; this.connection = connection; this.object_key = obj_key; this.operation = op; exceptions = new ExceptionList(); this.arguments = args; this.context = context; result_value = (org.jacorb.orb.NamedValue)result; logger = orb.getConfiguration().getLogger("org.jacorb.dii.request"); } public Request( org.omg.CORBA.Object target, ORB orb, ClientConnection connection, byte[] obj_key, String op, org.omg.CORBA.NVList args, org.omg.CORBA.Context context, org.omg.CORBA.NamedValue result, org.omg.CORBA.ExceptionList exceptions, org.omg.CORBA.ContextList contexts ) { super(); this.target = target; this.orb = orb; this.connection = connection; this.object_key = obj_key; this.operation = op; this.exceptions = exceptions; this.arguments = args; this.context = context; result_value = (org.jacorb.orb.NamedValue)result; logger = orb.getConfiguration().getLogger("org.jacorb.dii.request"); } public org.omg.CORBA.Object target() { return target; } public java.lang.String operation() { return operation; } public org.omg.CORBA.NVList arguments() { return arguments; } public org.omg.CORBA.NamedValue result() { return result_value; } /** * The <code>env</code> method returns a CORBA Environment object. This * allows a user to retrieve any exceptions that were thrown during * processing of this request. * If the remote process throws a known exception i.e. one that has been * provided within the ExceptionList parameter then actual exception may * be extracted via this function from the UnknownUserException Any that * is passed back. * If the remote process throws a CORBA system exception or a Java exception * then these will also be stored within this env parameter. * If the remote process throws a UserException that has not been defined * via the ExceptionList then a CORBA UNKNOWN will be thrown containing the * typecode of the unknown exception. * * @return an <code>org.omg.CORBA.Environment</code> value */ public org.omg.CORBA.Environment env() { return env; } public org.omg.CORBA.ExceptionList exceptions() { return exceptions; } public org.omg.CORBA.ContextList contexts() { return contexts; } public org.omg.CORBA.Context ctx() { return context; } public void ctx( org.omg.CORBA.Context ctx) { this.context = ctx; } public Any add_in_arg() { NamedValue nv = arguments.add(org.omg.CORBA.ARG_IN.value); ((org.jacorb.orb.NamedValue)nv).set_value( orb.create_any()); return nv.value(); } public Any add_named_in_arg(java.lang.String name) { NamedValue nv = arguments.add_item(name,org.omg.CORBA.ARG_IN.value); ((org.jacorb.orb.NamedValue)nv).set_value( orb.create_any()); return nv.value(); } public Any add_inout_arg() { NamedValue nv = arguments.add(org.omg.CORBA.ARG_INOUT.value); ((org.jacorb.orb.NamedValue)nv).set_value( orb.create_any()); return nv.value(); } public Any add_named_inout_arg(java.lang.String name) { NamedValue nv = arguments.add_item(name,org.omg.CORBA.ARG_INOUT.value); ((org.jacorb.orb.NamedValue)nv).set_value( orb.create_any()); return nv.value(); } public Any add_out_arg() { NamedValue nv = arguments.add(org.omg.CORBA.ARG_OUT.value); ((org.jacorb.orb.NamedValue)nv).set_value( orb.create_any()); return nv.value(); } public Any add_named_out_arg(java.lang.String name) { NamedValue nv = arguments.add_item( name, org.omg.CORBA.ARG_OUT.value ); ((org.jacorb.orb.NamedValue)nv).set_value( orb.create_any()); return nv.value(); } /** * default return type is void */ public void set_return_type( org.omg.CORBA.TypeCode tc) { result_value.value().type(tc); } public Any return_value() { return result_value.value(); } private void _read_result() { if( result_value.value().type().kind() != org.omg.CORBA.TCKind.tk_void ) { result_value.value().read_value( reply, result_value.value().type() ); } /** get out/inout parameters if any */ for( Iterator<NamedValue> e = ((org.jacorb.orb.NVList)arguments).iterator(); e.hasNext();) { NamedValue nv = e.next(); if( nv.flags() != org.omg.CORBA.ARG_IN.value ) { nv.value().read_value(reply, nv.value().type()); } } } private void _invoke( boolean response_expected ) { if (logger.isDebugEnabled ()) { logger.debug("DII::Request for " + target); } while (true) { org.jacorb.orb.Delegate delegate = (org.jacorb.orb.Delegate)((org.omg.CORBA.portable.ObjectImpl)target)._get_delegate(); final RequestOutputStream out = (RequestOutputStream)delegate.request(target, operation, response_expected); try { out.setRequest(this); for( Iterator<NamedValue> it = ((org.jacorb.orb.NVList)arguments).iterator(); it.hasNext();) { NamedValue namedValue = it.next(); if( namedValue.flags() != org.omg.CORBA.ARG_OUT.value ) { namedValue.value().write_value(out); } } try { reply = delegate.invoke(target, out); if( response_expected ) { _read_result(); if (info != null) { info.setResult (result_value.value()); InterceptorManager manager = orb.getInterceptorManager(); info.setCurrent (manager.getCurrent()); try { delegate.invokeInterceptors(info, ClientInterceptorIterator.RECEIVE_REPLY); } catch(RemarshalException e) { //not allowed to happen here anyway throw new INTERNAL("should not happen"); } info = null; } } } catch (RemarshalException e) { // Try again continue; } catch (ApplicationException e) { if (logger.isDebugEnabled ()) { logger.debug("DII Request caught ApplicationException", e); } org.omg.CORBA.Any any; org.omg.CORBA.TypeCode typeCode; String id = e.getId (); int count = (exceptions == null ? 0 : exceptions.count ()); // since count > 0, this means that we were provided a // list of exceptions that can be thrown by the invoked // operation. see if the ApplicationException we // received matches any item in the exception list and // set it if it does for (int i = 0; i < count; i++) { try { typeCode = exceptions.item (i); if (id.equals (typeCode.id ())) { if (logger.isDebugEnabled ()) { logger.debug ("Found matching typecode of " + id + " to throw."); } any = orb.create_any (); any.read_value (e.getInputStream (), typeCode); env.exception (new org.omg.CORBA.UnknownUserException (any)); break; } } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) // NOPMD { // Ignored } catch (org.omg.CORBA.Bounds ex) { break; } } if (count == 0) { env.exception ( new UNKNOWN ( "Caught an unknown exception with typecode id of " + e.getInputStream ().read_string (), 0, CompletionStatus.COMPLETED_YES ) ); } break; } catch (Exception e) { if (logger.isDebugEnabled ()) { logger.debug("DII Request caught Exception", e); } env.exception (e); break; } break; } finally { out.close(); } } } public void setInfo(ClientRequestInfoImpl info) { this.info = info; } public void invoke() { start(); _invoke(true); finish(); } public void send_oneway() { start(); _invoke(false); finish(); } private static class Caller extends Thread { private final Request request; private boolean active = true; public Caller( Request client ) { request = client; } public void run() { request._invoke(true); request.finish(); synchronized(request) { active = false; request.notifyAll(); } } public void joinWithCaller() { synchronized(request) { while(active) { try { request.wait(); } catch(InterruptedException e) // NOPMD { // ignored } } } } } public synchronized void send_deferred() { defer(); orb.addRequest( this ); deferred_caller = new Caller( this ); deferred_caller.start(); } public synchronized void get_response() { if( ! immediate && ! deferred ) { throw new org.omg.CORBA.BAD_INV_ORDER ( 11, org.omg.CORBA.CompletionStatus.COMPLETED_NO ); } if ( immediate ) { throw new org.omg.CORBA.BAD_INV_ORDER ( 13, org.omg.CORBA.CompletionStatus.COMPLETED_NO ); } if( deferred_caller != null ) { deferred_caller.joinWithCaller(); deferred_caller = null; orb.removeRequest( this ); } } public synchronized boolean poll_response() { if( ! immediate && ! deferred ) { throw new org.omg.CORBA.BAD_INV_ORDER ( 11, org.omg.CORBA.CompletionStatus.COMPLETED_NO ); } if ( immediate ) { throw new org.omg.CORBA.BAD_INV_ORDER ( 13, org.omg.CORBA.CompletionStatus.COMPLETED_NO ); } if ( deferred_caller == null ) { throw new org.omg.CORBA.BAD_INV_ORDER ( 12, org.omg.CORBA.CompletionStatus.COMPLETED_NO ); } return finished; } private synchronized void start() throws org.omg.CORBA.BAD_INV_ORDER { if( immediate || deferred ) { throw new org.omg.CORBA.BAD_INV_ORDER ( 10, org.omg.CORBA.CompletionStatus.COMPLETED_NO ); } immediate = true; } private synchronized void defer() throws org.omg.CORBA.BAD_INV_ORDER { if( immediate || deferred ) { throw new org.omg.CORBA.BAD_INV_ORDER ( 10, org.omg.CORBA.CompletionStatus.COMPLETED_NO ); } deferred = true; } private synchronized void finish() { finished = true; } }