Salome HOME
Copyright update 2021
[modules/yacs.git] / src / yacsorb / yacsSrv.cxx
1 // Copyright (C) 2006-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <Python.h>
21 #include <yacs.hh>
22 #include "RuntimeSALOME.hxx"
23 #include "Proc.hxx"
24 #include "Exception.hxx"
25 #include "Executor.hxx"
26 #include "Dispatcher.hxx"
27 #include "parsers.hxx"
28
29 #include <iostream>
30 #include <sstream>
31 #include <set>
32
33 //#define _DEVDEBUG_
34 #include "YacsTrace.hxx"
35
36 using namespace std;
37
38 YACS::YACSLoader::YACSLoader* loader;
39 CORBA::ORB_ptr orb;
40 YACS_ORB::YACS_Gen_var myyacsref;
41
42 class MyDispatcher:public YACS::ENGINE::Dispatcher
43 {
44 public:
45   void dispatch(YACS::ENGINE::Node* object, const std::string& event)
46   {
47     std::cerr << "dispatch " << object->getNumId() << std::endl;
48     typedef std::set<YACS_ORB::Observer_ptr>::iterator jt;
49     std::pair<int,std::string> key(object->getNumId(),event);
50     for(jt iter=_observers[key].begin();iter!=_observers[key].end();iter++)
51       {
52         (*iter)->notifyObserver((CORBA::Long)object->getNumId(),event.c_str());
53       }
54   }
55
56   void addObserver(YACS_ORB::Observer_ptr observer,int numid, const std::string& event)
57   {
58     _observers[std::pair<int,std::string>(numid,event)].insert(YACS_ORB::Observer::_duplicate(observer));
59   //  printObservers();
60   }
61 protected:
62   std::map< std::pair<int,std::string> , std::set<YACS_ORB::Observer_ptr> > _observers;
63 };
64
65 class Yacs_i : public POA_YACS_ORB::YACS_Gen,
66                public PortableServer::RefCountServantBase
67 {
68 public:
69   inline Yacs_i() {}
70   virtual ~Yacs_i() {}
71   YACS_ORB::Proc_ptr Load(const char* xmlFile);
72   void Run(YACS_ORB::Proc_ptr p);
73   void addObserver(YACS_ORB::Observer_ptr observer, CORBA::Long numid,const char* event);
74 };
75
76 class Proc_i : public POA_YACS_ORB::Proc,
77                public PortableServer::RefCountServantBase
78 {
79 public:
80   inline Proc_i(YACS::ENGINE::Proc* p) {_proc=p;};
81   virtual ~Proc_i() {};
82   virtual void RunW();
83   CORBA::Long getState(CORBA::Long numid);
84   char * getXMLState(CORBA::Long numid);
85   void getIds(YACS_ORB::longArray_out numids,YACS_ORB::stringArray_out names);
86 protected:
87   YACS::ENGINE::Executor _executor;
88   YACS::ENGINE::Proc* _proc;
89 };
90
91 void Proc_i::RunW()
92 {
93   _executor.RunW(_proc,0);
94 }
95
96 CORBA::Long Proc_i::getState(CORBA::Long numid)
97 {
98   if(YACS::ENGINE::Node::idMap.count(numid) == 0)
99     {
100       std::cerr << "Unknown node id " << numid << std::endl;
101       return (CORBA::Long)-1;
102     }
103   YACS::ENGINE::Node* node= YACS::ENGINE::Node::idMap[numid];
104   CORBA::Long state=node->getEffectiveState();
105   return state;
106 }
107
108 char * Proc_i::getXMLState(CORBA::Long numid)
109 {
110   if(YACS::ENGINE::Node::idMap.count(numid) == 0)
111     {
112       std::cerr << "Unknown node id " << numid << std::endl;
113       return "<state>unknown</state>";
114     }
115   YACS::ENGINE::Node* node= YACS::ENGINE::Node::idMap[numid];
116   std::stringstream msg;
117   msg << "<state>" << node->getEffectiveState() << "</state>";
118   msg << "<name>" << node->getQualifiedName() << "</name>";
119   msg << "<id>" << numid << "</id>";
120   return CORBA::string_dup(msg.str().c_str());
121 }
122
123 void Proc_i::getIds(YACS_ORB::longArray_out numids,YACS_ORB::stringArray_out names)
124 {
125   std::list<YACS::ENGINE::Node *> nodes=_proc->getAllRecursiveNodes();
126   int len=nodes.size();
127   names=new YACS_ORB::stringArray;
128   numids=new YACS_ORB::longArray;
129   names->length(len);
130   numids->length(len);
131   int i=0;
132   for(list<YACS::ENGINE::Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++,i++)
133     {
134       (*names)[i]=CORBA::string_dup((*iter)->getQualifiedName().c_str());
135       (*numids)[i]=(*iter)->getNumId();
136     }
137 }
138
139 YACS_ORB::Proc_ptr Yacs_i::Load(const char* xmlFile)
140 {
141   YACS::ENGINE::Proc* proc=loader->load(xmlFile);
142   Proc_i* p=new Proc_i(proc);
143   YACS_ORB::Proc_ptr pp = p->_this();
144   return pp;
145 }
146
147 void Yacs_i::addObserver(YACS_ORB::Observer_ptr observer, CORBA::Long numid,const char* event)
148 {
149   ((MyDispatcher*)YACS::ENGINE::Dispatcher::getDispatcher())->addObserver(observer,numid,event);
150 }
151
152 void Yacs_i::Run(YACS_ORB::Proc_ptr p)
153 {
154   Proc_i *servant=dynamic_cast<Proc_i *> (PortableServer::POA::_the_root_poa()->reference_to_servant(p));
155   servant->RunW();
156 }
157
158 static CORBA::Boolean bindObjectToName(CORBA::ORB_ptr, CORBA::Object_ptr,const char*);
159 static ostream& operator<<(ostream& os, const CORBA::Exception& e);
160
161 int main(int argc, char** argv)
162 {
163   YACS::ENGINE::RuntimeSALOME::setRuntime();
164   loader= new YACS::YACSLoader::YACSLoader();
165   MyDispatcher* disp=new MyDispatcher();
166   YACS::ENGINE::Dispatcher::setDispatcher(disp);
167
168   try 
169   {
170     orb = CORBA::ORB_init(argc, argv);
171
172     {
173       CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
174       PortableServer::POA_var root_poa = PortableServer::POA::_narrow(obj);
175       // POA manager
176       PortableServer::POAManager_var poa_man = root_poa->the_POAManager();
177       poa_man->activate();
178
179       // Create and activate servant
180       Yacs_i* myyacs = new Yacs_i();
181       // Obtain a reference to the object, and print it out as a
182       // stringified IOR.
183       obj = myyacs->_this();
184       CORBA::String_var sior(orb->object_to_string(obj));
185       DEBTRACE("'" << (char*)sior << "'");
186       myyacsref = YACS_ORB::YACS_Gen::_narrow(obj);
187
188       if( !bindObjectToName(orb, myyacsref,"Yacs") ) return 1;
189
190       // Decrement the reference count of the object implementation, so
191       // that it will be properly cleaned up when the POA has determined
192       // that it is no longer needed.
193       myyacs->_remove_ref();
194     }
195     orb->run();
196   }
197   catch(CORBA::SystemException&) {
198     DEBTRACE("Caught CORBA::SystemException.");
199   }
200   catch(CORBA::Exception& ex) {
201     DEBTRACE("Caught CORBA::Exception." << ex);
202   }
203   catch(omniORB::fatalException& fe) {
204     DEBTRACE("Caught omniORB::fatalException:");
205     DEBTRACE("  file: " << fe.file());
206     DEBTRACE("  line: " << fe.line());
207     DEBTRACE("  mesg: " << fe.errmsg());
208   }
209   catch(...) {
210     DEBTRACE("Caught unknown exception." );
211   }
212
213   return 0;
214 }
215
216
217 //////////////////////////////////////////////////////////////////////
218
219 static CORBA::Boolean
220 bindObjectToName(CORBA::ORB_ptr orb, CORBA::Object_ptr objref,const char *name)
221 {
222   CosNaming::NamingContext_var rootContext;
223
224   try {
225     // Obtain a reference to the root context of the Name service:
226     CORBA::Object_var obj;
227     obj = orb->resolve_initial_references("NameService");
228
229     // Narrow the reference returned.
230     rootContext = CosNaming::NamingContext::_narrow(obj);
231     if( CORBA::is_nil(rootContext) ) {
232       DEBTRACE("Failed to narrow the root naming context.");
233       return 0;
234     }
235   }
236   catch(CORBA::ORB::InvalidName& ex) {
237     // This should not happen!
238     DEBTRACE("Service required is invalid [does not exist]." );
239     return 0;
240   }
241
242   try {
243     // Bind a context called "test" to the root context:
244
245     CosNaming::Name contextName;
246     contextName.length(1);
247     contextName[0].id   = (const char*) "test";       // string copied
248     contextName[0].kind = (const char*) "my_context"; // string copied
249     // Note on kind: The kind field is used to indicate the type
250     // of the object. This is to avoid conventions such as that used
251     // by files (name.type -- e.g. test.ps = postscript etc.)
252
253     CosNaming::NamingContext_var testContext;
254     try {
255       // Bind the context to root.
256       testContext = rootContext->bind_new_context(contextName);
257     }
258     catch(CosNaming::NamingContext::AlreadyBound& ex) {
259       // If the context already exists, this exception will be raised.
260       // In this case, just resolve the name and assign testContext
261       // to the object returned:
262       CORBA::Object_var obj;
263       obj = rootContext->resolve(contextName);
264       testContext = CosNaming::NamingContext::_narrow(obj);
265       if( CORBA::is_nil(testContext) ) {
266         DEBTRACE("Failed to narrow naming context.");
267         return 0;
268       }
269     }
270
271     // Bind objref with name name to the testContext:
272     CosNaming::Name objectName;
273     objectName.length(1);
274     objectName[0].id   = name;   // string copied
275     objectName[0].kind = (const char*) "Object"; // string copied
276
277     try {
278       testContext->bind(objectName, objref);
279     }
280     catch(CosNaming::NamingContext::AlreadyBound& ex) {
281       testContext->rebind(objectName, objref);
282     }
283   }
284   catch(CORBA::COMM_FAILURE& ex) {
285     DEBTRACE("Caught system exception COMM_FAILURE -- unable to contact the "
286              << "naming service.");
287     return 0;
288   }
289   catch(CORBA::SystemException&) {
290     DEBTRACE("Caught a CORBA::SystemException while using the naming service.");
291     return 0;
292   }
293
294   return 1;
295 }
296
297 static ostream& operator<<(ostream& os, const CORBA::Exception& e)
298 {
299   CORBA::Any tmp;
300   tmp<<= e;
301   CORBA::TypeCode_var tc = tmp.type();
302   const char *p = tc->name();
303   if ( *p != '\0' ) {
304     os<<p;
305   }
306   else  {
307     os << tc->id();
308   }
309   return os;
310 }