CorbaOperationCallerFactory.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 CorbaOperationCallerFactory.cpp
3 
4  CorbaOperationCallerFactory.cpp - description
5  -------------------
6  begin : Tue September 07 2010
7  copyright : (C) 2010 The SourceWorks
8  email : peter@thesourceworks.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
40 #include "AnyDataSource.hpp"
41 #include "CorbaLib.hpp"
42 
43 #include "../../types/Types.hpp"
44 #include "../../internal/DataSources.hpp"
45 #include "../../internal/DataSourceCommand.hpp"
46 #include "../../SendStatus.hpp"
47 #include "../../Handle.hpp"
48 
49 using namespace std;
50 using namespace RTT;
51 using namespace RTT::detail;
52 
53 CorbaOperationCallerFactory::CorbaOperationCallerFactory(const std::string &method_name, corba::CService_ptr fact, PortableServer::POA_ptr the_poa )
55  mfact(corba::CService::_duplicate(fact) ),
56  mpoa(PortableServer::POA::_duplicate(the_poa)),
57  method(method_name)
58 {}
59 
60 CorbaOperationCallerFactory::CorbaOperationCallerFactory(const COperation &operation, corba::CService_ptr fact, PortableServer::POA_ptr the_poa )
62  mfact(corba::CService::_duplicate(fact) ),
63  mpoa(PortableServer::POA::_duplicate(the_poa)),
64  method(operation.name.in()),
65  mdescription(new COperation(operation))
66 {}
67 
69 
70 unsigned int CorbaOperationCallerFactory::arity() const {
71  if (mdescription)
72  return mdescription->arguments.length();
73 
74  return mfact->getArity( method.c_str() );
75 }
76 
78  if (mdescription)
79  return mdescription->collect_types.length();
80 
81  return mfact->getCollectArity( method.c_str() );
82 }
83 
85  std::string tname;
86 
87  if (mdescription) {
88  if (i == 0) {
89  tname = mdescription->result_type.in();
90  } else if (i <= mdescription->arguments.length()) {
91  tname = mdescription->arguments[i-1].type.in();
92  }
93 
94  // COperation mdescription contains fully-qualified argument types as returned
95  // by OperationInterfacePart::getArgumentList() and DataSourceTypeInfo<T>::getType(),
96  // while COperationInterface::getArgumentType() would return the unqualified type
97  // name as DataSourceTypeInfo<T>::getType().
98  // ==> Strip qualifiers from tname before lookup in the TypeInfoRepository.
99  std::string::size_type separator = tname.find(' ');
100  if ( separator != std::string::npos ) {
101  tname = tname.substr(0, separator);
102  }
103 
104  } else {
105  try {
106  tname = mfact->getArgumentType( method.c_str(), i);
107  } catch ( CNoSuchNameException& ) {
108  assert(false);
109  }
110  catch ( CWrongArgumentException& wae){
111  log(Error) << "CorbaOperationCallerFactory::getArgumentType: Wrong arg nbr: " << wae.which_arg <<" max is " << wae.max_arg <<endlog();
112  }
113  }
114 
115  if (tname.empty()) return 0;
116 
117  if ( Types()->type( tname ) != 0 )
118  return Types()->type( tname );
119  // locally unknown type:
120  if (i == 0)
121  log(Warning) << "CorbaOperationCallerFactory: remote operation's "<< method <<" return type " << tname << " is unknown in this process." << endlog();
122  else
123  log(Warning) << "CorbaOperationCallerFactory: remote operation's "<< method <<" argument "<< i <<" of type " << tname << " is unknown in this process." << endlog();
124 
125  return 0;
126 }
127 
129 
130  if (mdescription && i < mdescription->collect_types.length()) {
131  return Types()->type( mdescription->collect_types[i].in() );
132 
133  } else {
134 
135  try {
136  CORBA::String_var tname = mfact->getCollectType( method.c_str(), i);
137  return Types()->type( tname.in() );
138  } catch (...){
139  return 0;
140  }
141  }
142 
143  return 0;
144 }
145 
146 
148  if (mdescription)
149  return mdescription->result_type.in();
150 
151  try {
152  CORBA::String_var result = mfact->getResultType( method.c_str() );
153  return std::string( result.in() );
154  } catch ( corba::CNoSuchNameException& nsn ) {
155  throw name_not_found_exception( nsn.name.in() );
156  }
157  return std::string();
158 }
159 
161  return method;
162 }
163 
165  if (mdescription)
166  return mdescription->description.in();
167 
168  try {
169  CORBA::String_var result = mfact->getDescription( method.c_str() );
170  return std::string( result.in() );
171  } catch ( corba::CNoSuchNameException& nsn ) {
172  throw name_not_found_exception( nsn.name.in() );
173  }
174  return std::string();
175 }
176 
177 std::vector< ArgumentDescription > CorbaOperationCallerFactory::getArgumentList() const {
178  corba::CArgumentDescriptions_var result;
179  const corba::CArgumentDescriptions *result_ptr = 0;
180 
181  if (mdescription) {
182  result_ptr = &(mdescription->arguments);
183  } else {
184  try {
185  result = mfact->getArguments( method.c_str() );
186  result_ptr = &(result.in());
187  } catch ( corba::CNoSuchNameException& nsn ) {
188  throw name_not_found_exception( nsn.name.in() );
189  }
190  }
191 
193  ret.reserve( result_ptr->length() );
194  for (size_t i=0; i!= result_ptr->length(); ++i)
195  ret.push_back( ArgumentDescription(std::string( (*result_ptr)[i].name.in() ),
196  std::string( (*result_ptr)[i].description.in() ),
197  std::string( (*result_ptr)[i].type.in() ) ));
198  return ret;
199 }
200 
209 class CorbaOperationCallerCall: public ActionInterface
210 {
211  CService_var mfact;
212  std::string mop;
213  std::vector<base::DataSourceBase::shared_ptr> margs;
216  corba::CAnyArguments_var nargs;
217  // The type transporter for the return value
218  CorbaTypeTransporter* mctt;
219  bool mdocall;
220  bool moneway;
221 public:
222  CorbaOperationCallerCall(CService_ptr fact,
223  std::string op,
224  std::vector<base::DataSourceBase::shared_ptr> const& args,
225  ExecutionEngine* caller,
226  CorbaTypeTransporter* ctt,
227  base::DataSourceBase::shared_ptr result, bool docall, bool oneway)
228  : mfact(CService::_duplicate(fact)), mop(op), margs(args), mcaller(caller), mresult(result), mctt(ctt), mdocall(docall), moneway(oneway)
229  {
230  }
231 
232  void readArguments() {
233  // We need to delay reading the arguments upto this point such that the args contain
234  // the latest values.
235  nargs = new corba::CAnyArguments();
236  nargs->length( margs.size() );
237  for (size_t i=0; i < margs.size(); ++i ) {
238  const types::TypeInfo* ti = margs[i]->getTypeInfo();
239  CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
240  assert( ctt );
241  ctt->updateAny(margs[i], nargs[i]);
242  }
243  }
244 
245  bool execute() {
246  try {
247  if (mdocall) {
248  CORBA::Any_var any = mfact->callOperation( mop.c_str(), nargs.inout() );
249  for (size_t i=0; i < margs.size(); ++i ) {
250  const types::TypeInfo* ti = margs[i]->getTypeInfo();
251  CorbaTypeTransporter* ctt = dynamic_cast<CorbaTypeTransporter*>( ti->getProtocol(ORO_CORBA_PROTOCOL_ID) );
252  assert( ctt );
253  ctt->updateFromAny( &nargs[i], margs[i] );
254  }
255  // convert returned any to local type:
256  if (mctt)
257  return mctt->updateFromAny(&any.in(), mresult);
258  } else {
259  if (!moneway) {
260  CSendHandle_var sh = mfact->sendOperation( mop.c_str(), nargs.in() );
262  if (ads) {
263  ads->set( sh ); // _var creates a copy of the obj reference.
264  }
265  } else {
266  mfact->sendOperationOneway( mop.c_str(), nargs.in() );
267  }
268 
269  }
270  return true;
271  } catch ( corba::CNoSuchNameException& ) {
272  return false;
273  } catch ( corba::CWrongNumbArgException& ) {
274  return false;
275  } catch ( corba::CWrongTypeArgException& ) {
276  return false;
277  } catch ( corba::CCallError& e) {
278  throw std::runtime_error(std::string(e.what.in()));
279  }
280  }
281 
282  ActionInterface* clone() const { return new CorbaOperationCallerCall(CService::_duplicate( mfact.in() ), mop, margs, mcaller, mctt, mresult, mdocall, moneway); }
283 
284  virtual ActionInterface* copy( std::map<const DataSourceBase*, DataSourceBase*>& alreadyCloned ) const {
285  vector<DataSourceBase::shared_ptr> argcopy( margs.size() );
286  unsigned int v=0;
287  for (vector<DataSourceBase::shared_ptr>::iterator it = argcopy.begin(); it != argcopy.end(); ++it, ++v)
288  argcopy[v] = (*it)->copy(alreadyCloned);
289  DataSourceBase::shared_ptr result = mresult ? mresult->copy(alreadyCloned) : 0;
290  return new CorbaOperationCallerCall(CService::_duplicate( mfact.in() ), mop, argcopy, mcaller, mctt, result, mdocall, moneway);
291  }
292 };
293 
294 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produce(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const {
295 #ifndef RTT_CORBA_NO_CHECK_OPERATIONS
296  corba::CAnyArguments_var nargs = new corba::CAnyArguments();
297  nargs->length( args.size() );
298 
299  // this part is only done to feed to checkOperation() with some defaults.
300  // We don't want to evaluate() the *real* data sources yet !
301  for (size_t i=0; i < args.size(); ++i ) {
302  const types::TypeInfo* ti = args[i]->getTypeInfo();
304  if (!ctt)
305  throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName());
306  DataSourceBase::shared_ptr tryout = ti->buildValue();
307  ctt->updateAny(tryout, nargs[i]);
308  }
309 #endif
310 
311  // check argument types and produce:
312  try {
313 #ifndef RTT_CORBA_NO_CHECK_OPERATIONS
314  // will throw if wrong args.
315  mfact->checkOperation(method.c_str(), nargs.in() );
316 #endif
317  // convert returned any to local type:
318  const types::TypeInfo* ti = this->getArgumentType(0);
319  if ( ti ) {
320  if ( ti != Types()->type("void") ) {
321  // create a method call object and a return value and let the former store results in the latter.
323  DataSourceBase::shared_ptr result = ti->buildValue();
324  // evaluate()/get() will cause the method to be called and remote return value will end up in result.
325  return ti->buildActionAlias(new CorbaOperationCallerCall(mfact.in(),method,args,caller, ctt, result, true, false), result );
326  } else {
327  return new DataSourceCommand( new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, DataSourceBase::shared_ptr() , true, false) );
328  }
329  } else {
330  // it's returning a type we don't know ! Return a DataSource<Any>
331  DataSource<CORBA::Any_var>::shared_ptr result = new AnyDataSource( new CORBA::Any() );
332  // todo Provide a ctt implementation for 'CORBA::Any_var' such that the result is updated !
333  // The result is only for dummy reasons used now, since no ctt is set, no updating will be done.
334  return new ActionAliasDataSource<CORBA::Any_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, true, false), result.get() );
335  }
336  } catch ( corba::CNoSuchNameException& nsn ) {
337  throw name_not_found_exception( nsn.name.in() );
338  } catch ( corba::CWrongNumbArgException& wa ) {
339  throw wrong_number_of_args_exception( wa.wanted, wa.received );
340  } catch ( corba::CWrongTypeArgException& wta ) {
341  throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() );
342  }
343  return 0; // not reached.
344 }
345 
346 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const {
347 #ifndef RTT_CORBA_NO_CHECK_OPERATIONS
348  corba::CAnyArguments_var nargs = new corba::CAnyArguments();
349  nargs->length( args.size() );
350  for (size_t i=0; i < args.size(); ++i ) {
351  const types::TypeInfo* ti = args[i]->getTypeInfo();
353  if (!ctt)
354  throw wrong_types_of_args_exception(i+1,"type known to CORBA transport", ti->getTypeName());
355  DataSourceBase::shared_ptr tryout = ti->buildValue();
356  ctt->updateAny(tryout, nargs[i]);
357  }
358 #endif
359 
360  try {
361 #ifndef RTT_CORBA_NO_CHECK_OPERATIONS
362  // will throw if wrong args.
363  mfact->checkOperation(method.c_str(), nargs.inout() );
364 #endif
365  // Will return a CSendHandle_var:
367 #ifdef RTT_CORBA_SEND_ONEWAY_OPERATIONS
368  bool oneway = (mdescription && mdescription->send_oneway);
369 #else
370  bool oneway = false;
371 #endif
372  return new ActionAliasDataSource<CSendHandle_var>(new CorbaOperationCallerCall(mfact.in(),method,args,caller, 0, result, false, oneway), result.get() );
373  } catch ( corba::CNoSuchNameException& nsn ) {
374  throw name_not_found_exception( nsn.name.in() );
375  } catch ( corba::CWrongNumbArgException& wa ) {
376  throw wrong_number_of_args_exception( wa.wanted, wa.received );
377  } catch ( corba::CWrongTypeArgException& wta ) {
378  throw wrong_types_of_args_exception( wta.whicharg, wta.expected.in(), wta.received.in() );
379  }
380  return 0; // not reached.
381 }
382 
384  // collect expects a handle of this type. Also send returns a CSendHandle_var, which can be copied into this handle object.
386 }
387 
396 class CorbaOperationCallerCollect: public DataSource<SendStatus>
397 {
398  CSendHandle_var msh;
399  std::vector<base::DataSourceBase::shared_ptr> margs;
401  mutable SendStatus mss;
402 public:
403  CorbaOperationCallerCollect(CSendHandle_ptr sh,
404  std::vector<base::DataSourceBase::shared_ptr> const& args,
405  DataSource<bool>::shared_ptr isblocking)
406  : msh( CSendHandle::_duplicate(sh)), margs(args), misblocking(isblocking), mss(SendFailure)
407  {
408  }
409 
411  try {
412  msh->dispose();
413  } catch(...) {}
414  }
415 
416  SendStatus value() const { return mss; }
417 
418  SendStatus const& rvalue() const { return mss; }
419 
420  SendStatus get() const {
421  try {
422  // only try to collect if we didn't do so before:
423  if ( mss != SendSuccess ) {
424  corba::CAnyArguments_var nargs;
425  if ( misblocking->get() ) {
426  mss = SendStatus( static_cast<int>(msh->collect( nargs.out() ) ) - 2 );
427  } else {
428  mss = SendStatus( static_cast<int>(msh->collectIfDone( nargs.out() ) ) - 2 );
429  }
430  // only convert results when we got a success:
431  if (mss == SendSuccess) {
432  assert( nargs->length() == margs.size() );
433  for (size_t i=0; i < margs.size(); ++i ) {
434  const types::TypeInfo* ti = margs[i]->getTypeInfo();
436  assert( ctt );
437  ctt->updateFromAny( &nargs[i], margs[i] );
438  }
439  }
440  }
441  return mss;
442  } catch ( corba::CWrongNumbArgException& ) {
443  return mss;
444  } catch ( corba::CWrongTypeArgException& ) {
445  return mss;
446  } catch ( corba::CCallError& e) {
447  throw std::runtime_error(std::string(e.what.in()));
448  }
449  }
450 
451  DataSource<SendStatus>* clone() const { return new CorbaOperationCallerCollect(CSendHandle::_duplicate( msh.in() ), margs, misblocking); }
452 
453  virtual DataSource<SendStatus>* copy( std::map<const DataSourceBase*, DataSourceBase*>& alreadyCloned ) const {
454  vector<DataSourceBase::shared_ptr> argcopy( margs.size() );
455  unsigned int v=0;
456  for (vector<DataSourceBase::shared_ptr>::iterator it = argcopy.begin(); it != argcopy.end(); ++it, ++v)
457  argcopy[v] = (*it)->copy(alreadyCloned);
458  return new CorbaOperationCallerCollect(CSendHandle::_duplicate( msh.in() ), argcopy, misblocking);
459  }
460 };
461 
462 
463 base::DataSourceBase::shared_ptr CorbaOperationCallerFactory::produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, internal::DataSource<bool>::shared_ptr blocking) const {
464  unsigned int expected = 0;
465  if (mdescription)
466  expected = mdescription->collect_types.length();
467  else
468  expected = mfact->getCollectArity(method.c_str());
469 
470  if (args.size() != expected + 1) {
471  throw wrong_number_of_args_exception( expected + 1, args.size() );
472  }
473  // isolate and check CSendHandle
474  std::vector<base::DataSourceBase::shared_ptr> cargs( ++args.begin(), args.end() );
476  if (!ds) {
477  throw wrong_types_of_args_exception(0,"CSendHandle_var",(*args.begin())->getTypeName() );
478  }
479  if ( CORBA::is_nil(ds->get()) ) return new ValueDataSource<SendStatus>(SendSuccess);
480  // check if args matches what CSendHandle expects.
481  try {
482  corba::CAnyArguments_var nargs = new corba::CAnyArguments();
483  nargs->length( cargs.size() );
484  for (size_t i=0; i < cargs.size(); ++i ) {
485  const types::TypeInfo* ti = cargs[i]->getTypeInfo();
487  assert( ctt );
488  DataSourceBase::shared_ptr tryout = ti->buildValue();
489  ctt->updateAny(tryout, nargs[i]);
490  }
491  ds->get()->checkArguments( nargs.in() );
492  } catch ( CWrongNumbArgException& wna) {
493  throw wrong_number_of_args_exception(wna.wanted, wna.received);
494  } catch ( CWrongTypeArgException& wta) {
495  throw wrong_types_of_args_exception(wta.whicharg,wta.expected.in(), wta.received.in());
496  }
497  // All went well, produce collect DataSource:
498  return new CorbaOperationCallerCollect( ds->get().in(),cargs, blocking);
499 }
500 
501 #ifdef ORO_SIGNALLING_OPERATIONS
502 Handle CorbaOperationCallerFactory::produceSignal(base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* subscriber) const {
503  log(Error) << "Can not attach Signal to remote Corba Operation '"<<method <<"'" <<endlog();
504  return Handle();
505 }
506 #endif
virtual const types::TypeInfo * getCollectType(unsigned int i) const
virtual base::DataSourceBase::shared_ptr produceHandle() const
const std::string & getTypeName() const
Definition: TypeInfo.hpp:83
std::vector< base::DataSourceBase::shared_ptr > margs
virtual void set(param_t t)=0
Definition: mystd.hpp:163
CorbaOperationCallerCall(CService_ptr fact, std::string op, std::vector< base::DataSourceBase::shared_ptr > const &args, ExecutionEngine *caller, CorbaTypeTransporter *ctt, base::DataSourceBase::shared_ptr result, bool docall, bool oneway)
virtual ActionInterface * copy(std::map< const DataSourceBase *, DataSourceBase * > &alreadyCloned) const
virtual base::DataSourceBase::shared_ptr produceCollect(const std::vector< base::DataSourceBase::shared_ptr > &args, internal::DataSource< bool >::shared_ptr blocking) const
base::DataSourceBase::shared_ptr buildActionAlias(base::ActionInterface *action, base::DataSourceBase::shared_ptr source) const
Definition: TypeInfo.hpp:248
SendStatus
Definition: SendStatus.hpp:53
virtual DataSource< T > * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const =0
virtual std::vector< ArgumentDescription > getArgumentList() const
DataSource< SendStatus > * clone() const
base::DataSourceBase::shared_ptr mresult
CorbaOperationCallerCollect(CSendHandle_ptr sh, std::vector< base::DataSourceBase::shared_ptr > const &args, DataSource< bool >::shared_ptr isblocking)
CorbaOperationCallerFactory(const std::string &method_name, corba::CService_ptr fact, PortableServer::POA_ptr the_poa)
Description of one Argument of a Command.
Based on the software pattern &#39;command&#39;, this interface allows execution of action objects...
static AssignableDataSource< T > * narrow(base::DataSourceBase *db)
TypeInfoRepository::shared_ptr Types()
Definition: Types.cpp:48
DataSource< bool >::shared_ptr misblocking
ActionInterface * clone() const
virtual base::DataSourceBase::shared_ptr produceSend(const std::vector< base::DataSourceBase::shared_ptr > &args, ExecutionEngine *caller) const
boost::intrusive_ptr< DataSource< T > > shared_ptr
Definition: DataSource.hpp:115
boost::intrusive_ptr< AssignableDataSource< T > > shared_ptr
Definition: DataSource.hpp:198
std::vector< base::DataSourceBase::shared_ptr > margs
static DataSource< T > * narrow(base::DataSourceBase *db)
TypeTransporter * getProtocol(int protocol_id) const
Definition: TypeInfo.cpp:150
std::vector< ArgumentDescription > CArgumentDescriptions
#define ORO_CORBA_PROTOCOL_ID
Definition: CorbaLib.hpp:45
base::DataSourceBase::shared_ptr buildValue() const
Definition: TypeInfo.hpp:230
boost::shared_ptr< COperation const > mdescription
virtual bool updateFromAny(const CORBA::Any *blob, base::DataSourceBase::shared_ptr target) const =0
boost::intrusive_ptr< DataSourceBase > shared_ptr
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:53
static Logger & log()
Definition: Logger.hpp:350
The Handle holds the information, and allows manipulation, of a connection between a internal::Signal...
Definition: Handle.hpp:66
virtual DataSource< SendStatus > * copy(std::map< const DataSourceBase *, DataSourceBase * > &alreadyCloned) const
virtual bool updateAny(base::DataSourceBase::shared_ptr source, CORBA::Any &any) const =0
static Logger::LogFunction endlog()
Definition: Logger.hpp:362
virtual const types::TypeInfo * getArgumentType(unsigned int i) const
virtual base::DataSourceBase::shared_ptr produce(const std::vector< base::DataSourceBase::shared_ptr > &args, ExecutionEngine *caller) const


rtt
Author(s): RTT Developers
autogenerated on Tue Jun 25 2019 19:33:23