Salome HOME
ADD a end user module (services.py) to help the manipulation of SALOME KERNEL service...
[modules/kernel.git] / src / NamingService / SALOME_NamingService.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SALOME NamingService : wrapping NamingService services
24 //  File   : SALOME_NamingService.cxx
25 //  Author : Estelle Deville
26 //  Module : SALOME
27 //  $Header$
28 //
29 #include "SALOME_NamingService.hxx"
30 #include "ServiceUnreachable.hxx"
31
32 #include "utilities.h"
33
34 #include <iostream>
35 #include <cstring>
36 #include <string>
37 #include <cstdio>
38
39 #ifdef WNT
40 #define strdup _strdup
41 #endif
42
43 /*! \class SALOME_NamingService
44     \brief A class to manage the SALOME naming service
45
46 */
47
48 // ============================================================================
49 /*! \brief Default Constructor without ORB reference.
50  *
51  *  After Default Constructor, one needs to initialize ORB.
52  *  \sa init_orb(CORBA::ORB_ptr orb), SALOME_NamingService(CORBA::ORB_ptr orb)
53  */ 
54 // ============================================================================
55
56 SALOME_NamingService::SALOME_NamingService()
57 {
58   MESSAGE("SALOME_NamingService default constructor");
59   _orb = CORBA::ORB::_nil();
60   _root_context = CosNaming::NamingContext::_nil();
61 }
62
63 // ============================================================================
64 /*! \brief Standard Constructor, with ORB reference. 
65  * 
66  * Initializes the naming service root context
67  * \param orb CORBA::ORB_ptr arguments
68  */ 
69 // ============================================================================
70
71 SALOME_NamingService::SALOME_NamingService(CORBA::ORB_ptr orb)
72 {
73   MESSAGE("SALOME_NamingService creation");
74   _orb = CORBA::ORB::_duplicate(orb);
75   _initialize_root_context();
76 }
77
78 // ============================================================================
79 /*! \brief Standard destructor.
80  *
81  *  The standard destructor does nothing special.
82  */ 
83 // ============================================================================
84
85 SALOME_NamingService::~SALOME_NamingService()
86 {
87   // Problem MESSAGE with singleton: late destruction,
88   // after trace system destruction ?
89   //MESSAGE("SALOME_NamingService destruction");
90 }
91
92 // ============================================================================
93 /*! \brief initializes ORB reference and naming service root context.
94  * 
95  *  Initializes ORB reference and naming service root context.
96  *  For use after default constructor.
97  *  If param orb is null, the orb is initialized
98  *  \param orb CORBA::ORB_ptr arguments
99  */ 
100 // ============================================================================
101
102 void SALOME_NamingService::init_orb(CORBA::ORB_ptr orb)
103 {
104   MESSAGE("SALOME_NamingService initialisation");
105
106   Utils_Locker lock (&_myMutex);
107   if(orb)
108     _orb = CORBA::ORB::_duplicate(orb);
109   else
110     {
111       int argc=0;
112       _orb = CORBA::ORB_init(argc, 0); // Here we make the assumption that the orb has already been initialized
113     }
114
115   _initialize_root_context();
116 }
117
118 // ============================================================================
119 /*! \brief Registers a CORBA object reference under a path.
120  *
121  * Registers a CORBA object reference under a path. If the path ends with '/',
122  * only a directory is created.
123  * If the NamingService is out, the exception ServiceUnreachable is thrown.
124  * \param ObjRef CORBA object reference to associate to the path. To create
125  *               only a directory, give nil pointer.
126  * \param Path   A relative or absolute pathname to store the object reference.
127  *               If the pathname begins with a '/', pathname is taken
128  *               as an absolute pathname. Else, pathname is taken as a relative
129  *               path, to current context. Prefer absolute pathname, relative
130  *               pathname are not safe, when SALOME_NamingService object is
131  *               shared or use in multithreaded context. 
132  *               If the path ends with '/', only a directory is created.
133  * \sa           Change_Directory(const char* Path),
134  *               Create_Directory(const char* Path)
135  *               CORBA::Object_ptr Resolve(const char* Path)
136  */ 
137 // ============================================================================
138
139 void SALOME_NamingService::Register(CORBA::Object_ptr ObjRef,
140                                     const char* Path)
141   throw(ServiceUnreachable)
142 {
143   MESSAGE("BEGIN OF Register: " << Path);
144
145   Utils_Locker lock (&_myMutex);
146
147   // --- _current_context is replaced to the _root_context
148   //     if the Path begins whith '/'
149
150   if (Path[0] == '/'){
151     _current_context = _root_context;
152   }
153
154   // --- the resolution of the directory path has to be done
155   //      to place the current_context to the correct node
156
157   CosNaming::Name context_name;
158   std::vector<std::string> splitPath;
159   int dimension_resultat = _createContextNameDir(Path,
160                                                  context_name,
161                                                  splitPath,
162                                                  true);
163
164   CORBA::Boolean not_exist = false;
165
166   if (dimension_resultat > 0){
167     // A directory is treated (not only an object name)
168     // test if the directory where ObjRef should be recorded already exists
169     // If not, create the new context
170     
171     try{
172       CORBA::Object_var obj = _current_context->resolve(context_name);
173       _current_context = CosNaming::NamingContext::_narrow(obj);
174     }
175
176     catch (CosNaming::NamingContext::NotFound &){
177       // --- failed to resolve, therefore assume cold start
178       not_exist = true;
179     }
180
181     catch (CosNaming::NamingContext::InvalidName &){
182       INFOS("Register() : CosNaming::NamingContext::InvalidName");
183     }
184
185     catch (CosNaming::NamingContext::CannotProceed &){
186       INFOS("Register() : CosNaming::NamingContext::CannotProceed");
187     }
188
189     catch (CORBA::SystemException&){
190       INFOS("Register() : CORBA::SystemException: "
191             << "unable to contact the naming service");
192       throw ServiceUnreachable();
193     }
194
195     if (not_exist){
196       try{
197         context_name.length(1);
198         for (int i = 0 ; i < dimension_resultat ;i++){
199           context_name[0].id = CORBA::string_dup(splitPath[i].c_str());
200           context_name[0].kind = CORBA::string_dup("dir");
201           // SCRUTE(_context_name[0].id);
202           // --- check if the path is created
203           try{
204             // --- if the context is already created, nothing to do
205             CORBA::Object_var obj = _current_context->resolve(context_name);
206             _current_context = CosNaming::NamingContext::_narrow(obj);
207           }
208
209           catch (CosNaming::NamingContext::NotFound &){
210             try{
211               // --- the context must be created
212               CosNaming::NamingContext_var temp_context =
213                 _current_context->bind_new_context(context_name);
214               _current_context = temp_context;
215             }
216             catch (CosNaming::NamingContext::AlreadyBound&){
217               CORBA::Object_var obj = _current_context->resolve(context_name);
218               _current_context = CosNaming::NamingContext::_narrow(obj);
219             }
220           }
221         }
222       }
223
224       catch (CosNaming::NamingContext::AlreadyBound&){
225         INFOS("Register() : CosNaming::NamingContext::AlreadyBound");
226       }
227
228       catch (CosNaming::NamingContext::NotFound& ex){
229         CosNaming::Name n = ex.rest_of_name;
230
231         if (ex.why == CosNaming::NamingContext::missing_node)
232           INFOS("Register() : " << (char *) n[0].id
233                 << " (" << (char *) n[0].kind << ") not found");
234
235         if (ex.why == CosNaming::NamingContext::not_context)
236           INFOS("Register() : " << (char *) n[0].id
237                 << " (" << (char *) n[0].kind
238                 << ") is not a context");
239
240         if (ex.why == CosNaming::NamingContext::not_object)
241           INFOS("Register() : " << (char *) n[0].id
242                 << " (" << (char *) n[0].kind
243                 << ") is not an object");
244       }
245
246       catch (CosNaming::NamingContext::CannotProceed&){
247         INFOS("Register(): CosNaming::NamingContext::CannotProceed");
248       }
249
250       catch (CosNaming::NamingContext::InvalidName&){
251         INFOS("Register(): CosNaming::NamingContext::InvalidName");
252       }
253
254       catch (CORBA::SystemException&){
255         INFOS("Register():CORBA::SystemException: "
256               << "unable to contact the naming service");
257         throw ServiceUnreachable();
258       }
259     }
260   }
261
262   // --- The current directory is now the directory where the object should
263   //     be recorded
264
265   int sizePath = splitPath.size();
266   if (sizePath > dimension_resultat){
267     ASSERT(sizePath == dimension_resultat+1);
268     context_name.length(1);
269
270     try{
271       // --- the last element is an object and not a directory
272
273       context_name[0].id = CORBA::string_dup(splitPath[dimension_resultat].c_str());
274       context_name[0].kind = CORBA::string_dup("object");
275       //SCRUTE(context_name[0].id);
276
277       _current_context->bind(context_name, ObjRef);
278     }
279
280     catch (CosNaming::NamingContext::NotFound& ex){
281       CosNaming::Name n = ex.rest_of_name;
282
283       if (ex.why == CosNaming::NamingContext::missing_node)
284         INFOS("Register() : " << (char *) n[0].id
285               << " (" << (char *) n[0].kind << ") not found");
286
287       if (ex.why == CosNaming::NamingContext::not_context)
288         INFOS("Register() : " << (char *) n[0].id
289               << " (" << (char *) n[0].kind
290               << ") is not a context");
291
292       if (ex.why == CosNaming::NamingContext::not_object)
293         INFOS("Register() : " << (char *) n[0].id
294               << " (" << (char *) n[0].kind
295               << ") is not an object");
296     }
297
298     catch (CosNaming::NamingContext::CannotProceed&){
299       INFOS("Register(): CosNaming::NamingContext::CannotProceed");
300     }
301
302     catch (CosNaming::NamingContext::InvalidName&){
303       INFOS("Register(): CosNaming::NamingContext::InvalidName");
304     }
305
306     catch (CosNaming::NamingContext::AlreadyBound&){
307       INFOS("Register(): CosNaming::NamingContext::AlreadyBound, "
308             << "object will be rebind");
309       _current_context->rebind(context_name, ObjRef);
310     }
311
312     catch (CORBA::SystemException&){
313       INFOS("!!!Register(): CORBA::SystemException: "
314             << "unable to contact the naming service");
315       throw ServiceUnreachable();
316     }
317   }
318 }
319
320 // ============================================================================
321 /*! \brief get the CORBA object reference associated to a name.
322  * 
323  *  get the CORBA object reference associated to a complete name with a path.
324  *  If the NamingService is out, the exception ServiceUnreachable is thrown 
325  * \param Path pathname. If the pathname begins with a '/', pathname is taken
326  *             as an absolute pathname. Else, pathname is taken as a relative
327  *             path, to current context. Prefer absolute pathname, relative
328  *             pathname are not safe, when SALOME_NamingService object is
329  *             shared or use in multithreaded context.
330  * \return the object reference if it exists under the pathname,
331  *             or nil reference in other cases.
332  * \sa         Register(CORBA::Object_ptr ObjRef, const char* Path),
333  *             Change_Directory(const char* Path)
334  */ 
335 // ============================================================================
336
337 CORBA::Object_ptr SALOME_NamingService::Resolve(const char* Path)
338   throw(ServiceUnreachable)
339 {
340 //   MESSAGE("BEGIN OF Resolve: " << Path);
341
342   Utils_Locker lock (&_myMutex);
343
344   // --- _current_context is replaced to the _root_context
345   //     if the Path begins whith '/'
346
347   if (Path[0] == '/')
348     {
349       _current_context = _root_context;
350     }
351
352   // --- the resolution of the directory path has to be done
353   //     to place the current_context to the correct node
354
355   CosNaming::Name context_name;
356   std::vector<std::string> splitPath;
357   _createContextNameDir(Path,
358                                                  context_name,
359                                                  splitPath,
360                                                  false);
361
362   ASSERT(!CORBA::is_nil(_current_context));
363
364   CORBA::Object_var obj =  CORBA::Object::_nil();
365
366   try
367     {
368       obj = _current_context->resolve(context_name);
369     }
370
371   catch (CosNaming::NamingContext::NotFound& ex)
372     {
373       CosNaming::Name n = ex.rest_of_name;
374
375       if (ex.why == CosNaming::NamingContext::missing_node)
376         MESSAGE("Resolve() : " << (char *) n[0].id
377               << " (" << (char *) n[0].kind << ") not found");
378
379       if (ex.why == CosNaming::NamingContext::not_context)
380         INFOS("Resolve() : "
381               << (char *) n[0].id << " (" << (char *) n[0].kind
382               << ") is not a context");
383
384       if (ex.why == CosNaming::NamingContext::not_object)
385         INFOS("Resolve() : " << (char *) n[0].id
386               << " (" << (char *) n[0].kind
387               << ") is not an object");
388     }
389
390   catch (CosNaming::NamingContext::CannotProceed&)
391     {
392       INFOS("Resolve(): CosNaming::NamingContext::CannotProceed");
393     }
394
395   catch (CosNaming::NamingContext::InvalidName&)
396     {
397       INFOS("Resolve(): CosNaming::NamingContext::InvalidName");
398     }
399
400   catch (CORBA::SystemException&)
401     {
402       INFOS("Resolve():CORBA::SystemException : unable to contact"
403             << "the naming service");
404       throw ServiceUnreachable();
405     }
406
407   return obj._retn();
408 }
409
410 // ============================================================================
411 /*! \brief get the CORBA object reference associated to an uncomplete name.
412  *
413  *  get the CORBA object reference associated to an uncomplete name with a
414  *  path. Look for the first occurence of name*.
415  *  If the NamingService is out, the exception ServiceUnreachable is thrown 
416  * \param Path pathname under the form "/path/name" (Absolute reference !)
417  *             search the fist reference like "/path(.dir)/name*(.kind)"
418  * \return     the object reference if found, or nil reference.
419  * \sa         Resolve(const char* Path)
420  */
421 // ============================================================================
422
423 CORBA::Object_ptr SALOME_NamingService::ResolveFirst(const char* Path)
424   throw(ServiceUnreachable)
425 {
426 //   MESSAGE("ResolveFirst");
427
428   Utils_Locker lock (&_myMutex);
429 //   SCRUTE(Path);
430
431   std::string thePath = Path;
432   std::string basePath = "";
433   std::string name = thePath;
434
435   std::string::size_type idx = thePath.rfind('/');
436
437   if (idx != std::string::npos) // at least one '/' found
438     {
439       basePath = thePath.substr(0, idx);
440       name = thePath.substr(idx + 1);
441 //       SCRUTE(basePath);
442     }
443
444 //   SCRUTE(name);
445   CORBA::Object_var obj = CORBA::Object::_nil();
446
447   bool isOk = false;
448   if (basePath.empty())
449     isOk =true;
450   else
451     isOk = Change_Directory(basePath.c_str());
452   
453   if (isOk)
454     {
455       std::vector<std::string> listElem = list_directory();
456       std::vector<std::string>::iterator its = listElem.begin();
457       
458       while (its != listElem.end())
459         {
460           MESSAGE(*its);
461           
462           if ((*its).find(name) == 0)
463             {
464               return Resolve((*its).c_str());
465             }
466           
467           its++;
468         }
469     }
470
471   return obj._retn();
472 }
473
474 // ============================================================================
475 /*! \brief find a component instance from hostname, containername,
476  *         componentName and number of processors.
477  *
478  *  find a component instance from hostname, containername, componentName and
479  *  number of processors.
480  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
481  * \param hostname      name of the machine on which the component is searched.
482  * \param containerName name of the container in which the component is
483                         instanciated.
484  * \param componentName name of the component we are looking for an existing 
485                         instance.
486  * \param nbproc        in case of multi processor machine, container name is
487  *                      suffixed with _nbproc.
488  * \return the object reference
489  */ 
490 // ============================================================================
491
492 CORBA::Object_ptr
493 SALOME_NamingService::ResolveComponent(const char* hostname,
494                                        const char* containerName,
495                                        const char* componentName,
496                                        const int nbproc)
497   throw(ServiceUnreachable)
498 {
499 //   MESSAGE("ResolveComponent");
500
501   Utils_Locker lock (&_myMutex);
502
503   std::string name = "/Containers/";
504
505   name += hostname;
506
507   if ( strlen(containerName) != 0 )
508     {
509       name += "/";
510
511       if ( nbproc >= 1 )
512         {
513           char *newContainerName = new char[strlen(containerName) + 8];
514           sprintf(newContainerName, "%s_%d", containerName, nbproc);
515           name += newContainerName;
516           delete [] newContainerName;
517         }
518
519       else
520         name += containerName;
521
522       name += "/";
523
524       name += componentName;
525
526       return ResolveFirst(name.c_str());
527     }
528
529   else
530     {
531       SCRUTE(name);
532       std::string basename = name;
533       if (Change_Directory(basename.c_str()))
534         {
535           std::vector<std::string> contList = list_subdirs();
536
537           for (unsigned int ind = 0; ind < contList.size(); ind++)
538             {
539               name = contList[ind].c_str();
540
541               if ( nbproc >= 1 )
542                 {
543                   char *str_nbproc = new char[8];
544                   sprintf(str_nbproc, "_%d", nbproc);
545                   if( strstr(name.c_str(),str_nbproc) == NULL)
546                     continue; // check only containers with _%d in name
547                   delete [] str_nbproc;
548                 }
549
550               name += "/";
551               name += componentName;
552               SCRUTE(name);
553               CORBA::Object_ptr obj = ResolveFirst(name.c_str());
554
555               if ( !CORBA::is_nil(obj) )
556                 return obj;
557               else
558                 Change_Directory(basename.c_str());
559             }
560         }
561
562       return CORBA::Object::_nil();
563     }
564 }
565
566 // ============================================================================
567 /*! \brief provide a default container name if empty.
568  *
569  *  the given container name is returned unchanged, unless it is empty.
570  * \param  containerName
571  * \return container name, where empty input is replaced by "FactoryServer",
572  *         without the path.
573  * \sa BuildContainerNameForNS(const char *containerName, const char *hostname)
574  */
575 // ============================================================================
576
577 std::string SALOME_NamingService::ContainerName(const char *containerName)
578 {
579   std::string ret;
580
581   if (strlen(containerName) == 0)
582     ret = "FactoryServer";
583   else
584     ret = containerName;
585
586   return ret;
587 }
588
589 // ============================================================================
590 /*! \brief build a container name, given a MachineParameters struct.
591  *
592  *  Build a container name with a MachineParameters struct. In case of multi
593  *  processor machine, container name is suffixed with _nbproc. nproc equals
594  *  (number of nodes)*(number of processor per nodes).
595  * \param params struct from which we get container name (may be
596  *               empty),  number of nodes and number of processor
597  *               per node.
598  * \return a container name without the path.
599  * \sa BuildContainerNameForNS(const Engines::MachineParameters& params,
600  *                             const char *hostname)
601  */
602 // ============================================================================
603
604 std::string 
605 SALOME_NamingService::ContainerName(const Engines::MachineParameters& params)
606 {
607   int nbproc;
608
609   if ( !params.isMPI )
610     nbproc = 0;
611   else if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
612     nbproc = 1;
613   else if ( params.nb_node == 0 )
614     nbproc = params.nb_proc_per_node;
615   else if ( params.nb_proc_per_node == 0 )
616     nbproc = params.nb_node;
617   else
618     nbproc = params.nb_node * params.nb_proc_per_node;
619
620   std::string ret = ContainerName(params.container_name);
621
622   if ( nbproc >= 1 )
623     {
624       char *suffix = new char[8];
625       sprintf(suffix, "_%d", nbproc);
626       ret += suffix;
627     }
628
629   return ret;
630 }
631
632 std::string 
633 SALOME_NamingService::ContainerName(const Engines::ContainerParameters& params)
634 {
635   int nbproc;
636
637   if ( !params.isMPI )
638     nbproc = 0;
639   else if ( params.nb_proc <= 0 )
640     nbproc = 1;
641   else
642     nbproc = params.nb_proc;
643
644   std::string ret = ContainerName(params.container_name);
645
646   if ( nbproc >= 1 )
647     {
648       char *suffix = new char[8];
649       sprintf(suffix, "_%d", nbproc);
650       ret += suffix;
651     }
652
653   return ret;
654 }
655
656 // ============================================================================
657 /*! \brief build a string representing a container in Naming Service.
658  *
659  *  Build a string representing the absolute pathname of a container in
660  *  SALOME_NamingService. This form gives a suffixed containerName in case of
661  *  multi processor machine.
662  * \param containerName name of the container in which the component is
663                         instanciated.
664  * \param hostname name of the host of the container, without domain names.
665  * \return the path under the form /Containers/hostname/containerName
666  * \sa ContainerName(const Engines::MachineParameters& params)
667  */
668 // ============================================================================
669
670 std::string SALOME_NamingService::BuildContainerNameForNS(const char *containerName,
671                                                      const char *hostname)
672 {
673   std::string ret = "/Containers/";
674   ret += hostname;
675   ret += "/";
676   ret += ContainerName(containerName);
677
678   return ret;
679 }
680
681 // ============================================================================
682 /*! \brief build a string representing a container in Naming Service.
683  *
684  *  Build a string representing the absolute pathname of a container in
685  *  SALOME_NamingService.
686  * \param params used as it is, or replaced by FactoryServer if empty.
687  * \param hostname name of the host of the container, without domain names.
688  * \return the path under the form /Containers/hostname/containerName
689  * \sa ContainerName(const char *containerName)
690  */
691 // ============================================================================
692
693 std::string
694 SALOME_NamingService::
695 BuildContainerNameForNS(const Engines::MachineParameters& params,
696                         const char *hostname)
697 {
698   std::string ret = "/Containers/";
699   ret += hostname;
700   ret += "/";
701   ret += ContainerName(params);
702
703   return ret;
704 }
705
706 std::string
707 SALOME_NamingService::
708 BuildContainerNameForNS(const Engines::ContainerParameters& params,
709                         const char *hostname)
710 {
711   std::string ret = "/Containers/";
712   ret += hostname;
713   ret += "/";
714   ret += ContainerName(params);
715
716   return ret;
717 }
718
719 // ============================================================================
720 /*! \brief search a name in current directory.
721  *
722  *  Search a name in the current directory. after call, the current directory
723  *  is changed to the directory containing the last occurence of name found.
724  *  If no occurence found (see return value), current directory remains
725  *  unchanged.
726  *
727  * \param  name the name to search.
728  * \return number of occurences found.
729  * \sa Change_Directory(const char* Path)
730  */ 
731 // ============================================================================
732
733 int SALOME_NamingService::Find(const char* name)
734 throw(ServiceUnreachable)
735 {
736   MESSAGE("BEGIN OF Find " << name);
737
738   Utils_Locker lock (&_myMutex);
739
740   CORBA::Long occurence_number = 0 ;
741
742   try
743     {
744       _Find(name, occurence_number);
745     }
746
747   catch (CORBA::SystemException&)
748     {
749       INFOS("!!!Find() : CORBA::SystemException : unable to contact"
750             << " the naming service");
751       throw ServiceUnreachable();
752     }
753
754   return occurence_number;
755 }
756
757 // ============================================================================
758 /*! \brief Creates a directory (context_name)
759  *
760  *  Creates a directory (context_name) relative to the current directory 
761  *  (current context) or relative to the root directory (root context), if
762  *  the path given begins with a '/'.
763  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
764  * \param Path   A relative or absolute pathname to store the object reference.
765  *               If the pathname begins with a '/', pathname is taken
766  *               as an absolute pathname. Else, pathname is taken as a relative
767  *               path, to current context. Prefer absolute pathname, relative
768  *               pathname are not safe, when SALOME_NamingService object is
769  *               shared or use in multithreaded context.   
770  *  \return true if successfull
771  *          (creation not strictly garanteed if true, because Register may
772  *           catch some specific unlikely exception without throw anything
773  *           --- to be corrected ---)
774  *  \sa RegisterCORBA::Object_ptr ObjRef, const char* Path)
775  */ 
776 // ============================================================================
777
778 bool SALOME_NamingService::Create_Directory(const char* Path)
779 throw(ServiceUnreachable)
780 {
781   MESSAGE("BEGIN OF Create_Directory");
782
783   Utils_Locker lock (&_myMutex);
784
785   std::string path(Path);
786
787   // --- if path empty, nothing to create, no context change
788
789   if (path.empty())
790     return false;
791
792   // --- if path ='/', nothing to create, only change to root_context
793
794   if (path == "/")
795     {
796       MESSAGE("Create Directory '/', just change to root_context");
797       _current_context = _root_context;
798       return true;
799     }
800
801   // --- path must end with '/'
802   
803   if (path[path.length()-1] != '/') path += '/';
804
805   Register(CORBA::Object::_nil(), path.c_str());
806   return true;
807 }
808
809 // ============================================================================
810 /*! \brief change current directory to the given path
811  *
812  *  change the current directory to the given path in parameter.
813  *  Warning: avoid use when the SALOME_NamingService instance is shared by
814  *  several threads (current context may be modified by another thread).
815  *  If the path is empty, nothing done return OK.
816  *  If Path ="/", the current directory changes to the root directory.
817  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
818  * \param  Path the new current directory
819  * \return true if the change succeeded
820  */ 
821 // ============================================================================
822
823 bool SALOME_NamingService::Change_Directory(const char* Path)
824 throw(ServiceUnreachable)
825 {
826 //   MESSAGE("BEGIN OF Change_Directory " << Path);
827   Utils_Locker lock (&_myMutex);
828
829   std::string path(Path);
830
831   // --- if path empty, nothing to do
832
833   if (path.empty())
834     return true;
835
836   // --- if path ='/', nothing to resolve, only change to root_context
837
838   if (path == "/")
839     {
840 //       MESSAGE("Change_Directory is called to go to the root_context");
841       _current_context = _root_context;
842       return true;
843     }
844
845   CosNaming::NamingContext_var current_context = _current_context;
846   bool changeOK = false;
847
848   // --- replace _current_context with _root_context if Path begins whith '/'
849
850   if (path[0] == '/')
851     current_context = _root_context;
852
853   // --- need to resolve directory path
854
855   ASSERT(!CORBA::is_nil(current_context));
856   
857   if (path[path.length()-1] != '/') path += '/';
858 //   SCRUTE(path);
859   CosNaming::Name context_name;
860   std::vector<std::string> splitPath;
861   _createContextNameDir(path.c_str(),
862                                                  context_name,
863                                                  splitPath,
864                                                  true);
865   
866   // --- Context creation
867   
868   try
869     {
870       CORBA::Object_var obj = current_context->resolve(context_name);
871       current_context = CosNaming::NamingContext::_narrow(obj);
872       ASSERT(!CORBA::is_nil(current_context));
873       _current_context = current_context;
874       changeOK = true;
875     }
876   
877   catch (CosNaming::NamingContext::NotFound& ex)
878     {
879       CosNaming::Name n = ex.rest_of_name;
880       
881       if (ex.why == CosNaming::NamingContext::missing_node)
882         MESSAGE( "Change_Directory() : " << (char *) n[0].id
883                << " (" << (char *) n[0].kind << ") not found");
884       if (ex.why == CosNaming::NamingContext::not_context)
885         INFOS("Change_Directory() : " << (char *) n[0].id
886               << " (" << (char *) n[0].kind
887                   << ") is not a context" );
888       if (ex.why == CosNaming::NamingContext::not_object)
889         INFOS( "Change_Directory() : " << (char *) n[0].id
890                << " (" << (char *) n[0].kind
891                << ") is not an object" );
892     }
893   
894   catch (CosNaming::NamingContext::CannotProceed&)
895     {
896       INFOS("Change_Directory(): CosNaming::NamingContext::CannotProceed");
897     }
898   
899   catch (CosNaming::NamingContext::InvalidName&)
900     {
901       INFOS("Change_Directory(): CosNaming::NamingContext::InvalidName");
902     }
903   
904   catch (CORBA::SystemException&)
905     {
906       INFOS("Change_Directory():CORBA::SystemException : unable to contact"
907             << "the naming service");
908       throw ServiceUnreachable();
909     }
910
911   return changeOK;
912 }
913
914 // ============================================================================
915 /*! \brief get the current directory path
916  *
917  *  Get the current directory path.
918  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
919  * \return the path of the current_context
920  * \sa  _current_directory
921  */ 
922 // ============================================================================
923
924 char* SALOME_NamingService::Current_Directory()
925 throw(ServiceUnreachable)
926 {
927   MESSAGE("BEGIN OF Current_Directory");
928
929   Utils_Locker lock (&_myMutex);
930
931   CosNaming::NamingContext_var ref_context = _current_context;
932
933   std::vector<std::string> splitPath;
934   splitPath.resize(0);
935   int lengthPath = 0;
936   bool notFound = true ;
937
938   // --- start search from root context
939
940   _current_context = _root_context ;
941
942   try
943     {
944       _current_directory(splitPath, lengthPath, ref_context, notFound );
945     }
946
947   catch (CORBA::SystemException&)
948     {
949       INFOS("Current_Directory(): CORBA::SystemException: unable to contact"
950             << " the naming service" )
951       throw ServiceUnreachable();
952     }
953
954   std::string path;
955   lengthPath = splitPath.size();
956   for (int k = 0 ; k < lengthPath ;k++)
957     {
958       path += "/";
959       path += splitPath[k];
960     }
961
962   SCRUTE(path)
963   _current_context = ref_context ;
964
965   return strdup(path.c_str());
966 }
967
968 // ============================================================================
969 /*! \brief list recursively all objects in the current context
970  *
971  *  List and print via trace all directories and objects in the current
972  *  context. Trace must be activated: compile option _DEBUG_
973  *  If the NamingService is out, the exception ServiceUnreachable is thrown
974  */ 
975 // ============================================================================
976
977 void SALOME_NamingService::list()
978 throw(ServiceUnreachable)
979 {
980   MESSAGE("Begin of list");
981
982   Utils_Locker lock (&_myMutex)
983
984     ;
985   CosNaming::BindingList_var binding_list;
986   CosNaming::BindingIterator_var binding_iterator;
987   CosNaming::Binding_var binding ;
988
989   unsigned long nb = 0 ; // --- only for the BindingIterator use,
990                          //     to access the bindings
991
992   CosNaming::NamingContext_var ref_context = _current_context;
993
994   _current_context->list(nb, binding_list, binding_iterator) ;
995
996   if (! CORBA::is_nil(binding_iterator))
997     {
998       while (binding_iterator->next_one(binding))
999         {
1000           CosNaming::Name bindingName = binding->binding_name;
1001
1002           if (binding->binding_type == CosNaming::ncontext)
1003             {
1004               MESSAGE( "Context : " << bindingName[0].id );
1005
1006               try
1007                 {
1008                   Change_Directory(bindingName[0].id);
1009                 }
1010
1011               catch (ServiceUnreachable&)
1012                 {
1013                   INFOS( "list(): ServiceUnreachable" )
1014                     throw ServiceUnreachable();
1015                 }
1016
1017               list();
1018               _current_context = ref_context ;
1019             }
1020
1021           else if (binding->binding_type == CosNaming::nobject)
1022             {
1023               MESSAGE( "Object : " << bindingName[0].id );
1024             }
1025         }
1026
1027       binding_iterator->destroy();
1028     }
1029 }
1030
1031 // ============================================================================
1032 /*! \brief list all the objects in the current directory.
1033  *
1034  *  get a list of all the objects in the current directory, without recursion
1035  *  on the subdirectories. Only the objects are listed, not the directories.
1036  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1037  * \return list of strings with objects found.
1038  * \sa vector<string> list_directory_recurs()
1039  */ 
1040 // ============================================================================
1041
1042 std::vector<std::string> SALOME_NamingService::list_directory()
1043 throw(ServiceUnreachable)
1044 {
1045 //   MESSAGE("list_directory");
1046   std::vector<std::string> dirList ;
1047   dirList.resize(0);
1048
1049   CosNaming::BindingList_var binding_list;
1050   CosNaming::BindingIterator_var binding_iterator;
1051   CosNaming::Binding_var binding ;
1052
1053   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1054                          //     to access the bindings
1055
1056   CosNaming::NamingContext_var ref_context = _current_context;
1057
1058   _current_context->list(nb, binding_list, binding_iterator);
1059
1060   if (binding_iterator->_is_nil())
1061     return dirList;
1062
1063   while (binding_iterator->next_one(binding))
1064     {
1065       CosNaming::Name bindingName = binding->binding_name;
1066
1067       if (binding->binding_type == CosNaming::nobject)
1068         {
1069           // remove memory leak
1070           // dirList.push_back(CORBA::string_dup(bindingName[0].id));
1071           dirList.push_back(std::string(bindingName[0].id));
1072         }
1073     }
1074
1075 //   for (unsigned int ind = 0; ind < dirList.size(); ind++)
1076 //     MESSAGE("list_directory : Object : " << dirList[ind]);
1077
1078   binding_iterator->destroy();
1079
1080   return dirList;
1081 }
1082
1083
1084 // ============================================================================
1085 /*! \brief list all the subdirectories in the current directory.
1086  *
1087  *  get a list of all the subdirectories in the current directory,
1088  *  without recursion on the subdirectories.
1089  *  Only the subdirectories are listed, not the objects.
1090  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1091  * \return list of strings with directories found.
1092  * \sa vector<string> list_directory()
1093  */ 
1094 // ============================================================================
1095
1096 std::vector<std::string> SALOME_NamingService::list_subdirs()
1097 throw(ServiceUnreachable)
1098 {
1099   MESSAGE("list_subdirs");
1100   std::vector<std::string> dirList ;
1101   dirList.resize(0);
1102
1103   CosNaming::BindingList_var binding_list;
1104   CosNaming::BindingIterator_var binding_iterator;
1105   CosNaming::Binding_var binding ;
1106
1107   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1108                          //     to access the bindings
1109
1110   CosNaming::NamingContext_var ref_context = _current_context;
1111
1112   _current_context->list(nb, binding_list, binding_iterator) ;
1113
1114   if (binding_iterator->_is_nil())
1115     return dirList;
1116
1117   while (binding_iterator->next_one(binding))
1118     {
1119       CosNaming::Name bindingName = binding->binding_name;
1120
1121       if (binding->binding_type == CosNaming::ncontext)
1122         {
1123           dirList.push_back(bindingName[0].id.in());
1124         }
1125     }
1126
1127   for (unsigned int ind = 0; ind < dirList.size(); ind++)
1128     MESSAGE("list_directory : Object : " << dirList[ind]);
1129
1130   binding_iterator->destroy();
1131
1132   return dirList;
1133 }
1134
1135 // ============================================================================
1136 /*! \brief  list all the objects in the current directory and subdirectories.
1137  *
1138  *  get a list of all the objects in the current directory, with recursion
1139  *  on the subdirectories. Only the objects are listed, not the directories.
1140  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1141  * \return list of strings with objects found.
1142  * \sa vector<string> list_directory()
1143  */ 
1144 // ============================================================================
1145
1146 std::vector<std::string> SALOME_NamingService::list_directory_recurs()
1147 throw(ServiceUnreachable)
1148 {
1149   MESSAGE("list_directory_recurs");
1150
1151   Utils_Locker lock (&_myMutex);
1152
1153   std::vector<std::string> dirList ;
1154
1155   char* currentDir = Current_Directory();
1156
1157   _list_directory_recurs(dirList, "", currentDir);
1158
1159   free(currentDir);
1160
1161   return dirList;
1162 }
1163
1164 // ============================================================================
1165 /*! \brief destroy an entry in naming service.
1166  *
1167  *  Destroy an association Path - Object Reference.
1168  *  If the NamingService is out, the exception ServiceUnreachable is thrown 
1169  * \param Path object path
1170  */ 
1171 // ============================================================================
1172
1173 void SALOME_NamingService::Destroy_Name(const char* Path)
1174 throw(ServiceUnreachable)
1175 {
1176   MESSAGE("BEGIN OF Destroy_Name " << Path);
1177
1178   Utils_Locker lock (&_myMutex);
1179
1180   std::string path(Path);
1181
1182   // --- if path empty, nothing to do
1183
1184   if (path.empty())
1185     return;
1186
1187   // --- if path = '/' not applicable, nothing to do
1188
1189   if (path == "/")
1190     return;
1191
1192   // --- if path begins with '/', set current directory to root context
1193
1194   if (path[0] == '/')
1195     _current_context = _root_context;
1196
1197   // --- context of the directory containing the object
1198
1199   CosNaming::Name context_name;
1200   std::vector<std::string> splitPath;
1201   int dimension_resultat = _createContextNameDir(path.c_str(),
1202                                                  context_name,
1203                                                  splitPath,
1204                                                  true);
1205
1206   bool exist = false;
1207
1208   if (dimension_resultat > 0)
1209     {
1210       // --- path contains a directory, not only an object name
1211       //     switch to the new directory (or return if directory not found)
1212
1213       try
1214         {
1215           CORBA::Object_var obj = _current_context->resolve(context_name);
1216           _current_context = CosNaming::NamingContext::_narrow(obj);
1217           exist = true;
1218         }
1219
1220       catch (CosNaming::NamingContext::NotFound &ex)
1221         {
1222           // --- failed to resolve
1223           exist = false;
1224
1225           CosNaming::Name n = ex.rest_of_name;
1226
1227           if (ex.why == CosNaming::NamingContext::missing_node)
1228             INFOS( "Destroy_Name(): " << (char *) n[0].id
1229                    << " (" << (char *) n[0].kind << ") not found" );
1230           if (ex.why == CosNaming::NamingContext::not_context)
1231             INFOS( "Destroy_Name() : " << (char *) n[0].id
1232                    << " (" << (char *) n[0].kind
1233                    << ") is not a context" );
1234           if (ex.why == CosNaming::NamingContext::not_object)
1235             INFOS( "Destroy_Name() : " << (char *) n[0].id
1236                    << " (" << (char *) n[0].kind
1237                    << ") is not an object" );
1238         }
1239
1240       catch (CosNaming::NamingContext::InvalidName &)
1241         {
1242           INFOS("Destroy_Name: CosNaming::NamingContext::InvalidName");
1243         }
1244
1245       catch (CosNaming::NamingContext::CannotProceed &)
1246         {
1247           INFOS("Destroy_Name: CosNaming::NamingContext::CannotProceed");
1248         }
1249
1250       catch (CORBA::SystemException&)
1251         {
1252           INFOS("Destroy_Name : CORBA::SystemException: "
1253                 << "unable to contact the naming service");
1254           throw ServiceUnreachable();
1255         }
1256
1257       if (! exist) return;
1258     }
1259
1260   ASSERT(!CORBA::is_nil(_current_context));
1261
1262   // --- The current directory is now the directory where the object should
1263   //     be destroyed
1264
1265   int sizePath = splitPath.size();
1266   if (sizePath > dimension_resultat)
1267     {
1268       ASSERT(sizePath == dimension_resultat+1);
1269       context_name.length(1);
1270
1271       try
1272         {
1273           // --- the last element is an object and not a directory
1274
1275           context_name[0].id =
1276             CORBA::string_dup(splitPath[dimension_resultat].c_str());
1277           context_name[0].kind = CORBA::string_dup("object");
1278           SCRUTE(context_name[0].id);
1279  
1280           _current_context->unbind(context_name);
1281           MESSAGE("The object " << context_name[0].id << " has been deleted");
1282         }
1283
1284       catch (CosNaming::NamingContext::NotFound& ex)
1285         {
1286           CosNaming::Name n = ex.rest_of_name;
1287
1288           if (ex.why == CosNaming::NamingContext::missing_node)
1289             INFOS( "Destroy_Name() : " << (char *) n[0].id
1290                    << " (" << (char *) n[0].kind << ") not found" );
1291           if (ex.why == CosNaming::NamingContext::not_context)
1292             INFOS( "Destroy_Name() : " << (char *) n[0].id
1293                    << " (" << (char *) n[0].kind
1294                    << ") is not a context" );
1295           if (ex.why == CosNaming::NamingContext::not_object)
1296             INFOS( "Destroy_Name() : " << (char *) n[0].id
1297                    << " (" << (char *) n[0].kind
1298                    << ") is not an object" );
1299           }
1300
1301       catch (CosNaming::NamingContext::CannotProceed&)
1302         {
1303           INFOS( "Destroy_Name(): CosNaming::NamingContext::CannotProceed");
1304         }
1305
1306       catch (CosNaming::NamingContext::InvalidName&)
1307         {
1308           INFOS( "Destroy_Name(): CosNaming::NamingContext::InvalidName");
1309         }
1310
1311       catch (CORBA::SystemException&)
1312         {
1313           INFOS( "Destroy_Name(): CORBA::SystemException: unable to contact"
1314                  << " the naming service");
1315           throw ServiceUnreachable();
1316         }
1317     }
1318 }
1319
1320 // ============================================================================
1321 /*! \brief Destroy an empty directory
1322  *
1323  *  Destroy an empty directory in Naming Service.
1324  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1325  * \param Path directory path
1326  */ 
1327 // ============================================================================
1328
1329 void SALOME_NamingService::Destroy_Directory(const char* Path)
1330 throw(ServiceUnreachable)
1331 {
1332   MESSAGE("BEGIN OF Destroy_Directory " << Path);
1333
1334   Utils_Locker lock (&_myMutex);
1335
1336   std::string path(Path);
1337
1338   // --- if path empty, nothing to do
1339
1340   if (path.empty())
1341     return;
1342
1343   // --- if path begins with '/', set current directory to root context
1344
1345   if (path[0] == '/')
1346     _current_context = _root_context;
1347
1348   CosNaming::NamingContext_var ref_context = _current_context;
1349
1350   // --- path must ends with '/' for a directory
1351
1352   if (path[path.size() -1] != '/')
1353     path += '/';
1354
1355   // --- context of the directory
1356
1357   CosNaming::Name context_name;
1358   std::vector<std::string> splitPath;
1359   int dimension_resultat = _createContextNameDir(path.c_str(),
1360                                                  context_name,
1361                                                  splitPath,
1362                                                  true);
1363   bool exist = false;
1364
1365   if (dimension_resultat > 0)
1366     {
1367       // --- path contains a directory, not only an object name
1368       //     switch to the new directory (or return if directory not found)
1369
1370       try
1371         {
1372           CORBA::Object_var obj = _current_context->resolve(context_name);
1373           _current_context = CosNaming::NamingContext::_narrow(obj);
1374           exist = true;
1375         }
1376
1377       catch (CosNaming::NamingContext::NotFound &ex)
1378         {
1379           // --- failed to resolve
1380           exist = false;
1381
1382           CosNaming::Name n = ex.rest_of_name;
1383
1384           if (ex.why == CosNaming::NamingContext::missing_node)
1385             INFOS( "Destroy_Directory(): " << (char *) n[0].id
1386                    << " (" << (char *) n[0].kind << ") not found" );
1387           if (ex.why == CosNaming::NamingContext::not_context)
1388             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1389                    << " (" << (char *) n[0].kind
1390                    << ") is not a context" );
1391           if (ex.why == CosNaming::NamingContext::not_object)
1392             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1393                    << " (" << (char *) n[0].kind
1394                    << ") is not an object" );
1395         }
1396
1397       catch (CosNaming::NamingContext::InvalidName &)
1398         {
1399           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1400         }
1401
1402       catch (CosNaming::NamingContext::CannotProceed &)
1403         {
1404           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1405         }
1406
1407       catch (CORBA::SystemException&)
1408         {
1409           INFOS("Destroy_Directory : CORBA::SystemException: "
1410                 << "unable to contact the naming service");
1411           throw ServiceUnreachable();
1412         }
1413
1414       if (! exist) return;
1415     }
1416
1417   ASSERT(!CORBA::is_nil(_current_context));
1418
1419   // --- Context Destruction
1420
1421   bool isContextDestroyed = false;
1422   try
1423     {
1424       _current_context->destroy();
1425       MESSAGE( "The context " << path << " has been deleted" );
1426       isContextDestroyed = true;
1427     }
1428
1429   catch (CosNaming::NamingContext::NotEmpty&)
1430     {
1431       INFOS( "Destroy_Directory(): CosNaming::NamingContext::NoEmpty "
1432              << path << " is not empty" );
1433     }
1434
1435   catch (CORBA::SystemException&)
1436     {
1437       INFOS( "Destroy_Directory():CORBA::SystemException : "
1438              << "unable to contact the naming service");
1439       throw ServiceUnreachable();
1440     }
1441
1442   // --- go to the reference directory
1443
1444   _current_context = ref_context ;
1445
1446   ASSERT(!CORBA::is_nil(_current_context));
1447
1448   if (isContextDestroyed)
1449     {
1450       try
1451         {
1452           _current_context->unbind(context_name);
1453           MESSAGE( "The bind to the context "
1454                    << context_name[0].id
1455                    << " has been deleted" );
1456         }
1457
1458       catch (CosNaming::NamingContext::NotFound& ex)
1459         {
1460           CosNaming::Name n = ex.rest_of_name;
1461
1462           if (ex.why == CosNaming::NamingContext::missing_node)
1463             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1464                    << " (" << (char *) n[0].kind << ") not found" );
1465           if (ex.why == CosNaming::NamingContext::not_context)
1466             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1467                    << " (" << (char *) n[0].kind
1468                    << ") is not a context" );
1469           if (ex.why == CosNaming::NamingContext::not_object)
1470             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1471                    << " (" << (char *) n[0].kind
1472                    << ") is not an object" );
1473         }
1474
1475       catch (CosNaming::NamingContext::CannotProceed&)
1476         {
1477           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1478         }
1479
1480       catch (CosNaming::NamingContext::InvalidName&)
1481         {
1482           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1483             }
1484
1485       catch (CORBA::SystemException&)
1486         {
1487           INFOS("Destroy_Directory:CORBA::SystemException : unable to contact"
1488                  << " the naming service");
1489           throw ServiceUnreachable();
1490         }
1491     }
1492 }
1493
1494 // ============================================================================
1495 /*! \brief Destroy a directory with its contents.
1496  *
1497  *  Destroy the objects associations in a directory, and the directory itself,
1498  *  if there is no subdirectories. 
1499  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1500  * \param Path the directory path.
1501  */ 
1502 // ============================================================================
1503
1504 void SALOME_NamingService::Destroy_FullDirectory(const char* Path)
1505 throw(ServiceUnreachable)
1506 {
1507   MESSAGE("begin of Destroy_FullDirectory " << Path);
1508   if( Change_Directory(Path) )
1509     {
1510       std::vector<std::string> contList = list_directory();
1511
1512       for (unsigned int ind = 0; ind < contList.size(); ind++)
1513         Destroy_Name(contList[ind].c_str());
1514       
1515       Destroy_Directory(Path);
1516     }
1517 }
1518
1519 // ============================================================================
1520 /*! \brief  initialize root context (root directory)
1521  *
1522  * the root context initialisation must be done when the SALOME_NamingService
1523  * instance is created and before any othe call. See constructors.
1524  */ 
1525 // ============================================================================
1526
1527 void SALOME_NamingService::_initialize_root_context()
1528 {
1529   //MESSAGE("Get the root context");
1530
1531   try
1532     {
1533       CORBA::Object_var obj = _orb->resolve_initial_references("NameService");
1534       _root_context = CosNaming::NamingContext::_narrow(obj);
1535       _current_context = _root_context ;
1536       ASSERT(!CORBA::is_nil(_root_context));
1537     }
1538
1539   catch (CORBA::SystemException&)
1540     {
1541       INFOS("CORBA::SystemException: unable to contact the naming service");
1542       throw ServiceUnreachable();
1543     }
1544
1545   catch (...)
1546     {
1547       INFOS("Unknown Exception: unable to contact the naming service");
1548       throw ServiceUnreachable();
1549     }
1550 }
1551
1552 // ============================================================================
1553 /*! \brief transform a string path in CosNaming structure.
1554  *
1555  *  Transform a path given as a string in a CosNaming structure.
1556  *  \param path         a relative or absolute path, with or without an object.
1557  *                      An absolute path begins with '/'.
1558  *                      A path without an object ends with '/'.
1559  *  \param context_name CosNaming structure to put the path.
1560  *  \param splitPath    a vector of string with subdirectories and final
1561  *                      object, if any.
1562  *  \param onlyDir      if true, final object (if any) is ommited
1563  *                      in context_name.
1564  *                      if false, final object (if any) is included in
1565  *                      context_name.
1566  *  \return             dimension of context_name
1567  */ 
1568 // ============================================================================
1569
1570 int
1571 SALOME_NamingService::_createContextNameDir(std::string path,
1572                                             CosNaming::Name& context_name,
1573                                             std::vector<std::string>& splitPath,
1574                                             bool onlyDir)
1575 {
1576   if (path.empty())
1577     return 0;
1578
1579   std::string::size_type begIdx, endIdx;
1580   const std::string delims("/");
1581   splitPath.resize(0);
1582   bool endWithDelim = false;
1583
1584   begIdx = path.find_first_not_of(delims);
1585   while (begIdx != std::string::npos)
1586     {
1587       endIdx = path.find_first_of(delims, begIdx);
1588       if (endIdx == path.length()-1)
1589         endWithDelim = true;
1590       if (endIdx == std::string::npos)
1591         endIdx = path.length();
1592       int lsub = endIdx - begIdx;
1593       if (lsub >= 1)
1594         splitPath.push_back(path.substr(begIdx, lsub));
1595       begIdx = path.find_first_not_of(delims, endIdx);
1596     }
1597
1598   int dim;
1599   if (onlyDir)                  // only directory part
1600     {
1601       dim = splitPath.size()-1; // omit final object
1602       if (endWithDelim)         // unless the path ends with a delimiter 
1603         dim++;
1604       endWithDelim = true;
1605     }
1606   else
1607     dim = splitPath.size();     // directories and final object
1608
1609   context_name.length(dim);
1610   for (int i=0; i<dim; i++)
1611     {
1612 //       SCRUTE(splitPath[i]);
1613       context_name[i].id = CORBA::string_dup(splitPath[i].c_str());
1614       if (!endWithDelim && (i == dim-1)) // here, the last string is an object
1615         {
1616           context_name[i].kind = CORBA::string_dup("object");
1617 //        MESSAGE("--- " <<splitPath[i] <<".object");
1618         }
1619       else
1620         {
1621           context_name[i].kind = CORBA::string_dup("dir");
1622 //        MESSAGE("--- " <<splitPath[i] <<".dir");
1623         }
1624     }
1625   return dim;
1626 }
1627
1628 // ============================================================================
1629 /*! \brief search a name in current directory.
1630  *
1631  *  Search a name in the current directory. after call, the current directory
1632  *  is changed to the directory containing the last occurence of name found.
1633  *  If no occurence found (see return value), current directory remains
1634  *  unchanged. The call is recursive.
1635  *
1636  * \param  name the name to search.
1637  * \param  occurence_number number of occurence already found (incremented)
1638  */ 
1639 // ============================================================================
1640
1641 void SALOME_NamingService::_Find(const char* name,
1642                                  CORBA::Long& occurence_number)
1643 {
1644   MESSAGE("BEGIN OF _Find "<<  occurence_number << " " << name);
1645
1646   CosNaming::BindingList_var binding_list;
1647   CosNaming::BindingIterator_var binding_iterator;
1648   CosNaming::Binding_var binding;
1649
1650   unsigned long nb = 0 ; // --- only for the use of the BindingIterator,
1651                          //     to access the bindings
1652
1653   CosNaming::NamingContext_var ref_context = _current_context;
1654   CosNaming::NamingContext_var found_context = _current_context;
1655
1656   _current_context->list(nb, binding_list, binding_iterator) ;
1657
1658   if (! CORBA::is_nil(binding_iterator))
1659     {
1660       while (binding_iterator->next_one(binding))
1661         {
1662           CosNaming::Name bindingName = binding->binding_name;
1663           
1664           if (binding->binding_type == CosNaming::ncontext)
1665             {
1666               // --- We work on a directory,
1667               //     the search should be done in this directory
1668               
1669               Change_Directory(bindingName[0].id);
1670               _Find(name, occurence_number);
1671               
1672               // --- We'll go back to the initial context
1673               
1674               _current_context = ref_context ;
1675             }
1676           
1677           else if (binding->binding_type == CosNaming::nobject)
1678             {
1679               // --- We work on an object...
1680               
1681               if (!strcmp( bindingName[0].id, name))
1682                 {
1683                   //MESSAGE("One occurence was found");
1684                   occurence_number++;
1685                   
1686                   // --- We keep in memory the directory where
1687                   //     one occurence was found
1688                   
1689                   found_context = _current_context ;
1690                 }
1691             }
1692         }
1693       
1694       binding_iterator->destroy();
1695     }
1696   // --- We go to the last directory where an occurence was found
1697
1698   _current_context = found_context;
1699
1700   SCRUTE(occurence_number);
1701 }
1702
1703 // ============================================================================
1704 /*! \brief find the current directory path.
1705  * 
1706  *  Parse the naming service tree to find the current context and give the
1707  *  associated directory path (relative to root context).
1708  * \param splitPath 
1709  * \param lengthResult
1710  * \param contextToFind
1711  * \param notFound
1712  */ 
1713 // ============================================================================
1714
1715 void
1716 SALOME_NamingService::
1717 _current_directory(std::vector<std::string>& splitPath,
1718                    int& lengthResult,
1719                    CosNaming::NamingContext_var contextToFind,
1720                    bool& notFound)
1721 {
1722   MESSAGE("BEGIN OF _current_Directory");
1723
1724   CosNaming::BindingList_var binding_list;
1725   CosNaming::BindingIterator_var binding_iterator;
1726   CosNaming::Binding_var binding;
1727
1728   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1729                          //     to access the bindings
1730
1731   CosNaming::NamingContext_var ref_context = _current_context;
1732   CosNaming::NamingContext_var temp_context = _current_context;
1733
1734   _current_context->list(nb, binding_list, binding_iterator);
1735
1736   if ( !binding_iterator->_is_nil() )
1737     {
1738       while ((binding_iterator->next_one(binding)) && notFound)
1739         {
1740           CosNaming::Name bindingName = binding->binding_name;
1741
1742           if (binding->binding_type == CosNaming::ncontext)
1743             {
1744               // --- directory, search in it
1745
1746               const char* bindingNameid=bindingName[0].id;
1747               splitPath.push_back(bindingNameid);
1748               lengthResult++;
1749
1750               CORBA::Object_var obj = _current_context->resolve(bindingName);
1751               temp_context = CosNaming::NamingContext::_narrow(obj);
1752
1753               if (temp_context->_is_equivalent(contextToFind))
1754                 {
1755                   MESSAGE("The context is found, we stop the search");
1756                   notFound = false;
1757                   SCRUTE(notFound);
1758                 }
1759
1760               if (notFound)
1761                 {
1762                   SCRUTE(bindingName[0].id);
1763                   Change_Directory(bindingName[0].id);
1764                   _current_directory(splitPath,
1765                                      lengthResult,
1766                                      contextToFind,
1767                                      notFound);
1768
1769                   if (notFound)
1770                     {
1771                       // --- go back to the initial context
1772
1773                       _current_context = ref_context;
1774
1775                       MESSAGE("Just before the delete of "
1776                               << splitPath[lengthResult-1]);
1777                       splitPath.pop_back();
1778                       lengthResult--;
1779                     }
1780                 }
1781             }
1782         }
1783
1784       binding_iterator->destroy();
1785     }
1786
1787   // --- return to the last directory where an occurence was found
1788
1789   _current_context = ref_context ;
1790 }
1791
1792
1793 // ============================================================================
1794 /*! \brief list recursively all objects in the given directory and subdirs.
1795  *
1796  *  get a list of all the objects in the current directory, with recursion
1797  *  on the subdirectories. Only the objects are listed, not the directories.
1798  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1799  *  _current_context must refer to absCurDirectory.
1800  *
1801  *  \param myList          The list that will be filled.
1802  *  \param relativeSubDir  The directory relative to absCurDirectory in which
1803  *                         the objects are found.
1804  *  \param absCurDirectory The current directory, absolute path
1805  */ 
1806 // ============================================================================
1807
1808 void SALOME_NamingService::_list_directory_recurs(std::vector<std::string>& myList,
1809                                                   std::string relativeSubDir,
1810                                                   std::string absCurDirectory)
1811 {
1812   CosNaming::BindingList_var binding_list;
1813   CosNaming::BindingIterator_var binding_iterator;
1814   CosNaming::Binding_var binding ;
1815
1816   unsigned long nb = 0 ; // --- only for thethe use of BindingIterator
1817                          //     to access the bindings
1818
1819   std::string absDir;
1820
1821   CosNaming::NamingContext_var ref_context = _current_context;
1822
1823   if (! relativeSubDir.empty())
1824     {
1825       Change_Directory(relativeSubDir.c_str());
1826       absDir = absCurDirectory + "/" + relativeSubDir;
1827     }
1828
1829   else
1830     absDir = absCurDirectory;
1831
1832   SCRUTE(absDir);
1833   _current_context->list(nb, binding_list, binding_iterator) ;
1834
1835   if (! CORBA::is_nil(binding_iterator))
1836     {
1837       while (binding_iterator->next_one(binding))
1838         {
1839           CosNaming::Name bindingName = binding->binding_name;
1840
1841           if (binding->binding_type == CosNaming::ncontext)
1842             {
1843               std::string relativeSdir(bindingName[0].id);
1844               _list_directory_recurs(myList, relativeSdir, absDir);
1845             }
1846
1847           else if (binding->binding_type == CosNaming::nobject)
1848             {
1849               std::string objName(bindingName[0].id);
1850               std::string elt = absDir + "/" + objName;
1851               SCRUTE(elt);
1852               myList.push_back(elt);
1853             }
1854         }
1855
1856       binding_iterator->destroy();
1857     }
1858   if (! relativeSubDir.empty())
1859     {
1860       _current_context = ref_context;
1861     }
1862 }
1863
1864 // ============================================================================
1865 /*! \brief return a stringified reference of root context
1866  *
1867  * \return a stringified reference of root context
1868  */
1869 // ============================================================================
1870
1871 char * SALOME_NamingService::getIORaddr()
1872 {
1873   return _orb->object_to_string(_root_context);
1874 }
1875
1876 /*! \brief get the orb used by the naming service
1877  *
1878  *  \return the orb
1879  */
1880 CORBA::ORB_ptr SALOME_NamingService::orb()
1881 {
1882   return _orb;
1883 }
1884