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