1 // SALOME Session : implementation of Session.idl
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SALOME_Session_Server.cxx
25 // Author : Paul RASCLE, EDF
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"
40 #include <qapplication.h>
41 #include <qwaitcondition.h>
43 #include "Utils_SALOME_Exception.hxx"
44 #include "Utils_CorbaException.hxx"
45 #include "SALOME_Event.hxx"
47 #include <SALOMEconfig.h>
48 #include CORBA_SERVER_HEADER(SALOME_Session)
49 #include CORBA_SERVER_HEADER(SALOMEDS)
51 #include <utilities.h>
52 #include "Session_Session_i.hxx"
53 #include "Session_ServerLauncher.hxx"
55 #include "SUIT_Session.h"
56 #include "SUIT_Application.h"
57 #include "SUIT_MessageBox.h"
60 #include "SUIT_ExceptionHandler.h"
63 extern "C" int HandleSignals(QApplication *theQApplication);
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
71 //! CORBA server for SALOME Session
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.
77 * Main services offered by the servant are:
79 * - stop Session (must be idle)
83 QString salomeVersion()
85 QString path( ::getenv( "GUI_ROOT_DIR" ) );
86 if ( !path.isEmpty() )
87 path += QDir::separator();
88 path += QString( "bin/salome/VERSION" );
91 if ( !vf.open( IO_ReadOnly ) )
95 vf.readLine( line, 1024 );
101 while ( !line.isEmpty() && line.at( line.length() - 1 ) == QChar( '\n' ) )
102 line.remove( line.length() - 1, 1 );
105 int idx = line.findRev( ":" );
107 ver = line.mid( idx + 1 ).stripWhiteSpace();
112 PyObject *salome_shared_modules_module = NULL;
114 void MessageOutput( QtMsgType type, const char *msg )
118 MESSAGE( "Debug: " << msg );
121 MESSAGE( "Warning: " << msg );
124 MESSAGE( "Fatal: " << msg );
129 class SALOME_Session : public SUIT_Session
132 SALOME_Session() : SUIT_Session() {}
133 virtual ~SALOME_Session() {}
136 virtual SUIT_ResourceMgr* createResourceMgr( const QString& appName ) const
138 SUIT_ResourceMgr* resMgr = new SUIT_ResourceMgr( appName, QString( "%1Config" ) );
139 resMgr->setVersion( salomeVersion() );
140 resMgr->setCurrentFormat( "xml" );
141 resMgr->setOption( "translators", QString( "%P_msg_%L.qm|%P_icons.qm|%P_images.qm" ) );
146 class SALOME_QApplication : public QApplication
149 SALOME_QApplication( int& argc, char** argv ) : QApplication( argc, argv )
154 virtual bool notify( QObject* receiver, QEvent* e )
156 return myHandler ? myHandler->handle( receiver, e ) :
157 QApplication::notify( receiver, e );
159 SUIT_ExceptionHandler* handler() const { return myHandler; }
160 void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; }
163 SUIT_ExceptionHandler* myHandler;
166 int main(int argc, char **argv)
168 qInstallMsgHandler( MessageOutput );
172 strcpy( (char*)_argv_0, (char*)argv[0] );
175 // QApplication should be create before all other operations
176 // When uses QApplication::libraryPaths() (example, QFile::encodeName())
177 // qApp used for detection of the executable dir path.
178 SALOME_QApplication _qappl( argc, argv );
179 ASSERT( QObject::connect(&_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) ) );
180 QString path( ::getenv( "GUI_ROOT_DIR" ) );
181 if ( !path.isEmpty() )
182 path += QDir::separator();
183 path += QString( "bin/salome" );
184 _qappl.addLibraryPath( path );
185 _qappl.setStyle( "salome" );
188 Python initialisation : only once
192 char* _argv[] = {""};
193 KERNEL_PYTHON::init_python(_argc,_argv);
194 PyEval_RestoreThread(KERNEL_PYTHON::_gtstate);
195 if(!KERNEL_PYTHON::salome_shared_modules_module) // import only once
197 KERNEL_PYTHON::salome_shared_modules_module =
198 PyImport_ImportModule("salome_shared_modules");
200 if(!KERNEL_PYTHON::salome_shared_modules_module)
202 INFOS("salome_shared_modules_module == NULL");
206 PyEval_ReleaseThread(KERNEL_PYTHON::_gtstate);
210 // 1. create ORB, get RootPOA object, NamingService, etc.
211 ORB_INIT &init = *SINGLETON_<ORB_INIT>::Instance() ;
212 ASSERT(SINGLETON_<ORB_INIT>::IsAlreadyExisting()) ;
214 CORBA::ORB_var &orb = init( orbArgc , argv ) ;
215 SALOMETraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
219 SALOME_Event::GetSessionThread();
221 CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
222 PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
224 PortableServer::POAManager_var pman = poa->the_POAManager() ;
226 INFOS("pman->activate()");
228 SALOME_NamingService *_NS = new SALOME_NamingService(orb);
230 // CORBA Servant Launcher
232 QWaitCondition _ServerLaunch;
233 _GUIMutex.lock(); // to block Launch server thread until wait(mutex)
235 // 2. activate embedded CORBA servers: Registry, SALOMEDS, etc.
236 Session_ServerLauncher* myServerLauncher
237 = new Session_ServerLauncher(argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch);
238 myServerLauncher->start();
241 // Allow multiple activation/deactivation of GUI
243 MESSAGE("waiting wakeAll()");
244 _ServerLaunch.wait(&_GUIMutex); // to be reseased by Launch server thread when ready:
245 // atomic operation lock - unlock on mutex
246 // unlock mutex: serverThread runs, calls _ServerLaunch->wakeAll()
247 // this thread wakes up, and lock mutex
249 INFOS("Session activated, Launch IAPP...");
252 argv[0] = (char*)_argv_0;
253 SALOME_QApplication* _qappl = new SALOME_QApplication( qArgc, argv );
255 QStringList lst = _qappl->libraryPaths();
256 for ( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it )
257 printf( "=====> Library path: %s\n", (*it).latin1() );
259 _qappl->setStyle( "salome" );
261 ASSERT ( QObject::connect(_qappl, SIGNAL(lastWindowClosed()), _qappl, SLOT(quit()) ) );
264 INFOS("creation QApplication");
267 // 3.1 SUIT_Session creation
268 SUIT_Session* aGUISession = new SALOME_Session();
269 INFOS("creation SUIT_Application");
274 // T2.12 - catch exceptions thrown on attempts to modified a locked study
278 MESSAGE("run(): starting the main event loop");
280 // 3.2 load SalomeApp dynamic library
281 SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 );
284 _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application
285 // aGUISession contains SalomeApp_ExceptionHandler
286 result = _qappl.exec();
290 catch (SALOME::SALOME_Exception& e)
292 INFOS("run(): SALOME_Exception was caught!");
293 QApplication::restoreOverrideCursor();
294 SUIT_MessageBox::warn1 ( 0,
295 QObject::tr("WRN_WARNING"),
296 QObject::tr("SALOME_Exception was caught!"),
297 QObject::tr("BUT_OK") );
298 //QtCatchCorbaException(e);
300 catch(SALOMEDS::StudyBuilder::LockProtection&)
302 INFOS("run(): An attempt to modify a locked study has not been handled by QAD_Operation");
303 QApplication::restoreOverrideCursor();
304 SUIT_MessageBox::warn1 ( 0,
305 QObject::tr("WRN_WARNING"),
306 QObject::tr("WRN_STUDY_LOCKED"),
307 QObject::tr("BUT_OK") );
309 catch (const CORBA::Exception& e)
313 CORBA::TypeCode_var tc = tmp.type();
314 const char *p = tc->name();
315 INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
317 QApplication::restoreOverrideCursor();
318 SUIT_MessageBox::error1 ( 0,
319 QObject::tr("ERR_ERROR"),
320 QObject::tr("ERR_APP_EXCEPTION")
321 + QObject::tr(" CORBA exception ") + QObject::tr(p),
322 QObject::tr("BUT_OK") );
326 INFOS("run(): An exception has been caught");
327 QApplication::restoreOverrideCursor();
328 SUIT_MessageBox::error1 ( 0,
329 QObject::tr("ERR_ERROR"),
330 QObject::tr("ERR_APP_EXCEPTION")+ "\n" +QObject::tr(e.what()),
331 QObject::tr("BUT_OK") );
335 INFOS("run(): An exception has been caught");
336 QApplication::restoreOverrideCursor();
337 SUIT_MessageBox::error1 ( 0,
338 QObject::tr("ERR_ERROR"),
339 QObject::tr("ERR_APP_EXCEPTION"),
340 QObject::tr("BUT_OK") );
343 //} end of "outer" while( 1 )
345 // Prepare _GUIMutex for a new GUI activation
350 //myServerLauncher->KillAll();
352 catch (SALOME_Exception& e)
354 INFOS("run(): SALOME::SALOME_Exception is caught: "<<e.what());
356 catch (CORBA::SystemException& e)
358 INFOS("Caught CORBA::SystemException.");
360 catch (CORBA::Exception& e)
362 INFOS("Caught CORBA::Exception.");
365 CORBA::TypeCode_var tc = tmp.type();
366 const char *p = tc->name();
367 INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
371 INFOS("run(): An exception has been caught: " <<e.what());
375 INFOS("Caught unknown exception.");
377 delete myThreadTrace;