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