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" );
145 class SALOME_QApplication : public QApplication
148 SALOME_QApplication( int& argc, char** argv ) : QApplication( argc, argv )
153 virtual bool notify( QObject* receiver, QEvent* e )
155 return myHandler ? myHandler->handle( receiver, e ) :
156 QApplication::notify( receiver, e );
158 SUIT_ExceptionHandler* handler() const { return myHandler; }
159 void setHandler( SUIT_ExceptionHandler* h ) { myHandler = h; }
162 SUIT_ExceptionHandler* myHandler;
165 int main(int argc, char **argv)
167 qInstallMsgHandler( MessageOutput );
171 strcpy( (char*)_argv_0, (char*)argv[0] );
174 // QApplication should be create before all other operations
175 // When uses QApplication::libraryPaths() (example, QFile::encodeName())
176 // qApp used for detection of the executable dir path.
177 SALOME_QApplication _qappl( argc, argv );
178 ASSERT( QObject::connect(&_qappl, SIGNAL( lastWindowClosed() ), &_qappl, SLOT( quit() ) ) );
179 QString path( ::getenv( "GUI_ROOT_DIR" ) );
180 if ( !path.isEmpty() )
181 path += QDir::separator();
182 path += QString( "bin/salome" );
183 _qappl.addLibraryPath( path );
184 _qappl.setStyle( "salome" );
187 Python initialisation : only once
191 char* _argv[] = {""};
192 KERNEL_PYTHON::init_python(_argc,_argv);
193 PyEval_RestoreThread(KERNEL_PYTHON::_gtstate);
194 if(!KERNEL_PYTHON::salome_shared_modules_module) // import only once
196 KERNEL_PYTHON::salome_shared_modules_module =
197 PyImport_ImportModule("salome_shared_modules");
199 if(!KERNEL_PYTHON::salome_shared_modules_module)
201 INFOS("salome_shared_modules_module == NULL");
205 PyEval_ReleaseThread(KERNEL_PYTHON::_gtstate);
209 // 1. create ORB, get RootPOA object, NamingService, etc.
210 ORB_INIT &init = *SINGLETON_<ORB_INIT>::Instance() ;
211 ASSERT(SINGLETON_<ORB_INIT>::IsAlreadyExisting()) ;
213 CORBA::ORB_var &orb = init( orbArgc , argv ) ;
214 SALOMETraceCollector *myThreadTrace = SALOMETraceCollector::instance(orb);
218 SALOME_Event::GetSessionThread();
220 CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
221 PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
223 PortableServer::POAManager_var pman = poa->the_POAManager() ;
225 INFOS("pman->activate()");
227 SALOME_NamingService *_NS = new SALOME_NamingService(orb);
229 // CORBA Servant Launcher
231 QWaitCondition _ServerLaunch;
232 _GUIMutex.lock(); // to block Launch server thread until wait(mutex)
234 // 2. activate embedded CORBA servers: Registry, SALOMEDS, etc.
235 Session_ServerLauncher* myServerLauncher
236 = new Session_ServerLauncher(argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch);
237 myServerLauncher->start();
240 // Allow multiple activation/deactivation of GUI
242 MESSAGE("waiting wakeAll()");
243 _ServerLaunch.wait(&_GUIMutex); // to be reseased by Launch server thread when ready:
244 // atomic operation lock - unlock on mutex
245 // unlock mutex: serverThread runs, calls _ServerLaunch->wakeAll()
246 // this thread wakes up, and lock mutex
248 INFOS("Session activated, Launch IAPP...");
251 argv[0] = (char*)_argv_0;
252 SALOME_QApplication* _qappl = new SALOME_QApplication( qArgc, argv );
254 QStringList lst = _qappl->libraryPaths();
255 for ( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it )
256 printf( "=====> Library path: %s\n", (*it).latin1() );
258 _qappl->setStyle( "salome" );
260 ASSERT ( QObject::connect(_qappl, SIGNAL(lastWindowClosed()), _qappl, SLOT(quit()) ) );
263 INFOS("creation QApplication");
266 // 3.1 SUIT_Session creation
267 SUIT_Session* aGUISession = new SALOME_Session();
268 INFOS("creation SUIT_Application");
273 // T2.12 - catch exceptions thrown on attempts to modified a locked study
277 MESSAGE("run(): starting the main event loop");
279 // 3.2 load SalomeApp dynamic library
280 SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 );
283 _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application
284 // aGUISession contains SalomeApp_ExceptionHandler
285 result = _qappl.exec();
289 catch (SALOME::SALOME_Exception& e)
291 INFOS("run(): SALOME_Exception was caught!");
292 QApplication::restoreOverrideCursor();
293 SUIT_MessageBox::warn1 ( 0,
294 QObject::tr("WRN_WARNING"),
295 QObject::tr("SALOME_Exception was caught!"),
296 QObject::tr("BUT_OK") );
297 //QtCatchCorbaException(e);
299 catch(SALOMEDS::StudyBuilder::LockProtection&)
301 INFOS("run(): An attempt to modify a locked study has not been handled by QAD_Operation");
302 QApplication::restoreOverrideCursor();
303 SUIT_MessageBox::warn1 ( 0,
304 QObject::tr("WRN_WARNING"),
305 QObject::tr("WRN_STUDY_LOCKED"),
306 QObject::tr("BUT_OK") );
308 catch (const CORBA::Exception& e)
312 CORBA::TypeCode_var tc = tmp.type();
313 const char *p = tc->name();
314 INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
316 QApplication::restoreOverrideCursor();
317 SUIT_MessageBox::error1 ( 0,
318 QObject::tr("ERR_ERROR"),
319 QObject::tr("ERR_APP_EXCEPTION")
320 + QObject::tr(" CORBA exception ") + QObject::tr(p),
321 QObject::tr("BUT_OK") );
325 INFOS("run(): An exception has been caught");
326 QApplication::restoreOverrideCursor();
327 SUIT_MessageBox::error1 ( 0,
328 QObject::tr("ERR_ERROR"),
329 QObject::tr("ERR_APP_EXCEPTION")+ "\n" +QObject::tr(e.what()),
330 QObject::tr("BUT_OK") );
334 INFOS("run(): An exception has been caught");
335 QApplication::restoreOverrideCursor();
336 SUIT_MessageBox::error1 ( 0,
337 QObject::tr("ERR_ERROR"),
338 QObject::tr("ERR_APP_EXCEPTION"),
339 QObject::tr("BUT_OK") );
342 //} end of "outer" while( 1 )
344 // Prepare _GUIMutex for a new GUI activation
349 //myServerLauncher->KillAll();
351 catch (SALOME_Exception& e)
353 INFOS("run(): SALOME::SALOME_Exception is caught: "<<e.what());
355 catch (CORBA::SystemException& e)
357 INFOS("Caught CORBA::SystemException.");
359 catch (CORBA::Exception& e)
361 INFOS("Caught CORBA::Exception.");
364 CORBA::TypeCode_var tc = tmp.type();
365 const char *p = tc->name();
366 INFOS ("run(): CORBA exception of the kind : "<<p<< " is caught");
370 INFOS("run(): An exception has been caught: " <<e.what());
374 INFOS("Caught unknown exception.");
376 delete myThreadTrace;