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;
}
}