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