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