00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "CorbaOperationCallerFactory.hpp"
00040 #include "AnyDataSource.hpp"
00041 #include "CorbaLib.hpp"
00042
00043 #include "../../types/Types.hpp"
00044 #include "../../internal/DataSources.hpp"
00045 #include "../../internal/DataSourceCommand.hpp"
00046 #include "../../SendStatus.hpp"
00047 #include "../../Handle.hpp"
00048
00049 using namespace std;
00050 using namespace RTT;
00051 using namespace RTT::detail;
00052
00053 CorbaOperationCallerFactory::CorbaOperationCallerFactory( const std::string& method_name, corba::CService_ptr fact, PortableServer::POA_ptr the_poa )
00054 : RTT::OperationInterfacePart(),
00055 mfact(corba::CService::_duplicate(fact) ),
00056 mpoa(PortableServer::POA::_duplicate(the_poa)),
00057 method(method_name)
00058 {}
00059
00060 CorbaOperationCallerFactory::~CorbaOperationCallerFactory() {}
00061
00062 unsigned int CorbaOperationCallerFactory::arity() const {
00063 return mfact->getArity( method.c_str() );
00064 }
00065
00066 unsigned int CorbaOperationCallerFactory::collectArity() const {
00067 return mfact->getCollectArity( method.c_str() );
00068 }
00069
00070 const TypeInfo* CorbaOperationCallerFactory::getArgumentType(unsigned int i) const {
00071 try {
00072 CORBA::String_var tname = mfact->getArgumentType( method.c_str(), i);
00073 if ( Types()->type( tname.in() ) != 0 )
00074 return Types()->type( tname.in() );
00075
00076 if (i == 0)
00077 log(Warning) << "CorbaOperationCallerFactory: remote operation's "<< method <<" return type " << tname.in() << " is unknown in this process." << endlog();
00078 else
00079 log(Warning) << "CorbaOperationCallerFactory: remote operation's "<< method <<" argument "<< i <<" of type " << tname.in() << " is unknown in this process." << endlog();
00080 } catch ( CNoSuchNameException& ) {
00081 assert(false);
00082 }
00083 catch ( CWrongArgumentException& wae){
00084 log(Error) << "CorbaOperationCallerFactory::getArgumentType: Wrong arg nbr: " << wae.which_arg <<" max is " << wae.max_arg <<endlog();
00085 }
00086 return 0;
00087 }
00088
00089 const TypeInfo* CorbaOperationCallerFactory::getCollectType(unsigned int i) const {
00090 try {
00091 CORBA::String_var tname = mfact->getCollectType( method.c_str(), i);
00092 return Types()->type( tname.in() );
00093 } catch (...){
00094 return 0;
00095 }
00096 }
00097
00098
00099 std::string CorbaOperationCallerFactory::resultType() const {
00100 try {
00101 CORBA::String_var result = mfact->getResultType( method.c_str() );
00102 return std::string( result.in() );
00103 } catch ( corba::CNoSuchNameException& nsn ) {
00104 throw name_not_found_exception( nsn.name.in() );
00105 }
00106 return std::string();
00107 }
00108
00109 std::string CorbaOperationCallerFactory::getName() const {
00110 return method;
00111 }
00112
00113 std::string CorbaOperationCallerFactory::description() const {
00114 try {
00115 CORBA::String_var result = mfact->getDescription( method.c_str() );
00116 return std::string( result.in() );
00117 } catch ( corba::CNoSuchNameException& nsn ) {
00118 throw name_not_found_exception( nsn.name.in() );
00119 }
00120 return std::string();
00121 }
00122
00123 std::vector< ArgumentDescription > CorbaOperationCallerFactory::getArgumentList() const {
00124 CDescriptions ret;
00125 try {
00126 corba::CDescriptions_var result = mfact->getArguments( method.c_str() );
00127 ret.reserve( result->length() );
00128 for (size_t i=0; i!= result->length(); ++i)
00129 ret.push_back( ArgumentDescription(std::string( result[i].name.in() ),
00130 std::string( result[i].description.in() ),
00131 std::string( result[i].type.in() ) ));
00132 } catch ( corba::CNoSuchNameException& nsn ) {
00133 throw name_not_found_exception( nsn.name.in() );
00134 }
00135 return ret;
00136 }
00137
00146 class CorbaOperationCallerCall: public ActionInterface
00147 {
00148 CService_var mfact;
00149 std::string mop;
00150 std::vector<base::DataSourceBase::shared_ptr> margs;
00151 ExecutionEngine* mcaller;
00152 base::DataSourceBase::shared_ptr mresult;
00153 corba::CAnyArguments_var nargs;
00154
00155 CorbaTypeTransporter* mctt;
00156 bool mdocall;
00157 public:
00158 CorbaOperationCallerCall(CService_ptr fact,
00159 std::string op,
00160 std::vector<base::DataSourceBase::shared_ptr> const& args,
00161 ExecutionEngine* caller,
00162 CorbaTypeTransporter* ctt,
00163 base::DataSourceBase::shared_ptr result, bool docall)
00164 : mfact(CService::_duplicate(fact)), mop(op), margs(args), mcaller(caller), mresult(result), mctt(ctt), mdocall(docall)
00165 {
00166 }
00167
00168 void readArguments() {
00169
00170
00171 nargs = new corba::CAnyArguments();
00172 nargs->length( margs.size() );
00173 for (size_t i=0; i < margs.size(); ++i ) {
00174 const types::TypeInfo* ti = margs[i]->getTypeInfo();
00175 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00176 assert( ctt );
00177 ctt->updateAny(margs[i], nargs[i]);
00178 }
00179 }
00180
00181 bool execute() {
00182 try {
00183 if (mdocall) {
00184 CORBA::Any_var any = mfact->callOperation( mop.c_str(), nargs.inout() );
00185 for (size_t i=0; i < margs.size(); ++i ) {
00186 const types::TypeInfo* ti = margs[i]->getTypeInfo();
00187 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00188 assert( ctt );
00189 ctt->updateFromAny( &nargs[i], margs[i] );
00190 }
00191
00192 if (mctt)
00193 return mctt->updateFromAny(&any.in(), mresult);
00194 } else {
00195 CSendHandle_var sh = mfact->sendOperation( mop.c_str(), nargs.in() );
00196 AssignableDataSource<CSendHandle_var>::shared_ptr ads = AssignableDataSource<CSendHandle_var>::narrow( mresult.get() );
00197 if (ads) {
00198 ads->set( sh );
00199 }
00200 }
00201 return true;
00202 } catch ( corba::CNoSuchNameException& ) {
00203 return false;
00204 } catch ( corba::CWrongNumbArgException& ) {
00205 return false;
00206 } catch ( corba::CWrongTypeArgException& ) {
00207 return false;
00208 }
00209
00210 }
00211
00212 ActionInterface* clone() const { return new CorbaOperationCallerCall(CService::_duplicate( mfact.in() ), mop, margs, mcaller, mctt, mresult, mdocall); }
00213
00214 virtual ActionInterface* copy( std::map<const DataSourceBase*, DataSourceBase*>& alreadyCloned ) const {
00215 vector<DataSourceBase::shared_ptr> argcopy( margs.size() );
00216 unsigned int v=0;
00217 for (vector<DataSourceBase::shared_ptr>::iterator it = argcopy.begin(); it != argcopy.end(); ++it, ++v)
00218 argcopy[v] = (*it)->copy(alreadyCloned);
00219 return new CorbaOperationCallerCall(CService::_duplicate( mfact.in() ), mop, argcopy, mcaller, mctt, mresult->copy(alreadyCloned), mdocall);
00220 }
00221 };
00222
00223 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produce(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const {
00224 corba::CAnyArguments_var nargs = new corba::CAnyArguments();
00225 nargs->length( args.size() );
00226
00227
00228
00229 for (size_t i=0; i < args.size(); ++i ) {
00230 const types::TypeInfo* ti = args[i]->getTypeInfo();
00231 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00232 if (!ctt)
00233 throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName());
00234 DataSourceBase::shared_ptr tryout = ti->buildValue();
00235 ctt->updateAny(tryout, nargs[i]);
00236 }
00237
00238 try {
00239
00240 mfact->checkOperation(method.c_str(), nargs.in() );
00241
00242 const types::TypeInfo* ti = this->getArgumentType(0);
00243 if ( ti ) {
00244 if ( ti != Types()->type("void") ) {
00245
00246 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00247 DataSourceBase::shared_ptr result = ti->buildValue();
00248
00249 return ti->buildActionAlias(new CorbaOperationCallerCall(mfact.in(),method,args,caller, ctt, result, true), result );
00250 } else {
00251 return new DataSourceCommand( new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, DataSourceBase::shared_ptr() , true) );
00252 }
00253 } else {
00254
00255 DataSource<CORBA::Any_var>::shared_ptr result = new AnyDataSource( new CORBA::Any() );
00256
00257
00258 return new ActionAliasDataSource<CORBA::Any_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, true), result.get() );
00259 }
00260 } catch ( corba::CNoSuchNameException& nsn ) {
00261 throw name_not_found_exception( nsn.name.in() );
00262 } catch ( corba::CWrongNumbArgException& wa ) {
00263 throw wrong_number_of_args_exception( wa.wanted, wa.received );
00264 } catch ( corba::CWrongTypeArgException& wta ) {
00265 throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() );
00266 }
00267 return 0;
00268 }
00269
00270 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const {
00271 corba::CAnyArguments_var nargs = new corba::CAnyArguments();
00272 nargs->length( args.size() );
00273 for (size_t i=0; i < args.size(); ++i ) {
00274 const types::TypeInfo* ti = args[i]->getTypeInfo();
00275 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00276 if (!ctt)
00277 throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName());
00278 DataSourceBase::shared_ptr tryout = ti->buildValue();
00279 ctt->updateAny(tryout, nargs[i]);
00280 }
00281 try {
00282
00283 mfact->checkOperation(method.c_str(), nargs.inout() );
00284
00285 DataSource<CSendHandle_var>::shared_ptr result = new ValueDataSource<CSendHandle_var>();
00286 return new ActionAliasDataSource<CSendHandle_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, false), result.get() );
00287 } catch ( corba::CNoSuchNameException& nsn ) {
00288 throw name_not_found_exception( nsn.name.in() );
00289 } catch ( corba::CWrongNumbArgException& wa ) {
00290 throw wrong_number_of_args_exception( wa.wanted, wa.received );
00291 } catch ( corba::CWrongTypeArgException& wta ) {
00292 throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() );
00293 }
00294 return 0;
00295 }
00296
00297 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceHandle() const {
00298
00299 return new ValueDataSource<CSendHandle_var>();
00300 }
00301
00310 class CorbaOperationCallerCollect: public DataSource<SendStatus>
00311 {
00312 CSendHandle_var msh;
00313 std::vector<base::DataSourceBase::shared_ptr> margs;
00314 DataSource<bool>::shared_ptr misblocking;
00315 mutable SendStatus mss;
00316 public:
00317 CorbaOperationCallerCollect(CSendHandle_ptr sh,
00318 std::vector<base::DataSourceBase::shared_ptr> const& args,
00319 DataSource<bool>::shared_ptr isblocking)
00320 : msh( CSendHandle::_duplicate(sh)), margs(args), misblocking(isblocking), mss(SendFailure)
00321 {
00322 }
00323
00324 ~CorbaOperationCallerCollect() {
00325 try {
00326 msh->dispose();
00327 } catch(...) {}
00328 }
00329
00330 SendStatus value() const { return mss; }
00331
00332 SendStatus const& rvalue() const { return mss; }
00333
00334 SendStatus get() const {
00335 try {
00336
00337 if ( mss != SendSuccess ) {
00338 corba::CAnyArguments_var nargs;
00339 if ( misblocking->get() ) {
00340 mss = SendStatus( static_cast<int>(msh->collect( nargs.out() ) ) - 1 );
00341 } else {
00342 mss = SendStatus( static_cast<int>(msh->collectIfDone( nargs.out() ) ) - 1 );
00343 }
00344
00345 if (mss == SendSuccess) {
00346 assert( nargs->length() == margs.size() );
00347 for (size_t i=0; i < margs.size(); ++i ) {
00348 const types::TypeInfo* ti = margs[i]->getTypeInfo();
00349 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00350 assert( ctt );
00351 ctt->updateFromAny( &nargs[i], margs[i] );
00352 }
00353 }
00354 }
00355 return mss;
00356 } catch ( corba::CWrongNumbArgException& ) {
00357 return mss;
00358 } catch ( corba::CWrongTypeArgException& ) {
00359 return mss;
00360 }
00361 }
00362
00363 DataSource<SendStatus>* clone() const { return new CorbaOperationCallerCollect(CSendHandle::_duplicate( msh.in() ), margs, misblocking); }
00364
00365 virtual DataSource<SendStatus>* copy( std::map<const DataSourceBase*, DataSourceBase*>& alreadyCloned ) const {
00366 vector<DataSourceBase::shared_ptr> argcopy( margs.size() );
00367 unsigned int v=0;
00368 for (vector<DataSourceBase::shared_ptr>::iterator it = argcopy.begin(); it != argcopy.end(); ++it, ++v)
00369 argcopy[v] = (*it)->copy(alreadyCloned);
00370 return new CorbaOperationCallerCollect(CSendHandle::_duplicate( msh.in() ), argcopy, misblocking);
00371 }
00372 };
00373
00374
00375 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, internal::DataSource<bool>::shared_ptr blocking) const {
00376 unsigned int expected = mfact->getCollectArity(method.c_str());
00377 if (args.size() != expected + 1) {
00378 throw wrong_number_of_args_exception( expected + 1, args.size() );
00379 }
00380
00381 std::vector<base::DataSourceBase::shared_ptr> cargs( ++args.begin(), args.end() );
00382 DataSource<CSendHandle_var>::shared_ptr ds = DataSource<CSendHandle_var>::narrow( args.begin()->get() );
00383 if (!ds) {
00384 throw wrong_types_of_args_exception(0,"CSendHandle_var",(*args.begin())->getTypeName() );
00385 }
00386
00387 try {
00388 corba::CAnyArguments_var nargs = new corba::CAnyArguments();
00389 nargs->length( cargs.size() );
00390 for (size_t i=0; i < cargs.size(); ++i ) {
00391 const types::TypeInfo* ti = cargs[i]->getTypeInfo();
00392 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00393 assert( ctt );
00394 DataSourceBase::shared_ptr tryout = ti->buildValue();
00395 ctt->updateAny(tryout, nargs[i]);
00396 }
00397 ds->get()->checkArguments( nargs.in() );
00398 } catch ( CWrongNumbArgException& wna) {
00399 throw wrong_number_of_args_exception(wna.wanted, wna.received);
00400 } catch ( CWrongTypeArgException& wta) {
00401 throw wrong_types_of_args_exception(wta.whicharg,wta.expected.in(), wta.received.in());
00402 }
00403
00404 return new CorbaOperationCallerCollect( ds->get().in(),cargs, blocking);
00405 }
00406
00407 Handle CorbaOperationCallerFactory::produceSignal(base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args) const {
00408 log(Error) << "Can not attach Signal to remote Corba Operation '"<<method <<"'" <<endlog();
00409 return Handle();
00410 }