base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, internal::DataSource<bool>::shared_ptr blocking) const { unsigned int expected = mfact->getCollectArity(method.c_str()); if (args.size() != expected + 1) { throw wrong_number_of_args_exception( expected + 1, args.size() ); } // isolate and check CSendHandle std::vector<base::DataSourceBase::shared_ptr> cargs( ++args.begin(), args.end() ); DataSource<CSendHandle_var>::shared_ptr ds = DataSource<CSendHandle_var>::narrow( args.begin()->get() ); if (!ds) { throw wrong_types_of_args_exception(0,"CSendHandle_var",(*args.begin())->getTypeName() ); } // check if args matches what CSendHandle expects. try { corba::CAnyArguments_var nargs = new corba::CAnyArguments(); nargs->length( cargs.size() ); for (size_t i=0; i < cargs.size(); ++i ) { const types::TypeInfo* ti = cargs[i]->getTypeInfo(); CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); assert( ctt ); DataSourceBase::shared_ptr tryout = ti->buildValue(); ctt->updateAny(tryout, nargs[i]); } ds->get()->checkArguments( nargs.in() ); } catch ( CWrongNumbArgException& wna) { throw wrong_number_of_args_exception(wna.wanted, wna.received); } catch ( CWrongTypeArgException& wta) { throw wrong_types_of_args_exception(wta.whicharg,wta.expected.in(), wta.received.in()); } // All went well, produce collect DataSource: return new CorbaOperationCallerCollect( ds->get().in(),cargs, blocking); }
base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const { corba::CAnyArguments_var nargs = new corba::CAnyArguments(); nargs->length( args.size() ); for (size_t i=0; i < args.size(); ++i ) { const types::TypeInfo* ti = args[i]->getTypeInfo(); CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); if (!ctt) throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName()); DataSourceBase::shared_ptr tryout = ti->buildValue(); ctt->updateAny(tryout, nargs[i]); } try { // will throw if wrong args. mfact->checkOperation(method.c_str(), nargs.inout() ); // Will return a CSendHandle_var: DataSource<CSendHandle_var>::shared_ptr result = new ValueDataSource<CSendHandle_var>(); return new ActionAliasDataSource<CSendHandle_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, false), result.get() ); } catch ( corba::CNoSuchNameException& nsn ) { throw name_not_found_exception( nsn.name.in() ); } catch ( corba::CWrongNumbArgException& wa ) { throw wrong_number_of_args_exception( wa.wanted, wa.received ); } catch ( corba::CWrongTypeArgException& wta ) { throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() ); } return 0; // not reached. }
/** * Helper function to convert a vector of data sources to a sequence of anys. * @param sources * @param anys * @return */ bool sourcevector_to_anysequence( vector<DataSourceBase::shared_ptr> const& sources, CAnyArguments & anys ) { bool valid = true; anys.length( sources.size() ); for(unsigned int i = 0; i != sources.size(); ++i) { const TypeInfo* ti = sources[i]->getTypeInfo(); CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); ctt->updateAny(sources[i], anys[i]); } return valid; }
void readArguments() { // We need to delay reading the arguments upto this point such that the args contain // the latest values. nargs = new corba::CAnyArguments(); nargs->length( margs.size() ); for (size_t i=0; i < margs.size(); ++i ) { const types::TypeInfo* ti = margs[i]->getTypeInfo(); CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); assert( ctt ); ctt->updateAny(margs[i], nargs[i]); } }
::CORBA::Any * RTT_corba_COperationInterface_i::callOperation ( const char * operation, ::RTT::corba::CAnyArguments & args) { if ( mfact->hasMember( string( operation ) ) == false || mfact->isSynchronous(string(operation)) ) throw ::RTT::corba::CNoSuchNameException( operation ); // convert Corba args to C++ args. try { OperationCallerC orig(mfact->getPart(operation), operation, 0); vector<DataSourceBase::shared_ptr> results; for (size_t i =0; i != args.length(); ++i) { const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1); CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); // we need to store the results for returning them to caller (args is inout!) after the call() results.push_back( ctt->createDataSource( &args[i] ) ); orig.arg( results[i] ); } if ( orig.ready() ) { DataSourceBase::shared_ptr ds = orig.getCallDataSource(); CORBA::Any* retany; // Try to get the return result : const TypeInfo* ti = ds->getTypeInfo(); CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); if ( !ctt ) { log(Warning) << "Could not return results of call to " << operation << ": unknown return type by CORBA transport."<<endlog(); ds->evaluate(); // equivalent to orig.call() retany = new CORBA::Any(); } else { retany = ctt->createAny( ds ); // call evaluate internally } // Return results into args: for (size_t i =0; i != args.length(); ++i) { const TypeInfo* ti = mfact->getPart(operation)->getArgumentType( i + 1); CorbaTypeTransporter* ctta = dynamic_cast<CorbaTypeTransporter*> ( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); ctta->updateAny(results[i], args[i]); } return retany; } else { orig.check(); // will throw } } catch (no_asynchronous_operation_exception& ) { throw ::RTT::corba::CNoSuchNameException( operation ); } catch ( name_not_found_exception& ) { throw ::RTT::corba::CNoSuchNameException( operation ); } catch ( wrong_number_of_args_exception& wna ) { throw ::RTT::corba::CWrongNumbArgException( wna.wanted, wna.received ); } catch (wrong_types_of_args_exception& wta ) { throw ::RTT::corba::CWrongTypeArgException( wta.whicharg, wta.expected_.c_str(), wta.received_.c_str() ); } return new ::CORBA::Any(); }
base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produce(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const { corba::CAnyArguments_var nargs = new corba::CAnyArguments(); nargs->length( args.size() ); // this part is only done to feed to checkOperation() with some defaults. // We don't want to evaluate() the *real* data sources yet ! for (size_t i=0; i < args.size(); ++i ) { const types::TypeInfo* ti = args[i]->getTypeInfo(); CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); if (!ctt) throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName()); DataSourceBase::shared_ptr tryout = ti->buildValue(); ctt->updateAny(tryout, nargs[i]); } // check argument types and produce: try { // will throw if wrong args. mfact->checkOperation(method.c_str(), nargs.in() ); // convert returned any to local type: const types::TypeInfo* ti = this->getArgumentType(0); if ( ti ) { if ( ti != Types()->type("void") ) { // create a method call object and a return value and let the former store results in the latter. CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) ); DataSourceBase::shared_ptr result = ti->buildValue(); // evaluate()/get() will cause the method to be called and remote return value will end up in result. return ti->buildActionAlias(new CorbaOperationCallerCall(mfact.in(),method,args,caller, ctt, result, true), result ); } else { return new DataSourceCommand( new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, DataSourceBase::shared_ptr() , true) ); } } else { // it's returning a type we don't know ! Return a DataSource<Any> DataSource<CORBA::Any_var>::shared_ptr result = new AnyDataSource( new CORBA::Any() ); // todo Provide a ctt implementation for 'CORBA::Any_var' such that the result is updated ! // The result is only for dummy reasons used now, since no ctt is set, no updating will be done. return new ActionAliasDataSource<CORBA::Any_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, true), result.get() ); } } catch ( corba::CNoSuchNameException& nsn ) { throw name_not_found_exception( nsn.name.in() ); } catch ( corba::CWrongNumbArgException& wa ) { throw wrong_number_of_args_exception( wa.wanted, wa.received ); } catch ( corba::CWrongTypeArgException& wta ) { throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() ); } return 0; // not reached. }