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