Salome HOME
e3505a4feb1f8cf6168762b69cf6f5924335e276
[modules/gui.git] / src / Session / SALOME_Session_Server.cxx
1 //  SALOME Session : implementation of Session.idl
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOME_Session_Server.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SALOME
27 //  $Header$
28
29 #include <Container_init_python.hxx>
30 #include "Utils_ORB_INIT.hxx"
31 #include "Utils_SINGLETON.hxx"
32 #include "SALOME_NamingService.hxx"
33 #include "SALOMETraceCollector.hxx"
34
35 #include <iostream>
36 #include <unistd.h>
37
38 #include <qthread.h> 
39 #include <qapplication.h>
40 #include <qlabel.h>
41 #include <qwaitcondition.h>
42
43 #include "Utils_SALOME_Exception.hxx"
44 #include "Utils_CorbaException.hxx"
45 #include "SALOME_Event.hxx"
46
47 #include <SALOMEconfig.h>
48 #include CORBA_SERVER_HEADER(SALOME_Session)
49 #include CORBA_SERVER_HEADER(SALOMEDS)
50
51 #include <utilities.h>
52 #include "Session_Session_i.hxx"
53 #include "Session_ServerLauncher.hxx"
54
55 #include "SUIT_Session.h"
56 #include "SUIT_Application.h"
57 #include "SUIT_MessageBox.h"
58
59
60 #include "SalomeApp_ExceptionHandler.h"
61 using namespace std;
62
63 extern "C" int HandleSignals(QApplication *theQApplication);
64
65 /*! - read arguments, define list of server to launch with their arguments.
66  *  - wait for naming service
67  *  - create and run a thread for launch of all servers
68  *  
69  */
70
71 //! CORBA server for SALOME Session
72 /*!
73  *  SALOME_Session Server launches a SALOME session servant.
74  *  The servant registers to the Naming Service.
75  *  See SALOME_Session.idl for interface specification.
76  *
77  *  Main services offered by the servant are:
78  *   - launch GUI
79  *   - stop Session (must be idle)
80  *   - get session state
81  */
82
83 #ifdef _DEBUG_
84 static int MYDEBUG = 0;
85 #else
86 static int MYDEBUG = 0;
87 #endif
88
89 PyObject *salome_shared_modules_module = NULL;
90 void MessageOutput( QtMsgType type, const char *msg )
91 {
92   switch ( type ) {
93   case QtDebugMsg:
94     MESSAGE( "Debug: " << msg );
95     break;
96   case QtWarningMsg:
97     MESSAGE( "Warning: " << msg );
98     break;
99   case QtFatalMsg:
100     MESSAGE( "Fatal: " << msg );
101     break;
102   }
103 }
104
105 class SALOME_Session : public SUIT_Session
106 {
107 public:
108   SALOME_Session() : SUIT_Session() {}
109   virtual ~SALOME_Session() {}
110
111 protected:
112   virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const
113   {
114     SUIT_ResourceMgr* resMgr = new SUIT_ResourceMgr( appName, QString( "%1Config" ) );
115     resMgr->setCurrentFormat( "xml" );
116     return resMgr;
117   }
118 };
119
120 class SALOME_QApplication : public QApplication 
121 {
122 public:
123   SALOME_QApplication( int& argc, char** argv ) : QApplication( argc, argv ) 
124   {
125     myHandler = 0;
126   }
127   
128   virtual bool notify( QObject* receiver, QEvent* e ) 
129   {
130     return myHandler ? myHandler->handle( receiver, e ) :
131                        QApplication::notify( receiver, e );
132   }
133   SUIT_ExceptionHandler*  handler() const { return myHandler; }
134   void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; }
135
136 private:
137   SUIT_ExceptionHandler*  myHandler;
138 };
139
140
141
142
143 int main(int argc, char **argv)
144 {
145   qInstallMsgHandler( MessageOutput );
146
147   /*
148    * Python initialisation : only once
149    */
150   int _argc = 1;
151   char* _argv[] = {""};
152   KERNEL_PYTHON::init_python(_argc,_argv);
153   PyEval_RestoreThread(KERNEL_PYTHON::_gtstate);
154   if(!KERNEL_PYTHON::salome_shared_modules_module) // import only once
155     {
156       KERNEL_PYTHON::salome_shared_modules_module =
157         PyImport_ImportModule("salome_shared_modules");
158     }
159   if(!KERNEL_PYTHON::salome_shared_modules_module)
160     {
161       INFOS("salome_shared_modules_module == NULL");
162       PyErr_Print();
163       PyErr_Clear();
164     }
165   PyEval_ReleaseThread(KERNEL_PYTHON::_gtstate);
166
167   int result = -1;
168
169   // 1. create ORB, get RootPOA object, NamingService, etc.
170   ORB_INIT &init = *SINGLETON_<ORB_INIT>::Instance() ;
171   ASSERT(SINGLETON_<ORB_INIT>::IsAlreadyExisting()) ;
172   int orbArgc = 1;
173   CORBA::ORB_var &orb = init( orbArgc , argv ) ;
174   SALOMETraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
175
176   try
177     {
178       SALOME_Event::GetSessionThread();
179
180       CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
181       PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
182
183       PortableServer::POAManager_var pman = poa->the_POAManager() ;
184       pman->activate() ;
185       INFOS("pman->activate()");
186
187       SALOME_NamingService *_NS = new SALOME_NamingService(orb);
188
189       // CORBA Servant Launcher
190       QMutex _GUIMutex ;
191       QWaitCondition _ServerLaunch;
192       _GUIMutex.lock();     // to block Launch server thread until wait(mutex)
193
194       // 2. activate embedded CORBA servers: Registry, SALOMEDS, etc.
195       Session_ServerLauncher* myServerLauncher
196         = new Session_ServerLauncher(argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch);
197       myServerLauncher->start();
198
199       // 3. GUI activation
200       // Allow multiple activation/deactivation of GUI
201       //while ( 1 ) {
202         MESSAGE("waiting wakeAll()");
203         _ServerLaunch.wait(&_GUIMutex); // to be reseased by Launch server thread when ready:
204         // atomic operation lock - unlock on mutex
205         // unlock mutex: serverThread runs, calls  _ServerLaunch->wakeAll()
206         // this thread wakes up, and lock mutex
207
208         INFOS("Session activated, Launch IAPP...");
209
210         int qArgc = 1;
211         SALOME_QApplication* _qappl = new SALOME_QApplication( qArgc, argv );
212         
213         INFOS("creation QApplication");
214         _GUIMutex.unlock();
215
216         ASSERT ( QObject::connect(_qappl, SIGNAL(lastWindowClosed()), _qappl, SLOT(quit()) ) );
217
218         // 3.1 SUIT_Session creation    
219         SUIT_Session* aGUISession = new SALOME_Session();
220         INFOS("creation SUIT_Application");
221
222         SCRUTE(_NS);
223
224         // 3.3 run GUI loop
225         // T2.12 - catch exceptions thrown on attempts to modified a locked study
226         while (1) {
227           try 
228           {
229             MESSAGE("run(): starting the main event loop");
230
231 // 3.2 load SalomeApp dynamic library
232 #ifdef WNT
233             SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp.dll", 0, 0 );
234 #else
235             SUIT_Application* aGUIApp = aGUISession->startApplication( "libSalomeApp.so", 0, 0 );
236 #endif
237             if ( aGUIApp ) 
238             {
239               _qappl->setHandler( aGUISession->handler() ); // after loading SalomeApp application
240                                                             // aGUISession contains SalomeApp_ExceptionHandler
241               result = _qappl->exec();
242             }
243             break;
244           }
245           catch (SALOME::SALOME_Exception& e)
246           {
247             INFOS("run(): SALOME_Exception was caught!");
248             QApplication::restoreOverrideCursor();
249             SUIT_MessageBox::warn1 ( 0,
250                                     QObject::tr("WRN_WARNING"), 
251                                     QObject::tr("SALOME_Exception was caught!"),
252                                     QObject::tr("BUT_OK") );
253             //QtCatchCorbaException(e);
254           }
255           catch(SALOMEDS::StudyBuilder::LockProtection&)
256           {
257             INFOS("run(): An attempt to modify a locked study has not been handled by QAD_Operation");
258             QApplication::restoreOverrideCursor();
259             SUIT_MessageBox::warn1 ( 0,
260                                     QObject::tr("WRN_WARNING"), 
261                                     QObject::tr("WRN_STUDY_LOCKED"),
262                                     QObject::tr("BUT_OK") );
263           }
264           catch (const CORBA::Exception& e)
265           {
266             CORBA::Any tmp;
267             tmp<<= e;
268             CORBA::TypeCode_var tc = tmp.type();
269             const char *p = tc->name();
270             INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
271
272             QApplication::restoreOverrideCursor();
273             SUIT_MessageBox::error1 ( 0,
274                                      QObject::tr("ERR_ERROR"), 
275                                      QObject::tr("ERR_APP_EXCEPTION")
276                                      + QObject::tr(" CORBA exception ") + QObject::tr(p),
277                                      QObject::tr("BUT_OK") );
278           }
279           catch(exception& e)
280           {
281             INFOS("run(): An exception has been caught");
282             QApplication::restoreOverrideCursor();
283             SUIT_MessageBox::error1 ( 0,
284                                      QObject::tr("ERR_ERROR"), 
285                                      QObject::tr("ERR_APP_EXCEPTION")+ "\n" +QObject::tr(e.what()),
286                                      QObject::tr("BUT_OK") );
287           }
288           catch(...)
289           {
290             INFOS("run(): An exception has been caught");
291             QApplication::restoreOverrideCursor();
292             SUIT_MessageBox::error1 ( 0,
293                                      QObject::tr("ERR_ERROR"), 
294                                      QObject::tr("ERR_APP_EXCEPTION"),
295                                      QObject::tr("BUT_OK") );
296           }
297         }
298 //}  end of "outer" while( 1 )
299
300       // Prepare _GUIMutex for a new GUI activation
301       //_GUIMutex.lock(); 
302         //      }
303
304       //orb->shutdown(0);
305       //myServerLauncher->KillAll();
306     }
307   catch (SALOME_Exception& e)
308     {
309       INFOS("run(): SALOME::SALOME_Exception is caught: "<<e.what());
310     }
311   catch (CORBA::SystemException& e)
312     {
313       INFOS("Caught CORBA::SystemException.");
314     }
315   catch (CORBA::Exception& e)
316     {
317       INFOS("Caught CORBA::Exception.");
318       CORBA::Any tmp;
319       tmp<<= e;
320       CORBA::TypeCode_var tc = tmp.type();
321       const char *p = tc->name();
322       INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
323     }
324   catch(exception& e)
325     {
326       INFOS("run(): An exception has been caught: " <<e.what());
327     }
328   catch (...)
329     {
330       INFOS("Caught unknown exception.");
331     }
332   delete myThreadTrace;
333   return result ;
334 }