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 } catch ( corba::CCallError& e) {
00209 throw std::runtime_error(std::string(e.what.in()));
00210 }
00211 }
00212
00213 ActionInterface* clone() const { return new CorbaOperationCallerCall(CService::_duplicate( mfact.in() ), mop, margs, mcaller, mctt, mresult, mdocall); }
00214
00215 virtual ActionInterface* copy( std::map<const DataSourceBase*, DataSourceBase*>& alreadyCloned ) const {
00216 vector<DataSourceBase::shared_ptr> argcopy( margs.size() );
00217 unsigned int v=0;
00218 for (vector<DataSourceBase::shared_ptr>::iterator it = argcopy.begin(); it != argcopy.end(); ++it, ++v)
00219 argcopy[v] = (*it)->copy(alreadyCloned);
00220 return new CorbaOperationCallerCall(CService::_duplicate( mfact.in() ), mop, argcopy, mcaller, mctt, mresult->copy(alreadyCloned), mdocall);
00221 }
00222 };
00223
00224 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produce(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const {
00225 corba::CAnyArguments_var nargs = new corba::CAnyArguments();
00226 nargs->length( args.size() );
00227
00228
00229
00230 for (size_t i=0; i < args.size(); ++i ) {
00231 const types::TypeInfo* ti = args[i]->getTypeInfo();
00232 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00233 if (!ctt)
00234 throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName());
00235 DataSourceBase::shared_ptr tryout = ti->buildValue();
00236 ctt->updateAny(tryout, nargs[i]);
00237 }
00238
00239 try {
00240
00241 mfact->checkOperation(method.c_str(), nargs.in() );
00242
00243 const types::TypeInfo* ti = this->getArgumentType(0);
00244 if ( ti ) {
00245 if ( ti != Types()->type("void") ) {
00246
00247 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00248 DataSourceBase::shared_ptr result = ti->buildValue();
00249
00250 return ti->buildActionAlias(new CorbaOperationCallerCall(mfact.in(),method,args,caller, ctt, result, true), result );
00251 } else {
00252 return new DataSourceCommand( new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, DataSourceBase::shared_ptr() , true) );
00253 }
00254 } else {
00255
00256 DataSource<CORBA::Any_var>::shared_ptr result = new AnyDataSource( new CORBA::Any() );
00257
00258
00259 return new ActionAliasDataSource<CORBA::Any_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, true), result.get() );
00260 }
00261 } catch ( corba::CNoSuchNameException& nsn ) {
00262 throw name_not_found_exception( nsn.name.in() );
00263 } catch ( corba::CWrongNumbArgException& wa ) {
00264 throw wrong_number_of_args_exception( wa.wanted, wa.received );
00265 } catch ( corba::CWrongTypeArgException& wta ) {
00266 throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() );
00267 }
00268 return 0;
00269 }
00270
00271 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const {
00272 corba::CAnyArguments_var nargs = new corba::CAnyArguments();
00273 nargs->length( args.size() );
00274 for (size_t i=0; i < args.size(); ++i ) {
00275 const types::TypeInfo* ti = args[i]->getTypeInfo();
00276 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00277 if (!ctt)
00278 throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName());
00279 DataSourceBase::shared_ptr tryout = ti->buildValue();
00280 ctt->updateAny(tryout, nargs[i]);
00281 }
00282 try {
00283
00284 mfact->checkOperation(method.c_str(), nargs.inout() );
00285
00286 DataSource<CSendHandle_var>::shared_ptr result = new ValueDataSource<CSendHandle_var>();
00287 return new ActionAliasDataSource<CSendHandle_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, false), result.get() );
00288 } catch ( corba::CNoSuchNameException& nsn ) {
00289 throw name_not_found_exception( nsn.name.in() );
00290 } catch ( corba::CWrongNumbArgException& wa ) {
00291 throw wrong_number_of_args_exception( wa.wanted, wa.received );
00292 } catch ( corba::CWrongTypeArgException& wta ) {
00293 throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() );
00294 }
00295 return 0;
00296 }
00297
00298 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceHandle() const {
00299
00300 return new ValueDataSource<CSendHandle_var>();
00301 }
00302
00311 class CorbaOperationCallerCollect: public DataSource<SendStatus>
00312 {
00313 CSendHandle_var msh;
00314 std::vector<base::DataSourceBase::shared_ptr> margs;
00315 DataSource<bool>::shared_ptr misblocking;
00316 mutable SendStatus mss;
00317 public:
00318 CorbaOperationCallerCollect(CSendHandle_ptr sh,
00319 std::vector<base::DataSourceBase::shared_ptr> const& args,
00320 DataSource<bool>::shared_ptr isblocking)
00321 : msh( CSendHandle::_duplicate(sh)), margs(args), misblocking(isblocking), mss(SendFailure)
00322 {
00323 }
00324
00325 ~CorbaOperationCallerCollect() {
00326 try {
00327 msh->dispose();
00328 } catch(...) {}
00329 }
00330
00331 SendStatus value() const { return mss; }
00332
00333 SendStatus const& rvalue() const { return mss; }
00334
00335 SendStatus get() const {
00336 try {
00337
00338 if ( mss != SendSuccess ) {
00339 corba::CAnyArguments_var nargs;
00340 if ( misblocking->get() ) {
00341 mss = SendStatus( static_cast<int>(msh->collect( nargs.out() ) ) - 1 );
00342 } else {
00343 mss = SendStatus( static_cast<int>(msh->collectIfDone( nargs.out() ) ) - 1 );
00344 }
00345
00346 if (mss == SendSuccess) {
00347 assert( nargs->length() == margs.size() );
00348 for (size_t i=0; i < margs.size(); ++i ) {
00349 const types::TypeInfo* ti = margs[i]->getTypeInfo();
00350 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00351 assert( ctt );
00352 ctt->updateFromAny( &nargs[i], margs[i] );
00353 }
00354 }
00355 }
00356 return mss;
00357 } catch ( corba::CWrongNumbArgException& ) {
00358 return mss;
00359 } catch ( corba::CWrongTypeArgException& ) {
00360 return mss;
00361 } catch ( corba::CCallError& e) {
00362 throw std::runtime_error(std::string(e.what.in()));
00363 }
00364 }
00365
00366 DataSource<SendStatus>* clone() const { return new CorbaOperationCallerCollect(CSendHandle::_duplicate( msh.in() ), margs, misblocking); }
00367
00368 virtual DataSource<SendStatus>* copy( std::map<const DataSourceBase*, DataSourceBase*>& alreadyCloned ) const {
00369 vector<DataSourceBase::shared_ptr> argcopy( margs.size() );
00370 unsigned int v=0;
00371 for (vector<DataSourceBase::shared_ptr>::iterator it = argcopy.begin(); it != argcopy.end(); ++it, ++v)
00372 argcopy[v] = (*it)->copy(alreadyCloned);
00373 return new CorbaOperationCallerCollect(CSendHandle::_duplicate( msh.in() ), argcopy, misblocking);
00374 }
00375 };
00376
00377
00378 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, internal::DataSource<bool>::shared_ptr blocking) const {
00379 unsigned int expected = mfact->getCollectArity(method.c_str());
00380 if (args.size() != expected + 1) {
00381 throw wrong_number_of_args_exception( expected + 1, args.size() );
00382 }
00383
00384 std::vector<base::DataSourceBase::shared_ptr> cargs( ++args.begin(), args.end() );
00385 DataSource<CSendHandle_var>::shared_ptr ds = DataSource<CSendHandle_var>::narrow( args.begin()->get() );
00386 if (!ds) {
00387 throw wrong_types_of_args_exception(0,"CSendHandle_var",(*args.begin())->getTypeName() );
00388 }
00389
00390 try {
00391 corba::CAnyArguments_var nargs = new corba::CAnyArguments();
00392 nargs->length( cargs.size() );
00393 for (size_t i=0; i < cargs.size(); ++i ) {
00394 const types::TypeInfo* ti = cargs[i]->getTypeInfo();
00395 CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
00396 assert( ctt );
00397 DataSourceBase::shared_ptr tryout = ti->buildValue();
00398 ctt->updateAny(tryout, nargs[i]);
00399 }
00400 ds->get()->checkArguments( nargs.in() );
00401 } catch ( CWrongNumbArgException& wna) {
00402 throw wrong_number_of_args_exception(wna.wanted, wna.received);
00403 } catch ( CWrongTypeArgException& wta) {
00404 throw wrong_types_of_args_exception(wta.whicharg,wta.expected.in(), wta.received.in());
00405 }
00406
00407 return new CorbaOperationCallerCollect( ds->get().in(),cargs, blocking);
00408 }
00409
00410 #ifdef ORO_SIGNALLING_OPERATIONS
00411 Handle CorbaOperationCallerFactory::produceSignal(base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* subscriber) const {
00412 log(Error) << "Can not attach Signal to remote Corba Operation '"<<method <<"'" <<endlog();
00413 return Handle();
00414 }
00415 #endif