Salome HOME
638fee21eada1792d5ae1b6c3aa13751a4acc6d9
[modules/kernel.git] / src / NamingService / SALOME_NamingService.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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 WIN32
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 ContainerParameters struct.
591  *
592  *  Build a container name with a ContainerParameters struct. In case of multi
593  *  processor machine, container name is suffixed with number of processors.
594  * \param params struct from which we get container name (may be empty) and
595  *               number of processors.
596  * \return a container name without the path.
597  * \sa BuildContainerNameForNS(const Engines::ContainerParameters& params,
598  *                             const char *hostname)
599  */
600 // ============================================================================
601
602 std::string 
603 SALOME_NamingService::ContainerName(const Engines::ContainerParameters& params)
604 {
605   int nbproc;
606
607   if ( !params.isMPI )
608     nbproc = 0;
609   else if ( params.nb_proc <= 0 )
610     nbproc = 1;
611   else
612     nbproc = params.nb_proc;
613
614   std::string ret = ContainerName(params.container_name);
615
616   if ( nbproc >= 1 )
617     {
618       char *suffix = new char[8];
619       sprintf(suffix, "_%d", nbproc);
620       ret += suffix;
621     }
622
623   return ret;
624 }
625
626 // ============================================================================
627 /*! \brief build a string representing a container in Naming Service.
628  *
629  *  Build a string representing the absolute pathname of a container in
630  *  SALOME_NamingService. This form gives a suffixed containerName in case of
631  *  multi processor machine.
632  * \param containerName name of the container in which the component is
633                         instanciated.
634  * \param hostname name of the host of the container, without domain names.
635  * \return the path under the form /Containers/hostname/containerName
636  * \sa ContainerName(const Engines::MachineParameters& params)
637  */
638 // ============================================================================
639
640 std::string SALOME_NamingService::BuildContainerNameForNS(const char *containerName,
641                                                      const char *hostname)
642 {
643   std::string ret = "/Containers/";
644   ret += hostname;
645   ret += "/";
646   ret += ContainerName(containerName);
647
648   return ret;
649 }
650
651 // ============================================================================
652 /*! \brief build a string representing a container in Naming Service.
653  *
654  *  Build a string representing the absolute pathname of a container in
655  *  SALOME_NamingService.
656  * \param params used as it is, or replaced by FactoryServer if empty.
657  * \param hostname name of the host of the container, without domain names.
658  * \return the path under the form /Containers/hostname/containerName
659  * \sa ContainerName(const char *containerName)
660  */
661 // ============================================================================
662
663 std::string
664 SALOME_NamingService::
665 BuildContainerNameForNS(const Engines::ContainerParameters& params,
666                         const char *hostname)
667 {
668   std::string ret = "/Containers/";
669   ret += hostname;
670   ret += "/";
671   ret += ContainerName(params);
672
673   return ret;
674 }
675
676 // ============================================================================
677 /*! \brief search a name in current directory.
678  *
679  *  Search a name in the current directory. after call, the current directory
680  *  is changed to the directory containing the last occurence of name found.
681  *  If no occurence found (see return value), current directory remains
682  *  unchanged.
683  *
684  * \param  name the name to search.
685  * \return number of occurences found.
686  * \sa Change_Directory(const char* Path)
687  */ 
688 // ============================================================================
689
690 int SALOME_NamingService::Find(const char* name)
691 throw(ServiceUnreachable)
692 {
693   MESSAGE("BEGIN OF Find " << name);
694
695   Utils_Locker lock (&_myMutex);
696
697   CORBA::Long occurence_number = 0 ;
698
699   try
700     {
701       _Find(name, occurence_number);
702     }
703
704   catch (CORBA::SystemException&)
705     {
706       INFOS("!!!Find() : CORBA::SystemException : unable to contact"
707             << " the naming service");
708       throw ServiceUnreachable();
709     }
710
711   return occurence_number;
712 }
713
714 // ============================================================================
715 /*! \brief Creates a directory (context_name)
716  *
717  *  Creates a directory (context_name) relative to the current directory 
718  *  (current context) or relative to the root directory (root context), if
719  *  the path given begins with a '/'.
720  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
721  * \param Path   A relative or absolute pathname to store the object reference.
722  *               If the pathname begins with a '/', pathname is taken
723  *               as an absolute pathname. Else, pathname is taken as a relative
724  *               path, to current context. Prefer absolute pathname, relative
725  *               pathname are not safe, when SALOME_NamingService object is
726  *               shared or use in multithreaded context.   
727  *  \return true if successfull
728  *          (creation not strictly garanteed if true, because Register may
729  *           catch some specific unlikely exception without throw anything
730  *           --- to be corrected ---)
731  *  \sa RegisterCORBA::Object_ptr ObjRef, const char* Path)
732  */ 
733 // ============================================================================
734
735 bool SALOME_NamingService::Create_Directory(const char* Path)
736 throw(ServiceUnreachable)
737 {
738   MESSAGE("BEGIN OF Create_Directory");
739
740   Utils_Locker lock (&_myMutex);
741
742   std::string path(Path);
743
744   // --- if path empty, nothing to create, no context change
745
746   if (path.empty())
747     return false;
748
749   // --- if path ='/', nothing to create, only change to root_context
750
751   if (path == "/")
752     {
753       MESSAGE("Create Directory '/', just change to root_context");
754       _current_context = _root_context;
755       return true;
756     }
757
758   // --- path must end with '/'
759   
760   if (path[path.length()-1] != '/') path += '/';
761
762   Register(CORBA::Object::_nil(), path.c_str());
763   return true;
764 }
765
766 // ============================================================================
767 /*! \brief change current directory to the given path
768  *
769  *  change the current directory to the given path in parameter.
770  *  Warning: avoid use when the SALOME_NamingService instance is shared by
771  *  several threads (current context may be modified by another thread).
772  *  If the path is empty, nothing done return OK.
773  *  If Path ="/", the current directory changes to the root directory.
774  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
775  * \param  Path the new current directory
776  * \return true if the change succeeded
777  */ 
778 // ============================================================================
779
780 bool SALOME_NamingService::Change_Directory(const char* Path)
781 throw(ServiceUnreachable)
782 {
783 //   MESSAGE("BEGIN OF Change_Directory " << Path);
784   Utils_Locker lock (&_myMutex);
785
786   std::string path(Path);
787
788   // --- if path empty, nothing to do
789
790   if (path.empty())
791     return true;
792
793   // --- if path ='/', nothing to resolve, only change to root_context
794
795   if (path == "/")
796     {
797 //       MESSAGE("Change_Directory is called to go to the root_context");
798       _current_context = _root_context;
799       return true;
800     }
801
802   CosNaming::NamingContext_var current_context = _current_context;
803   bool changeOK = false;
804
805   // --- replace _current_context with _root_context if Path begins whith '/'
806
807   if (path[0] == '/')
808     current_context = _root_context;
809
810   // --- need to resolve directory path
811
812   ASSERT(!CORBA::is_nil(current_context));
813   
814   if (path[path.length()-1] != '/') path += '/';
815 //   SCRUTE(path);
816   CosNaming::Name context_name;
817   std::vector<std::string> splitPath;
818   _createContextNameDir(path.c_str(),
819                                                  context_name,
820                                                  splitPath,
821                                                  true);
822   
823   // --- Context creation
824   
825   try
826     {
827       CORBA::Object_var obj = current_context->resolve(context_name);
828       current_context = CosNaming::NamingContext::_narrow(obj);
829       ASSERT(!CORBA::is_nil(current_context));
830       _current_context = current_context;
831       changeOK = true;
832     }
833   
834   catch (CosNaming::NamingContext::NotFound& ex)
835     {
836       CosNaming::Name n = ex.rest_of_name;
837       
838       if (ex.why == CosNaming::NamingContext::missing_node)
839         MESSAGE( "Change_Directory() : " << (char *) n[0].id
840                << " (" << (char *) n[0].kind << ") not found");
841       if (ex.why == CosNaming::NamingContext::not_context)
842         INFOS("Change_Directory() : " << (char *) n[0].id
843               << " (" << (char *) n[0].kind
844                   << ") is not a context" );
845       if (ex.why == CosNaming::NamingContext::not_object)
846         INFOS( "Change_Directory() : " << (char *) n[0].id
847                << " (" << (char *) n[0].kind
848                << ") is not an object" );
849     }
850   
851   catch (CosNaming::NamingContext::CannotProceed&)
852     {
853       INFOS("Change_Directory(): CosNaming::NamingContext::CannotProceed");
854     }
855   
856   catch (CosNaming::NamingContext::InvalidName&)
857     {
858       INFOS("Change_Directory(): CosNaming::NamingContext::InvalidName");
859     }
860   
861   catch (CORBA::SystemException&)
862     {
863       INFOS("Change_Directory():CORBA::SystemException : unable to contact"
864             << "the naming service");
865       throw ServiceUnreachable();
866     }
867
868   return changeOK;
869 }
870
871 // ============================================================================
872 /*! \brief get the current directory path
873  *
874  *  Get the current directory path.
875  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
876  * \return the path of the current_context
877  * \sa  _current_directory
878  */ 
879 // ============================================================================
880
881 char* SALOME_NamingService::Current_Directory()
882 throw(ServiceUnreachable)
883 {
884   MESSAGE("BEGIN OF Current_Directory");
885
886   Utils_Locker lock (&_myMutex);
887
888   CosNaming::NamingContext_var ref_context = _current_context;
889
890   std::vector<std::string> splitPath;
891   splitPath.resize(0);
892   int lengthPath = 0;
893   bool notFound = true ;
894
895   // --- start search from root context
896
897   _current_context = _root_context ;
898
899   try
900     {
901       _current_directory(splitPath, lengthPath, ref_context, notFound );
902     }
903
904   catch (CORBA::SystemException&)
905     {
906       INFOS("Current_Directory(): CORBA::SystemException: unable to contact"
907             << " the naming service" )
908       throw ServiceUnreachable();
909     }
910
911   std::string path;
912   lengthPath = splitPath.size();
913   for (int k = 0 ; k < lengthPath ;k++)
914     {
915       path += "/";
916       path += splitPath[k];
917     }
918
919   SCRUTE(path)
920   _current_context = ref_context ;
921
922   return strdup(path.c_str());
923 }
924
925 // ============================================================================
926 /*! \brief list recursively all objects in the current context
927  *
928  *  List and print via trace all directories and objects in the current
929  *  context. Trace must be activated: compile option _DEBUG_
930  *  If the NamingService is out, the exception ServiceUnreachable is thrown
931  */ 
932 // ============================================================================
933
934 void SALOME_NamingService::list()
935 throw(ServiceUnreachable)
936 {
937   MESSAGE("Begin of list");
938
939   Utils_Locker lock (&_myMutex)
940
941     ;
942   CosNaming::BindingList_var binding_list;
943   CosNaming::BindingIterator_var binding_iterator;
944   CosNaming::Binding_var binding ;
945
946   unsigned long nb = 0 ; // --- only for the BindingIterator use,
947                          //     to access the bindings
948
949   CosNaming::NamingContext_var ref_context = _current_context;
950
951   _current_context->list(nb, binding_list, binding_iterator) ;
952
953   if (! CORBA::is_nil(binding_iterator))
954     {
955       while (binding_iterator->next_one(binding))
956         {
957           CosNaming::Name bindingName = binding->binding_name;
958
959           if (binding->binding_type == CosNaming::ncontext)
960             {
961               MESSAGE( "Context : " << bindingName[0].id );
962
963               try
964                 {
965                   Change_Directory(bindingName[0].id);
966                 }
967
968               catch (ServiceUnreachable&)
969                 {
970                   INFOS( "list(): ServiceUnreachable" )
971                     throw ServiceUnreachable();
972                 }
973
974               list();
975               _current_context = ref_context ;
976             }
977
978           else if (binding->binding_type == CosNaming::nobject)
979             {
980               MESSAGE( "Object : " << bindingName[0].id );
981             }
982         }
983
984       binding_iterator->destroy();
985     }
986 }
987
988 // ============================================================================
989 /*! \brief list all the objects in the current directory.
990  *
991  *  get a list of all the objects in the current directory, without recursion
992  *  on the subdirectories. Only the objects are listed, not the directories.
993  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
994  * \return list of strings with objects found.
995  * \sa vector<string> list_directory_recurs()
996  */ 
997 // ============================================================================
998
999 std::vector<std::string> SALOME_NamingService::list_directory()
1000 throw(ServiceUnreachable)
1001 {
1002 //   MESSAGE("list_directory");
1003   std::vector<std::string> dirList ;
1004   dirList.resize(0);
1005
1006   CosNaming::BindingList_var binding_list;
1007   CosNaming::BindingIterator_var binding_iterator;
1008   CosNaming::Binding_var binding ;
1009
1010   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1011                          //     to access the bindings
1012
1013   CosNaming::NamingContext_var ref_context = _current_context;
1014
1015   _current_context->list(nb, binding_list, binding_iterator);
1016
1017   if (binding_iterator->_is_nil())
1018     return dirList;
1019
1020   while (binding_iterator->next_one(binding))
1021     {
1022       CosNaming::Name bindingName = binding->binding_name;
1023
1024       if (binding->binding_type == CosNaming::nobject)
1025         {
1026           // remove memory leak
1027           // dirList.push_back(CORBA::string_dup(bindingName[0].id));
1028           dirList.push_back(std::string(bindingName[0].id));
1029         }
1030     }
1031
1032 //   for (unsigned int ind = 0; ind < dirList.size(); ind++)
1033 //     MESSAGE("list_directory : Object : " << dirList[ind]);
1034
1035   binding_iterator->destroy();
1036
1037   return dirList;
1038 }
1039
1040
1041 // ============================================================================
1042 /*! \brief list all the subdirectories in the current directory.
1043  *
1044  *  get a list of all the subdirectories in the current directory,
1045  *  without recursion on the subdirectories.
1046  *  Only the subdirectories are listed, not the objects.
1047  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1048  * \return list of strings with directories found.
1049  * \sa vector<string> list_directory()
1050  */ 
1051 // ============================================================================
1052
1053 std::vector<std::string> SALOME_NamingService::list_subdirs()
1054 throw(ServiceUnreachable)
1055 {
1056   MESSAGE("list_subdirs");
1057   std::vector<std::string> dirList ;
1058   dirList.resize(0);
1059
1060   CosNaming::BindingList_var binding_list;
1061   CosNaming::BindingIterator_var binding_iterator;
1062   CosNaming::Binding_var binding ;
1063
1064   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1065                          //     to access the bindings
1066
1067   CosNaming::NamingContext_var ref_context = _current_context;
1068
1069   _current_context->list(nb, binding_list, binding_iterator) ;
1070
1071   if (binding_iterator->_is_nil())
1072     return dirList;
1073
1074   while (binding_iterator->next_one(binding))
1075     {
1076       CosNaming::Name bindingName = binding->binding_name;
1077
1078       if (binding->binding_type == CosNaming::ncontext)
1079         {
1080           dirList.push_back(bindingName[0].id.in());
1081         }
1082     }
1083
1084   for (unsigned int ind = 0; ind < dirList.size(); ind++)
1085     MESSAGE("list_directory : Object : " << dirList[ind]);
1086
1087   binding_iterator->destroy();
1088
1089   return dirList;
1090 }
1091
1092 // ============================================================================
1093 /*! \brief  list all the objects in the current directory and subdirectories.
1094  *
1095  *  get a list of all the objects in the current directory, with recursion
1096  *  on the subdirectories. Only the objects are listed, not the directories.
1097  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1098  * \return list of strings with objects found.
1099  * \sa vector<string> list_directory()
1100  */ 
1101 // ============================================================================
1102
1103 std::vector<std::string> SALOME_NamingService::list_directory_recurs()
1104 throw(ServiceUnreachable)
1105 {
1106   MESSAGE("list_directory_recurs");
1107
1108   Utils_Locker lock (&_myMutex);
1109
1110   std::vector<std::string> dirList ;
1111
1112   char* currentDir = Current_Directory();
1113
1114   _list_directory_recurs(dirList, "", currentDir);
1115
1116   free(currentDir);
1117
1118   return dirList;
1119 }
1120
1121 // ============================================================================
1122 /*! \brief destroy an entry in naming service.
1123  *
1124  *  Destroy an association Path - Object Reference.
1125  *  If the NamingService is out, the exception ServiceUnreachable is thrown 
1126  * \param Path object path
1127  */ 
1128 // ============================================================================
1129
1130 void SALOME_NamingService::Destroy_Name(const char* Path)
1131 throw(ServiceUnreachable)
1132 {
1133   MESSAGE("BEGIN OF Destroy_Name " << Path);
1134
1135   Utils_Locker lock (&_myMutex);
1136
1137   std::string path(Path);
1138
1139   // --- if path empty, nothing to do
1140
1141   if (path.empty())
1142     return;
1143
1144   // --- if path = '/' not applicable, nothing to do
1145
1146   if (path == "/")
1147     return;
1148
1149   // --- if path begins with '/', set current directory to root context
1150
1151   if (path[0] == '/')
1152     _current_context = _root_context;
1153
1154   // --- context of the directory containing the object
1155
1156   CosNaming::Name context_name;
1157   std::vector<std::string> splitPath;
1158   int dimension_resultat = _createContextNameDir(path.c_str(),
1159                                                  context_name,
1160                                                  splitPath,
1161                                                  true);
1162
1163   bool exist = false;
1164
1165   if (dimension_resultat > 0)
1166     {
1167       // --- path contains a directory, not only an object name
1168       //     switch to the new directory (or return if directory not found)
1169
1170       try
1171         {
1172           CORBA::Object_var obj = _current_context->resolve(context_name);
1173           _current_context = CosNaming::NamingContext::_narrow(obj);
1174           exist = true;
1175         }
1176
1177       catch (CosNaming::NamingContext::NotFound &ex)
1178         {
1179           // --- failed to resolve
1180           exist = false;
1181
1182           CosNaming::Name n = ex.rest_of_name;
1183
1184           if (ex.why == CosNaming::NamingContext::missing_node)
1185             INFOS( "Destroy_Name(): " << (char *) n[0].id
1186                    << " (" << (char *) n[0].kind << ") not found" );
1187           if (ex.why == CosNaming::NamingContext::not_context)
1188             INFOS( "Destroy_Name() : " << (char *) n[0].id
1189                    << " (" << (char *) n[0].kind
1190                    << ") is not a context" );
1191           if (ex.why == CosNaming::NamingContext::not_object)
1192             INFOS( "Destroy_Name() : " << (char *) n[0].id
1193                    << " (" << (char *) n[0].kind
1194                    << ") is not an object" );
1195         }
1196
1197       catch (CosNaming::NamingContext::InvalidName &)
1198         {
1199           INFOS("Destroy_Name: CosNaming::NamingContext::InvalidName");
1200         }
1201
1202       catch (CosNaming::NamingContext::CannotProceed &)
1203         {
1204           INFOS("Destroy_Name: CosNaming::NamingContext::CannotProceed");
1205         }
1206
1207       catch (CORBA::SystemException&)
1208         {
1209           INFOS("Destroy_Name : CORBA::SystemException: "
1210                 << "unable to contact the naming service");
1211           throw ServiceUnreachable();
1212         }
1213
1214       if (! exist) return;
1215     }
1216
1217   ASSERT(!CORBA::is_nil(_current_context));
1218
1219   // --- The current directory is now the directory where the object should
1220   //     be destroyed
1221
1222   int sizePath = splitPath.size();
1223   if (sizePath > dimension_resultat)
1224     {
1225       ASSERT(sizePath == dimension_resultat+1);
1226       context_name.length(1);
1227
1228       try
1229         {
1230           // --- the last element is an object and not a directory
1231
1232           context_name[0].id =
1233             CORBA::string_dup(splitPath[dimension_resultat].c_str());
1234           context_name[0].kind = CORBA::string_dup("object");
1235           SCRUTE(context_name[0].id);
1236  
1237           _current_context->unbind(context_name);
1238           MESSAGE("The object " << context_name[0].id << " has been deleted");
1239         }
1240
1241       catch (CosNaming::NamingContext::NotFound& ex)
1242         {
1243           CosNaming::Name n = ex.rest_of_name;
1244
1245           if (ex.why == CosNaming::NamingContext::missing_node)
1246             INFOS( "Destroy_Name() : " << (char *) n[0].id
1247                    << " (" << (char *) n[0].kind << ") not found" );
1248           if (ex.why == CosNaming::NamingContext::not_context)
1249             INFOS( "Destroy_Name() : " << (char *) n[0].id
1250                    << " (" << (char *) n[0].kind
1251                    << ") is not a context" );
1252           if (ex.why == CosNaming::NamingContext::not_object)
1253             INFOS( "Destroy_Name() : " << (char *) n[0].id
1254                    << " (" << (char *) n[0].kind
1255                    << ") is not an object" );
1256           }
1257
1258       catch (CosNaming::NamingContext::CannotProceed&)
1259         {
1260           INFOS( "Destroy_Name(): CosNaming::NamingContext::CannotProceed");
1261         }
1262
1263       catch (CosNaming::NamingContext::InvalidName&)
1264         {
1265           INFOS( "Destroy_Name(): CosNaming::NamingContext::InvalidName");
1266         }
1267
1268       catch (CORBA::SystemException&)
1269         {
1270           INFOS( "Destroy_Name(): CORBA::SystemException: unable to contact"
1271                  << " the naming service");
1272           throw ServiceUnreachable();
1273         }
1274     }
1275 }
1276
1277 // ============================================================================
1278 /*! \brief Destroy an empty directory
1279  *
1280  *  Destroy an empty directory in Naming Service.
1281  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1282  * \param Path directory path
1283  */ 
1284 // ============================================================================
1285
1286 void SALOME_NamingService::Destroy_Directory(const char* Path)
1287 throw(ServiceUnreachable)
1288 {
1289   MESSAGE("BEGIN OF Destroy_Directory " << Path);
1290
1291   Utils_Locker lock (&_myMutex);
1292
1293   std::string path(Path);
1294
1295   // --- if path empty, nothing to do
1296
1297   if (path.empty())
1298     return;
1299
1300   // --- if path begins with '/', set current directory to root context
1301
1302   if (path[0] == '/')
1303     _current_context = _root_context;
1304
1305   CosNaming::NamingContext_var ref_context = _current_context;
1306
1307   // --- path must ends with '/' for a directory
1308
1309   if (path[path.size() -1] != '/')
1310     path += '/';
1311
1312   // --- context of the directory
1313
1314   CosNaming::Name context_name;
1315   std::vector<std::string> splitPath;
1316   int dimension_resultat = _createContextNameDir(path.c_str(),
1317                                                  context_name,
1318                                                  splitPath,
1319                                                  true);
1320   bool exist = false;
1321
1322   if (dimension_resultat > 0)
1323     {
1324       // --- path contains a directory, not only an object name
1325       //     switch to the new directory (or return if directory not found)
1326
1327       try
1328         {
1329           CORBA::Object_var obj = _current_context->resolve(context_name);
1330           _current_context = CosNaming::NamingContext::_narrow(obj);
1331           exist = true;
1332         }
1333
1334       catch (CosNaming::NamingContext::NotFound &ex)
1335         {
1336           // --- failed to resolve
1337           exist = false;
1338
1339           CosNaming::Name n = ex.rest_of_name;
1340
1341           if (ex.why == CosNaming::NamingContext::missing_node)
1342             INFOS( "Destroy_Directory(): " << (char *) n[0].id
1343                    << " (" << (char *) n[0].kind << ") not found" );
1344           if (ex.why == CosNaming::NamingContext::not_context)
1345             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1346                    << " (" << (char *) n[0].kind
1347                    << ") is not a context" );
1348           if (ex.why == CosNaming::NamingContext::not_object)
1349             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1350                    << " (" << (char *) n[0].kind
1351                    << ") is not an object" );
1352         }
1353
1354       catch (CosNaming::NamingContext::InvalidName &)
1355         {
1356           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1357         }
1358
1359       catch (CosNaming::NamingContext::CannotProceed &)
1360         {
1361           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1362         }
1363
1364       catch (CORBA::SystemException&)
1365         {
1366           INFOS("Destroy_Directory : CORBA::SystemException: "
1367                 << "unable to contact the naming service");
1368           throw ServiceUnreachable();
1369         }
1370
1371       if (! exist) return;
1372     }
1373
1374   ASSERT(!CORBA::is_nil(_current_context));
1375
1376   // --- Context Destruction
1377
1378   bool isContextDestroyed = false;
1379   try
1380     {
1381       _current_context->destroy();
1382       MESSAGE( "The context " << path << " has been deleted" );
1383       isContextDestroyed = true;
1384     }
1385
1386   catch (CosNaming::NamingContext::NotEmpty&)
1387     {
1388       INFOS( "Destroy_Directory(): CosNaming::NamingContext::NoEmpty "
1389              << path << " is not empty" );
1390     }
1391
1392   catch (CORBA::SystemException&)
1393     {
1394       INFOS( "Destroy_Directory():CORBA::SystemException : "
1395              << "unable to contact the naming service");
1396       throw ServiceUnreachable();
1397     }
1398
1399   // --- go to the reference directory
1400
1401   _current_context = ref_context ;
1402
1403   ASSERT(!CORBA::is_nil(_current_context));
1404
1405   if (isContextDestroyed)
1406     {
1407       try
1408         {
1409           _current_context->unbind(context_name);
1410           MESSAGE( "The bind to the context "
1411                    << context_name[0].id
1412                    << " has been deleted" );
1413         }
1414
1415       catch (CosNaming::NamingContext::NotFound& ex)
1416         {
1417           CosNaming::Name n = ex.rest_of_name;
1418
1419           if (ex.why == CosNaming::NamingContext::missing_node)
1420             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1421                    << " (" << (char *) n[0].kind << ") not found" );
1422           if (ex.why == CosNaming::NamingContext::not_context)
1423             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1424                    << " (" << (char *) n[0].kind
1425                    << ") is not a context" );
1426           if (ex.why == CosNaming::NamingContext::not_object)
1427             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1428                    << " (" << (char *) n[0].kind
1429                    << ") is not an object" );
1430         }
1431
1432       catch (CosNaming::NamingContext::CannotProceed&)
1433         {
1434           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1435         }
1436
1437       catch (CosNaming::NamingContext::InvalidName&)
1438         {
1439           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1440             }
1441
1442       catch (CORBA::SystemException&)
1443         {
1444           INFOS("Destroy_Directory:CORBA::SystemException : unable to contact"
1445                  << " the naming service");
1446           throw ServiceUnreachable();
1447         }
1448     }
1449 }
1450
1451 // ============================================================================
1452 /*! \brief Destroy a directory with its contents.
1453  *
1454  *  Destroy the objects associations in a directory, and the directory itself,
1455  *  if there is no subdirectories. 
1456  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1457  * \param Path the directory path.
1458  */ 
1459 // ============================================================================
1460
1461 void SALOME_NamingService::Destroy_FullDirectory(const char* Path)
1462 throw(ServiceUnreachable)
1463 {
1464   MESSAGE("begin of Destroy_FullDirectory " << Path);
1465   if( Change_Directory(Path) )
1466     {
1467       std::vector<std::string> contList = list_directory();
1468
1469       for (unsigned int ind = 0; ind < contList.size(); ind++)
1470         Destroy_Name(contList[ind].c_str());
1471       
1472       Destroy_Directory(Path);
1473     }
1474 }
1475
1476 // ============================================================================
1477 /*! \brief  initialize root context (root directory)
1478  *
1479  * the root context initialisation must be done when the SALOME_NamingService
1480  * instance is created and before any othe call. See constructors.
1481  */ 
1482 // ============================================================================
1483
1484 void SALOME_NamingService::_initialize_root_context()
1485 {
1486   //MESSAGE("Get the root context");
1487
1488   try
1489     {
1490       CORBA::Object_var obj = _orb->resolve_initial_references("NameService");
1491       _root_context = CosNaming::NamingContext::_narrow(obj);
1492       _current_context = _root_context ;
1493       ASSERT(!CORBA::is_nil(_root_context));
1494     }
1495
1496   catch (CORBA::SystemException&)
1497     {
1498       INFOS("CORBA::SystemException: unable to contact the naming service");
1499       throw ServiceUnreachable();
1500     }
1501
1502   catch (...)
1503     {
1504       INFOS("Unknown Exception: unable to contact the naming service");
1505       throw ServiceUnreachable();
1506     }
1507 }
1508
1509 // ============================================================================
1510 /*! \brief transform a string path in CosNaming structure.
1511  *
1512  *  Transform a path given as a string in a CosNaming structure.
1513  *  \param path         a relative or absolute path, with or without an object.
1514  *                      An absolute path begins with '/'.
1515  *                      A path without an object ends with '/'.
1516  *  \param context_name CosNaming structure to put the path.
1517  *  \param splitPath    a vector of string with subdirectories and final
1518  *                      object, if any.
1519  *  \param onlyDir      if true, final object (if any) is ommited
1520  *                      in context_name.
1521  *                      if false, final object (if any) is included in
1522  *                      context_name.
1523  *  \return             dimension of context_name
1524  */ 
1525 // ============================================================================
1526
1527 int
1528 SALOME_NamingService::_createContextNameDir(std::string path,
1529                                             CosNaming::Name& context_name,
1530                                             std::vector<std::string>& splitPath,
1531                                             bool onlyDir)
1532 {
1533   if (path.empty())
1534     return 0;
1535
1536   std::string::size_type begIdx, endIdx;
1537   const std::string delims("/");
1538   splitPath.resize(0);
1539   bool endWithDelim = false;
1540
1541   begIdx = path.find_first_not_of(delims);
1542   while (begIdx != std::string::npos)
1543     {
1544       endIdx = path.find_first_of(delims, begIdx);
1545       if (endIdx == path.length()-1)
1546         endWithDelim = true;
1547       if (endIdx == std::string::npos)
1548         endIdx = path.length();
1549       int lsub = endIdx - begIdx;
1550       if (lsub >= 1)
1551         splitPath.push_back(path.substr(begIdx, lsub));
1552       begIdx = path.find_first_not_of(delims, endIdx);
1553     }
1554
1555   int dim;
1556   if (onlyDir)                  // only directory part
1557     {
1558       dim = splitPath.size()-1; // omit final object
1559       if (endWithDelim)         // unless the path ends with a delimiter 
1560         dim++;
1561       endWithDelim = true;
1562     }
1563   else
1564     dim = splitPath.size();     // directories and final object
1565
1566   context_name.length(dim);
1567   for (int i=0; i<dim; i++)
1568     {
1569 //       SCRUTE(splitPath[i]);
1570       context_name[i].id = CORBA::string_dup(splitPath[i].c_str());
1571       if (!endWithDelim && (i == dim-1)) // here, the last string is an object
1572         {
1573           context_name[i].kind = CORBA::string_dup("object");
1574 //        MESSAGE("--- " <<splitPath[i] <<".object");
1575         }
1576       else
1577         {
1578           context_name[i].kind = CORBA::string_dup("dir");
1579 //        MESSAGE("--- " <<splitPath[i] <<".dir");
1580         }
1581     }
1582   return dim;
1583 }
1584
1585 // ============================================================================
1586 /*! \brief search a name in current directory.
1587  *
1588  *  Search a name in the current directory. after call, the current directory
1589  *  is changed to the directory containing the last occurence of name found.
1590  *  If no occurence found (see return value), current directory remains
1591  *  unchanged. The call is recursive.
1592  *
1593  * \param  name the name to search.
1594  * \param  occurence_number number of occurence already found (incremented)
1595  */ 
1596 // ============================================================================
1597
1598 void SALOME_NamingService::_Find(const char* name,
1599                                  CORBA::Long& occurence_number)
1600 {
1601   MESSAGE("BEGIN OF _Find "<<  occurence_number << " " << name);
1602
1603   CosNaming::BindingList_var binding_list;
1604   CosNaming::BindingIterator_var binding_iterator;
1605   CosNaming::Binding_var binding;
1606
1607   unsigned long nb = 0 ; // --- only for the use of the BindingIterator,
1608                          //     to access the bindings
1609
1610   CosNaming::NamingContext_var ref_context = _current_context;
1611   CosNaming::NamingContext_var found_context = _current_context;
1612
1613   _current_context->list(nb, binding_list, binding_iterator) ;
1614
1615   if (! CORBA::is_nil(binding_iterator))
1616     {
1617       while (binding_iterator->next_one(binding))
1618         {
1619           CosNaming::Name bindingName = binding->binding_name;
1620           
1621           if (binding->binding_type == CosNaming::ncontext)
1622             {
1623               // --- We work on a directory,
1624               //     the search should be done in this directory
1625               
1626               Change_Directory(bindingName[0].id);
1627               _Find(name, occurence_number);
1628               
1629               // --- We'll go back to the initial context
1630               
1631               _current_context = ref_context ;
1632             }
1633           
1634           else if (binding->binding_type == CosNaming::nobject)
1635             {
1636               // --- We work on an object...
1637               
1638               if (!strcmp( bindingName[0].id, name))
1639                 {
1640                   //MESSAGE("One occurence was found");
1641                   occurence_number++;
1642                   
1643                   // --- We keep in memory the directory where
1644                   //     one occurence was found
1645                   
1646                   found_context = _current_context ;
1647                 }
1648             }
1649         }
1650       
1651       binding_iterator->destroy();
1652     }
1653   // --- We go to the last directory where an occurence was found
1654
1655   _current_context = found_context;
1656
1657   SCRUTE(occurence_number);
1658 }
1659
1660 // ============================================================================
1661 /*! \brief find the current directory path.
1662  * 
1663  *  Parse the naming service tree to find the current context and give the
1664  *  associated directory path (relative to root context).
1665  * \param splitPath 
1666  * \param lengthResult
1667  * \param contextToFind
1668  * \param notFound
1669  */ 
1670 // ============================================================================
1671
1672 void
1673 SALOME_NamingService::
1674 _current_directory(std::vector<std::string>& splitPath,
1675                    int& lengthResult,
1676                    CosNaming::NamingContext_var contextToFind,
1677                    bool& notFound)
1678 {
1679   MESSAGE("BEGIN OF _current_Directory");
1680
1681   CosNaming::BindingList_var binding_list;
1682   CosNaming::BindingIterator_var binding_iterator;
1683   CosNaming::Binding_var binding;
1684
1685   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1686                          //     to access the bindings
1687
1688   CosNaming::NamingContext_var ref_context = _current_context;
1689   CosNaming::NamingContext_var temp_context = _current_context;
1690
1691   _current_context->list(nb, binding_list, binding_iterator);
1692
1693   if ( !binding_iterator->_is_nil() )
1694     {
1695       while ((binding_iterator->next_one(binding)) && notFound)
1696         {
1697           CosNaming::Name bindingName = binding->binding_name;
1698
1699           if (binding->binding_type == CosNaming::ncontext)
1700             {
1701               // --- directory, search in it
1702
1703               const char* bindingNameid=bindingName[0].id;
1704               splitPath.push_back(bindingNameid);
1705               lengthResult++;
1706
1707               CORBA::Object_var obj = _current_context->resolve(bindingName);
1708               temp_context = CosNaming::NamingContext::_narrow(obj);
1709
1710               if (temp_context->_is_equivalent(contextToFind))
1711                 {
1712                   MESSAGE("The context is found, we stop the search");
1713                   notFound = false;
1714                   SCRUTE(notFound);
1715                 }
1716
1717               if (notFound)
1718                 {
1719                   SCRUTE(bindingName[0].id);
1720                   Change_Directory(bindingName[0].id);
1721                   _current_directory(splitPath,
1722                                      lengthResult,
1723                                      contextToFind,
1724                                      notFound);
1725
1726                   if (notFound)
1727                     {
1728                       // --- go back to the initial context
1729
1730                       _current_context = ref_context;
1731
1732                       MESSAGE("Just before the delete of "
1733                               << splitPath[lengthResult-1]);
1734                       splitPath.pop_back();
1735                       lengthResult--;
1736                     }
1737                 }
1738             }
1739         }
1740
1741       binding_iterator->destroy();
1742     }
1743
1744   // --- return to the last directory where an occurence was found
1745
1746   _current_context = ref_context ;
1747 }
1748
1749
1750 // ============================================================================
1751 /*! \brief list recursively all objects in the given directory and subdirs.
1752  *
1753  *  get a list of all the objects in the current directory, with recursion
1754  *  on the subdirectories. Only the objects are listed, not the directories.
1755  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1756  *  _current_context must refer to absCurDirectory.
1757  *
1758  *  \param myList          The list that will be filled.
1759  *  \param relativeSubDir  The directory relative to absCurDirectory in which
1760  *                         the objects are found.
1761  *  \param absCurDirectory The current directory, absolute path
1762  */ 
1763 // ============================================================================
1764
1765 void SALOME_NamingService::_list_directory_recurs(std::vector<std::string>& myList,
1766                                                   std::string relativeSubDir,
1767                                                   std::string absCurDirectory)
1768 {
1769   CosNaming::BindingList_var binding_list;
1770   CosNaming::BindingIterator_var binding_iterator;
1771   CosNaming::Binding_var binding ;
1772
1773   unsigned long nb = 0 ; // --- only for thethe use of BindingIterator
1774                          //     to access the bindings
1775
1776   std::string absDir;
1777
1778   CosNaming::NamingContext_var ref_context = _current_context;
1779
1780   if (! relativeSubDir.empty())
1781     {
1782       Change_Directory(relativeSubDir.c_str());
1783       absDir = absCurDirectory + "/" + relativeSubDir;
1784     }
1785
1786   else
1787     absDir = absCurDirectory;
1788
1789   SCRUTE(absDir);
1790   _current_context->list(nb, binding_list, binding_iterator) ;
1791
1792   if (! CORBA::is_nil(binding_iterator))
1793     {
1794       while (binding_iterator->next_one(binding))
1795         {
1796           CosNaming::Name bindingName = binding->binding_name;
1797
1798           if (binding->binding_type == CosNaming::ncontext)
1799             {
1800               std::string relativeSdir(bindingName[0].id);
1801               _list_directory_recurs(myList, relativeSdir, absDir);
1802             }
1803
1804           else if (binding->binding_type == CosNaming::nobject)
1805             {
1806               std::string objName(bindingName[0].id);
1807               std::string elt = absDir + "/" + objName;
1808               SCRUTE(elt);
1809               myList.push_back(elt);
1810             }
1811         }
1812
1813       binding_iterator->destroy();
1814     }
1815   if (! relativeSubDir.empty())
1816     {
1817       _current_context = ref_context;
1818     }
1819 }
1820
1821 // ============================================================================
1822 /*! \brief return a stringified reference of root context
1823  *
1824  * \return a stringified reference of root context
1825  */
1826 // ============================================================================
1827
1828 char * SALOME_NamingService::getIORaddr()
1829 {
1830   return _orb->object_to_string(_root_context);
1831 }
1832
1833 /*! \brief get the orb used by the naming service
1834  *
1835  *  \return the orb
1836  */
1837 CORBA::ORB_ptr SALOME_NamingService::orb()
1838 {
1839   return _orb;
1840 }
1841