Salome HOME
Issue 0020194: EDF 977 ALL: Get rid of warnings PACKAGE_VERSION already defined
[modules/kernel.git] / src / NamingService / SALOME_NamingService.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SALOME NamingService : wrapping NamingService services
23 //  File   : SALOME_NamingService.cxx
24 //  Author : Estelle Deville
25 //  Module : SALOME
26 //  $Header$
27 //
28 #include "SALOME_NamingService.hxx"
29 #include "ServiceUnreachable.hxx"
30
31 #include "utilities.h"
32
33 #include <iostream>
34 #include <cstring>
35 #include <string>
36
37 using namespace std;
38
39 /*! \class SALOME_NamingService
40     \brief A class to manage the SALOME naming service
41
42 */
43
44 // ============================================================================
45 /*! \brief Default Constructor without ORB reference.
46  *
47  *  After Default Constructor, one needs to initialize ORB.
48  *  \sa init_orb(CORBA::ORB_ptr orb), SALOME_NamingService(CORBA::ORB_ptr orb)
49  */ 
50 // ============================================================================
51
52 SALOME_NamingService::SALOME_NamingService()
53 {
54   MESSAGE("SALOME_NamingService default constructor");
55   _orb = CORBA::ORB::_nil();
56   _root_context = CosNaming::NamingContext::_nil();
57 }
58
59 // ============================================================================
60 /*! \brief Standard Constructor, with ORB reference. 
61  * 
62  * Initializes the naming service root context
63  * \param orb CORBA::ORB_ptr arguments
64  */ 
65 // ============================================================================
66
67 SALOME_NamingService::SALOME_NamingService(CORBA::ORB_ptr orb)
68 {
69   MESSAGE("SALOME_NamingService creation");
70   _orb = CORBA::ORB::_duplicate(orb);
71   _initialize_root_context();
72 }
73
74 // ============================================================================
75 /*! \brief Standard destructor.
76  *
77  *  The standard destructor does nothing special.
78  */ 
79 // ============================================================================
80
81 SALOME_NamingService::~SALOME_NamingService()
82 {
83   // Problem MESSAGE with singleton: late destruction,
84   // after trace system destruction ?
85   //MESSAGE("SALOME_NamingService destruction");
86 }
87
88 // ============================================================================
89 /*! \brief initializes ORB reference and naming service root context.
90  * 
91  *  Initializes ORB reference and naming service root context.
92  *  For use after default constructor.
93  *  \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 = CORBA::ORB::_duplicate(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       string basename = name;
522       if (Change_Directory(basename.c_str()))
523         {
524           vector<string> contList = list_subdirs();
525
526           for (unsigned int ind = 0; ind < contList.size(); ind++)
527             {
528               name = contList[ind].c_str();
529
530               if ( nbproc >= 1 )
531                 {
532                   char *str_nbproc = new char[8];
533                   sprintf(str_nbproc, "_%d", nbproc);
534                   if( strstr(name.c_str(),str_nbproc) == NULL)
535                     continue; // check only containers with _%d in name
536                   delete [] str_nbproc;
537                 }
538
539               name += "/";
540               name += componentName;
541               SCRUTE(name);
542               CORBA::Object_ptr obj = ResolveFirst(name.c_str());
543
544               if ( !CORBA::is_nil(obj) )
545                 return obj;
546               else
547                 Change_Directory(basename.c_str());
548             }
549         }
550
551       return CORBA::Object::_nil();
552     }
553 }
554
555 // ============================================================================
556 /*! \brief provide a default container name if empty.
557  *
558  *  the given container name is returned unchanged, unless it is empty.
559  * \param  containerName
560  * \return container name, where empty input is replaced by "FactoryServer",
561  *         without the path.
562  * \sa BuildContainerNameForNS(const char *containerName, const char *hostname)
563  */
564 // ============================================================================
565
566 string SALOME_NamingService::ContainerName(const char *containerName)
567 {
568   string ret;
569
570   if (strlen(containerName) == 0)
571     ret = "FactoryServer";
572   else
573     ret = containerName;
574
575   return ret;
576 }
577
578 // ============================================================================
579 /*! \brief build a container name, given a MachineParameters struct.
580  *
581  *  Build a container name with a MachineParameters struct. In case of multi
582  *  processor machine, container name is suffixed with _nbproc. nproc equals
583  *  (number of nodes)*(number of processor per nodes).
584  * \param params struct from which we get container name (may be
585  *               empty),  number of nodes and number of processor
586  *               per node.
587  * \return a container name without the path.
588  * \sa BuildContainerNameForNS(const Engines::MachineParameters& params,
589  *                             const char *hostname)
590  */
591 // ============================================================================
592
593 string 
594 SALOME_NamingService::ContainerName(const Engines::MachineParameters& params)
595 {
596   int nbproc;
597
598   if ( !params.isMPI )
599     nbproc = 0;
600   else if ( (params.nb_node <= 0) && (params.nb_proc_per_node <= 0) )
601     nbproc = 1;
602   else if ( params.nb_node == 0 )
603     nbproc = params.nb_proc_per_node;
604   else if ( params.nb_proc_per_node == 0 )
605     nbproc = params.nb_node;
606   else
607     nbproc = params.nb_node * params.nb_proc_per_node;
608
609   string ret = ContainerName(params.container_name);
610
611   if ( nbproc >= 1 )
612     {
613       char *suffix = new char[8];
614       sprintf(suffix, "_%d", nbproc);
615       ret += suffix;
616     }
617
618   return ret;
619 }
620
621 // ============================================================================
622 /*! \brief build a string representing a container in Naming Service.
623  *
624  *  Build a string representing the absolute pathname of a container in
625  *  SALOME_NamingService. This form gives a suffixed containerName in case of
626  *  multi processor machine.
627  * \param containerName name of the container in which the component is
628                         instanciated.
629  * \param hostname name of the host of the container, without domain names.
630  * \return the path under the form /Containers/hostname/containerName
631  * \sa ContainerName(const Engines::MachineParameters& params)
632  */
633 // ============================================================================
634
635 string SALOME_NamingService::BuildContainerNameForNS(const char *containerName,
636                                                      const char *hostname)
637 {
638   string ret = "/Containers/";
639   ret += hostname;
640   ret += "/";
641   ret += ContainerName(containerName);
642
643   return ret;
644 }
645
646 // ============================================================================
647 /*! \brief build a string representing a container in Naming Service.
648  *
649  *  Build a string representing the absolute pathname of a container in
650  *  SALOME_NamingService.
651  * \param params used as it is, or replaced by FactoryServer if empty.
652  * \param hostname name of the host of the container, without domain names.
653  * \return the path under the form /Containers/hostname/containerName
654  * \sa ContainerName(const char *containerName)
655  */
656 // ============================================================================
657
658 string
659 SALOME_NamingService::
660 BuildContainerNameForNS(const Engines::MachineParameters& params,
661                         const char *hostname)
662 {
663   string ret = "/Containers/";
664   ret += hostname;
665   ret += "/";
666   ret += ContainerName(params);
667
668   return ret;
669 }
670
671 // ============================================================================
672 /*! \brief search a name in current directory.
673  *
674  *  Search a name in the current directory. after call, the current directory
675  *  is changed to the directory containing the last occurence of name found.
676  *  If no occurence found (see return value), current directory remains
677  *  unchanged.
678  *
679  * \param  name the name to search.
680  * \return number of occurences found.
681  * \sa Change_Directory(const char* Path)
682  */ 
683 // ============================================================================
684
685 int SALOME_NamingService::Find(const char* name)
686 throw(ServiceUnreachable)
687 {
688   MESSAGE("BEGIN OF Find " << name);
689
690   Utils_Locker lock (&_myMutex);
691
692   CORBA::Long occurence_number = 0 ;
693
694   try
695     {
696       _Find(name, occurence_number);
697     }
698
699   catch (CORBA::SystemException&)
700     {
701       INFOS("!!!Find() : CORBA::SystemException : unable to contact"
702             << " the naming service");
703       throw ServiceUnreachable();
704     }
705
706   return occurence_number;
707 }
708
709 // ============================================================================
710 /*! \brief Creates a directory (context_name)
711  *
712  *  Creates a directory (context_name) relative to the current directory 
713  *  (current context) or relative to the root directory (root context), if
714  *  the path given begins with a '/'.
715  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
716  * \param Path   A relative or absolute pathname to store the object reference.
717  *               If the pathname begins with a '/', pathname is taken
718  *               as an absolute pathname. Else, pathname is taken as a relative
719  *               path, to current context. Prefer absolute pathname, relative
720  *               pathname are not safe, when SALOME_NamingService object is
721  *               shared or use in multithreaded context.   
722  *  \return true if successfull
723  *          (creation not strictly garanteed if true, because Register may
724  *           catch some specific unlikely exception without throw anything
725  *           --- to be corrected ---)
726  *  \sa RegisterCORBA::Object_ptr ObjRef, const char* Path)
727  */ 
728 // ============================================================================
729
730 bool SALOME_NamingService::Create_Directory(const char* Path)
731 throw(ServiceUnreachable)
732 {
733   MESSAGE("BEGIN OF Create_Directory");
734
735   Utils_Locker lock (&_myMutex);
736
737   string path(Path);
738
739   // --- if path empty, nothing to create, no context change
740
741   if (path.empty())
742     return false;
743
744   // --- if path ='/', nothing to create, only change to root_context
745
746   if (path == "/")
747     {
748       MESSAGE("Create Directory '/', just change to root_context");
749       _current_context = _root_context;
750       return true;
751     }
752
753   // --- path must end with '/'
754   
755   if (path[path.length()-1] != '/') path += '/';
756
757   Register(CORBA::Object::_nil(), path.c_str());
758   return true;
759 }
760
761 // ============================================================================
762 /*! \brief change current directory to the given path
763  *
764  *  change the current directory to the given path in parameter.
765  *  Warning: avoid use when the SALOME_NamingService instance is shared by
766  *  several threads (current context may be modified by another thread).
767  *  If the path is empty, nothing done return OK.
768  *  If Path ="/", the current directory changes to the root directory.
769  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
770  * \param  Path the new current directory
771  * \return true if the change succeeded
772  */ 
773 // ============================================================================
774
775 bool SALOME_NamingService::Change_Directory(const char* Path)
776 throw(ServiceUnreachable)
777 {
778 //   MESSAGE("BEGIN OF Change_Directory " << Path);
779   Utils_Locker lock (&_myMutex);
780
781   string path(Path);
782
783   // --- if path empty, nothing to do
784
785   if (path.empty())
786     return true;
787
788   // --- if path ='/', nothing to resolve, only change to root_context
789
790   if (path == "/")
791     {
792 //       MESSAGE("Change_Directory is called to go to the root_context");
793       _current_context = _root_context;
794       return true;
795     }
796
797   CosNaming::NamingContext_var current_context = _current_context;
798   bool changeOK = false;
799
800   // --- replace _current_context with _root_context if Path begins whith '/'
801
802   if (path[0] == '/')
803     current_context = _root_context;
804
805   // --- need to resolve directory path
806
807   ASSERT(!CORBA::is_nil(current_context));
808   
809   if (path[path.length()-1] != '/') path += '/';
810 //   SCRUTE(path);
811   CosNaming::Name context_name;
812   vector<string> splitPath;
813   _createContextNameDir(path.c_str(),
814                                                  context_name,
815                                                  splitPath,
816                                                  true);
817   
818   // --- Context creation
819   
820   try
821     {
822       CORBA::Object_var obj = current_context->resolve(context_name);
823       current_context = CosNaming::NamingContext::_narrow(obj);
824       ASSERT(!CORBA::is_nil(current_context));
825       _current_context = current_context;
826       changeOK = true;
827     }
828   
829   catch (CosNaming::NamingContext::NotFound& ex)
830     {
831       CosNaming::Name n = ex.rest_of_name;
832       
833       if (ex.why == CosNaming::NamingContext::missing_node)
834         MESSAGE( "Change_Directory() : " << (char *) n[0].id
835                << " (" << (char *) n[0].kind << ") not found");
836       if (ex.why == CosNaming::NamingContext::not_context)
837         INFOS("Change_Directory() : " << (char *) n[0].id
838               << " (" << (char *) n[0].kind
839                   << ") is not a context" );
840       if (ex.why == CosNaming::NamingContext::not_object)
841         INFOS( "Change_Directory() : " << (char *) n[0].id
842                << " (" << (char *) n[0].kind
843                << ") is not an object" );
844     }
845   
846   catch (CosNaming::NamingContext::CannotProceed&)
847     {
848       INFOS("Change_Directory(): CosNaming::NamingContext::CannotProceed");
849     }
850   
851   catch (CosNaming::NamingContext::InvalidName&)
852     {
853       INFOS("Change_Directory(): CosNaming::NamingContext::InvalidName");
854     }
855   
856   catch (CORBA::SystemException&)
857     {
858       INFOS("Change_Directory():CORBA::SystemException : unable to contact"
859             << "the naming service");
860       throw ServiceUnreachable();
861     }
862
863   return changeOK;
864 }
865
866 // ============================================================================
867 /*! \brief get the current directory path
868  *
869  *  Get the current directory path.
870  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
871  * \return the path of the current_context
872  * \sa  _current_directory
873  */ 
874 // ============================================================================
875
876 char* SALOME_NamingService::Current_Directory()
877 throw(ServiceUnreachable)
878 {
879   MESSAGE("BEGIN OF Current_Directory");
880
881   Utils_Locker lock (&_myMutex);
882
883   CosNaming::NamingContext_var ref_context = _current_context;
884
885   vector<string> splitPath;
886   splitPath.resize(0);
887   int lengthPath = 0;
888   bool notFound = true ;
889
890   // --- start search from root context
891
892   _current_context = _root_context ;
893
894   try
895     {
896       _current_directory(splitPath, lengthPath, ref_context, notFound );
897     }
898
899   catch (CORBA::SystemException&)
900     {
901       INFOS("Current_Directory(): CORBA::SystemException: unable to contact"
902             << " the naming service" )
903       throw ServiceUnreachable();
904     }
905
906   string path;
907   lengthPath = splitPath.size();
908   for (int k = 0 ; k < lengthPath ;k++)
909     {
910       path += "/";
911       path += splitPath[k];
912     }
913
914   SCRUTE(path)
915   _current_context = ref_context ;
916
917   return strdup(path.c_str());
918 }
919
920 // ============================================================================
921 /*! \brief list recursively all objects in the current context
922  *
923  *  List and print via trace all directories and objects in the current
924  *  context. Trace must be activated: compile option _DEBUG_
925  *  If the NamingService is out, the exception ServiceUnreachable is thrown
926  */ 
927 // ============================================================================
928
929 void SALOME_NamingService::list()
930 throw(ServiceUnreachable)
931 {
932   MESSAGE("Begin of list");
933
934   Utils_Locker lock (&_myMutex)
935
936     ;
937   CosNaming::BindingList_var binding_list;
938   CosNaming::BindingIterator_var binding_iterator;
939   CosNaming::Binding_var binding ;
940
941   unsigned long nb = 0 ; // --- only for the BindingIterator use,
942                          //     to access the bindings
943
944   CosNaming::NamingContext_var ref_context = _current_context;
945
946   _current_context->list(nb, binding_list, binding_iterator) ;
947
948   if (! CORBA::is_nil(binding_iterator))
949     {
950       while (binding_iterator->next_one(binding))
951         {
952           CosNaming::Name bindingName = binding->binding_name;
953
954           if (binding->binding_type == CosNaming::ncontext)
955             {
956               MESSAGE( "Context : " << bindingName[0].id );
957
958               try
959                 {
960                   Change_Directory(bindingName[0].id);
961                 }
962
963               catch (ServiceUnreachable&)
964                 {
965                   INFOS( "list(): ServiceUnreachable" )
966                     throw ServiceUnreachable();
967                 }
968
969               list();
970               _current_context = ref_context ;
971             }
972
973           else if (binding->binding_type == CosNaming::nobject)
974             {
975               MESSAGE( "Object : " << bindingName[0].id );
976             }
977         }
978
979       binding_iterator->destroy();
980     }
981 }
982
983 // ============================================================================
984 /*! \brief list all the objects in the current directory.
985  *
986  *  get a list of all the objects in the current directory, without recursion
987  *  on the subdirectories. Only the objects are listed, not the directories.
988  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
989  * \return list of strings with objects found.
990  * \sa vector<string> list_directory_recurs()
991  */ 
992 // ============================================================================
993
994 vector<string> SALOME_NamingService::list_directory()
995 throw(ServiceUnreachable)
996 {
997 //   MESSAGE("list_directory");
998   vector<string> dirList ;
999   dirList.resize(0);
1000
1001   CosNaming::BindingList_var binding_list;
1002   CosNaming::BindingIterator_var binding_iterator;
1003   CosNaming::Binding_var binding ;
1004
1005   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1006                          //     to access the bindings
1007
1008   CosNaming::NamingContext_var ref_context = _current_context;
1009
1010   _current_context->list(nb, binding_list, binding_iterator);
1011
1012   if (binding_iterator->_is_nil())
1013     return dirList;
1014
1015   while (binding_iterator->next_one(binding))
1016     {
1017       CosNaming::Name bindingName = binding->binding_name;
1018
1019       if (binding->binding_type == CosNaming::nobject)
1020         {
1021           // remove memory leak
1022           // dirList.push_back(CORBA::string_dup(bindingName[0].id));
1023           dirList.push_back(string(bindingName[0].id));
1024         }
1025     }
1026
1027 //   for (unsigned int ind = 0; ind < dirList.size(); ind++)
1028 //     MESSAGE("list_directory : Object : " << dirList[ind]);
1029
1030   binding_iterator->destroy();
1031
1032   return dirList;
1033 }
1034
1035
1036 // ============================================================================
1037 /*! \brief list all the subdirectories in the current directory.
1038  *
1039  *  get a list of all the subdirectories in the current directory,
1040  *  without recursion on the subdirectories.
1041  *  Only the subdirectories are listed, not the objects.
1042  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1043  * \return list of strings with directories found.
1044  * \sa vector<string> list_directory()
1045  */ 
1046 // ============================================================================
1047
1048 vector<string> SALOME_NamingService::list_subdirs()
1049 throw(ServiceUnreachable)
1050 {
1051   MESSAGE("list_subdirs");
1052   vector<string> dirList ;
1053   dirList.resize(0);
1054
1055   CosNaming::BindingList_var binding_list;
1056   CosNaming::BindingIterator_var binding_iterator;
1057   CosNaming::Binding_var binding ;
1058
1059   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1060                          //     to access the bindings
1061
1062   CosNaming::NamingContext_var ref_context = _current_context;
1063
1064   _current_context->list(nb, binding_list, binding_iterator) ;
1065
1066   if (binding_iterator->_is_nil())
1067     return dirList;
1068
1069   while (binding_iterator->next_one(binding))
1070     {
1071       CosNaming::Name bindingName = binding->binding_name;
1072
1073       if (binding->binding_type == CosNaming::ncontext)
1074         {
1075           dirList.push_back(bindingName[0].id.in());
1076         }
1077     }
1078
1079   for (unsigned int ind = 0; ind < dirList.size(); ind++)
1080     MESSAGE("list_directory : Object : " << dirList[ind]);
1081
1082   binding_iterator->destroy();
1083
1084   return dirList;
1085 }
1086
1087 // ============================================================================
1088 /*! \brief  list all the objects in the current directory and subdirectories.
1089  *
1090  *  get a list of all the objects in the current directory, with recursion
1091  *  on the subdirectories. Only the objects are listed, not the directories.
1092  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1093  * \return list of strings with objects found.
1094  * \sa vector<string> list_directory()
1095  */ 
1096 // ============================================================================
1097
1098 vector<string> SALOME_NamingService::list_directory_recurs()
1099 throw(ServiceUnreachable)
1100 {
1101   MESSAGE("list_directory_recurs");
1102
1103   Utils_Locker lock (&_myMutex);
1104
1105   vector<string> dirList ;
1106
1107   char* currentDir = Current_Directory();
1108
1109   _list_directory_recurs(dirList, "", currentDir);
1110
1111   free(currentDir);
1112
1113   return dirList;
1114 }
1115
1116 // ============================================================================
1117 /*! \brief destroy an entry in naming service.
1118  *
1119  *  Destroy an association Path - Object Reference.
1120  *  If the NamingService is out, the exception ServiceUnreachable is thrown 
1121  * \param Path object path
1122  */ 
1123 // ============================================================================
1124
1125 void SALOME_NamingService::Destroy_Name(const char* Path)
1126 throw(ServiceUnreachable)
1127 {
1128   MESSAGE("BEGIN OF Destroy_Name " << Path);
1129
1130   Utils_Locker lock (&_myMutex);
1131
1132   string path(Path);
1133
1134   // --- if path empty, nothing to do
1135
1136   if (path.empty())
1137     return;
1138
1139   // --- if path = '/' not applicable, nothing to do
1140
1141   if (path == "/")
1142     return;
1143
1144   // --- if path begins with '/', set current directory to root context
1145
1146   if (path[0] == '/')
1147     _current_context = _root_context;
1148
1149   // --- context of the directory containing the object
1150
1151   CosNaming::Name context_name;
1152   vector<string> splitPath;
1153   int dimension_resultat = _createContextNameDir(path.c_str(),
1154                                                  context_name,
1155                                                  splitPath,
1156                                                  true);
1157
1158   bool exist = false;
1159
1160   if (dimension_resultat > 0)
1161     {
1162       // --- path contains a directory, not only an object name
1163       //     switch to the new directory (or return if directory not found)
1164
1165       try
1166         {
1167           CORBA::Object_var obj = _current_context->resolve(context_name);
1168           _current_context = CosNaming::NamingContext::_narrow(obj);
1169           exist = true;
1170         }
1171
1172       catch (CosNaming::NamingContext::NotFound &ex)
1173         {
1174           // --- failed to resolve
1175           exist = false;
1176
1177           CosNaming::Name n = ex.rest_of_name;
1178
1179           if (ex.why == CosNaming::NamingContext::missing_node)
1180             INFOS( "Destroy_Name(): " << (char *) n[0].id
1181                    << " (" << (char *) n[0].kind << ") not found" );
1182           if (ex.why == CosNaming::NamingContext::not_context)
1183             INFOS( "Destroy_Name() : " << (char *) n[0].id
1184                    << " (" << (char *) n[0].kind
1185                    << ") is not a context" );
1186           if (ex.why == CosNaming::NamingContext::not_object)
1187             INFOS( "Destroy_Name() : " << (char *) n[0].id
1188                    << " (" << (char *) n[0].kind
1189                    << ") is not an object" );
1190         }
1191
1192       catch (CosNaming::NamingContext::InvalidName &)
1193         {
1194           INFOS("Destroy_Name: CosNaming::NamingContext::InvalidName");
1195         }
1196
1197       catch (CosNaming::NamingContext::CannotProceed &)
1198         {
1199           INFOS("Destroy_Name: CosNaming::NamingContext::CannotProceed");
1200         }
1201
1202       catch (CORBA::SystemException&)
1203         {
1204           INFOS("Destroy_Name : CORBA::SystemException: "
1205                 << "unable to contact the naming service");
1206           throw ServiceUnreachable();
1207         }
1208
1209       if (! exist) return;
1210     }
1211
1212   ASSERT(!CORBA::is_nil(_current_context));
1213
1214   // --- The current directory is now the directory where the object should
1215   //     be destroyed
1216
1217   int sizePath = splitPath.size();
1218   if (sizePath > dimension_resultat)
1219     {
1220       ASSERT(sizePath == dimension_resultat+1);
1221       context_name.length(1);
1222
1223       try
1224         {
1225           // --- the last element is an object and not a directory
1226
1227           context_name[0].id =
1228             CORBA::string_dup(splitPath[dimension_resultat].c_str());
1229           context_name[0].kind = CORBA::string_dup("object");
1230           SCRUTE(context_name[0].id);
1231  
1232           _current_context->unbind(context_name);
1233           MESSAGE("The object " << context_name[0].id << " has been deleted");
1234         }
1235
1236       catch (CosNaming::NamingContext::NotFound& ex)
1237         {
1238           CosNaming::Name n = ex.rest_of_name;
1239
1240           if (ex.why == CosNaming::NamingContext::missing_node)
1241             INFOS( "Destroy_Name() : " << (char *) n[0].id
1242                    << " (" << (char *) n[0].kind << ") not found" );
1243           if (ex.why == CosNaming::NamingContext::not_context)
1244             INFOS( "Destroy_Name() : " << (char *) n[0].id
1245                    << " (" << (char *) n[0].kind
1246                    << ") is not a context" );
1247           if (ex.why == CosNaming::NamingContext::not_object)
1248             INFOS( "Destroy_Name() : " << (char *) n[0].id
1249                    << " (" << (char *) n[0].kind
1250                    << ") is not an object" );
1251           }
1252
1253       catch (CosNaming::NamingContext::CannotProceed&)
1254         {
1255           INFOS( "Destroy_Name(): CosNaming::NamingContext::CannotProceed");
1256         }
1257
1258       catch (CosNaming::NamingContext::InvalidName&)
1259         {
1260           INFOS( "Destroy_Name(): CosNaming::NamingContext::InvalidName");
1261         }
1262
1263       catch (CORBA::SystemException&)
1264         {
1265           INFOS( "Destroy_Name(): CORBA::SystemException: unable to contact"
1266                  << " the naming service");
1267           throw ServiceUnreachable();
1268         }
1269     }
1270 }
1271
1272 // ============================================================================
1273 /*! \brief Destroy an empty directory
1274  *
1275  *  Destroy an empty directory in Naming Service.
1276  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1277  * \param Path directory path
1278  */ 
1279 // ============================================================================
1280
1281 void SALOME_NamingService::Destroy_Directory(const char* Path)
1282 throw(ServiceUnreachable)
1283 {
1284   MESSAGE("BEGIN OF Destroy_Directory " << Path);
1285
1286   Utils_Locker lock (&_myMutex);
1287
1288   string path(Path);
1289
1290   // --- if path empty, nothing to do
1291
1292   if (path.empty())
1293     return;
1294
1295   // --- if path begins with '/', set current directory to root context
1296
1297   if (path[0] == '/')
1298     _current_context = _root_context;
1299
1300   CosNaming::NamingContext_var ref_context = _current_context;
1301
1302   // --- path must ends with '/' for a directory
1303
1304   if (path[path.size() -1] != '/')
1305     path += '/';
1306
1307   // --- context of the directory
1308
1309   CosNaming::Name context_name;
1310   vector<string> splitPath;
1311   int dimension_resultat = _createContextNameDir(path.c_str(),
1312                                                  context_name,
1313                                                  splitPath,
1314                                                  true);
1315   bool exist = false;
1316
1317   if (dimension_resultat > 0)
1318     {
1319       // --- path contains a directory, not only an object name
1320       //     switch to the new directory (or return if directory not found)
1321
1322       try
1323         {
1324           CORBA::Object_var obj = _current_context->resolve(context_name);
1325           _current_context = CosNaming::NamingContext::_narrow(obj);
1326           exist = true;
1327         }
1328
1329       catch (CosNaming::NamingContext::NotFound &ex)
1330         {
1331           // --- failed to resolve
1332           exist = false;
1333
1334           CosNaming::Name n = ex.rest_of_name;
1335
1336           if (ex.why == CosNaming::NamingContext::missing_node)
1337             INFOS( "Destroy_Directory(): " << (char *) n[0].id
1338                    << " (" << (char *) n[0].kind << ") not found" );
1339           if (ex.why == CosNaming::NamingContext::not_context)
1340             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1341                    << " (" << (char *) n[0].kind
1342                    << ") is not a context" );
1343           if (ex.why == CosNaming::NamingContext::not_object)
1344             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1345                    << " (" << (char *) n[0].kind
1346                    << ") is not an object" );
1347         }
1348
1349       catch (CosNaming::NamingContext::InvalidName &)
1350         {
1351           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1352         }
1353
1354       catch (CosNaming::NamingContext::CannotProceed &)
1355         {
1356           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1357         }
1358
1359       catch (CORBA::SystemException&)
1360         {
1361           INFOS("Destroy_Directory : CORBA::SystemException: "
1362                 << "unable to contact the naming service");
1363           throw ServiceUnreachable();
1364         }
1365
1366       if (! exist) return;
1367     }
1368
1369   ASSERT(!CORBA::is_nil(_current_context));
1370
1371   // --- Context Destruction
1372
1373   bool isContextDestroyed = false;
1374   try
1375     {
1376       _current_context->destroy();
1377       MESSAGE( "The context " << path << " has been deleted" );
1378       isContextDestroyed = true;
1379     }
1380
1381   catch (CosNaming::NamingContext::NotEmpty&)
1382     {
1383       INFOS( "Destroy_Directory(): CosNaming::NamingContext::NoEmpty "
1384              << path << " is not empty" );
1385     }
1386
1387   catch (CORBA::SystemException&)
1388     {
1389       INFOS( "Destroy_Directory():CORBA::SystemException : "
1390              << "unable to contact the naming service");
1391       throw ServiceUnreachable();
1392     }
1393
1394   // --- go to the reference directory
1395
1396   _current_context = ref_context ;
1397
1398   ASSERT(!CORBA::is_nil(_current_context));
1399
1400   if (isContextDestroyed)
1401     {
1402       try
1403         {
1404           _current_context->unbind(context_name);
1405           MESSAGE( "The bind to the context "
1406                    << context_name[0].id
1407                    << " has been deleted" );
1408         }
1409
1410       catch (CosNaming::NamingContext::NotFound& ex)
1411         {
1412           CosNaming::Name n = ex.rest_of_name;
1413
1414           if (ex.why == CosNaming::NamingContext::missing_node)
1415             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1416                    << " (" << (char *) n[0].kind << ") not found" );
1417           if (ex.why == CosNaming::NamingContext::not_context)
1418             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1419                    << " (" << (char *) n[0].kind
1420                    << ") is not a context" );
1421           if (ex.why == CosNaming::NamingContext::not_object)
1422             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1423                    << " (" << (char *) n[0].kind
1424                    << ") is not an object" );
1425         }
1426
1427       catch (CosNaming::NamingContext::CannotProceed&)
1428         {
1429           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1430         }
1431
1432       catch (CosNaming::NamingContext::InvalidName&)
1433         {
1434           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1435             }
1436
1437       catch (CORBA::SystemException&)
1438         {
1439           INFOS("Destroy_Directory:CORBA::SystemException : unable to contact"
1440                  << " the naming service");
1441           throw ServiceUnreachable();
1442         }
1443     }
1444 }
1445
1446 // ============================================================================
1447 /*! \brief Destroy a directory with its contents.
1448  *
1449  *  Destroy the objects associations in a directory, and the directory itself,
1450  *  if there is no subdirectories. 
1451  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1452  * \param Path the directory path.
1453  */ 
1454 // ============================================================================
1455
1456 void SALOME_NamingService::Destroy_FullDirectory(const char* Path)
1457 throw(ServiceUnreachable)
1458 {
1459   MESSAGE("begin of Destroy_FullDirectory " << Path);
1460   if( Change_Directory(Path) )
1461     {
1462       vector<string> contList = list_directory();
1463
1464       for (unsigned int ind = 0; ind < contList.size(); ind++)
1465         Destroy_Name(contList[ind].c_str());
1466       
1467       Destroy_Directory(Path);
1468     }
1469 }
1470
1471 // ============================================================================
1472 /*! \brief  initialize root context (root directory)
1473  *
1474  * the root context initialisation must be done when the SALOME_NamingService
1475  * instance is created and before any othe call. See constructors.
1476  */ 
1477 // ============================================================================
1478
1479 void SALOME_NamingService::_initialize_root_context()
1480 {
1481   //MESSAGE("Get the root context");
1482
1483   try
1484     {
1485       CORBA::Object_var obj = _orb->resolve_initial_references("NameService");
1486       _root_context = CosNaming::NamingContext::_narrow(obj);
1487       _current_context = _root_context ;
1488       ASSERT(!CORBA::is_nil(_root_context));
1489     }
1490
1491   catch (CORBA::SystemException&)
1492     {
1493       INFOS("CORBA::SystemException: unable to contact the naming service");
1494       throw ServiceUnreachable();
1495     }
1496
1497   catch (...)
1498     {
1499       INFOS("Unknown Exception: unable to contact the naming service");
1500       throw ServiceUnreachable();
1501     }
1502 }
1503
1504 // ============================================================================
1505 /*! \brief transform a string path in CosNaming structure.
1506  *
1507  *  Transform a path given as a string in a CosNaming structure.
1508  *  \param path         a relative or absolute path, with or without an object.
1509  *                      An absolute path begins with '/'.
1510  *                      A path without an object ends with '/'.
1511  *  \param context_name CosNaming structure to put the path.
1512  *  \param splitPath    a vector of string with subdirectories and final
1513  *                      object, if any.
1514  *  \param onlyDir      if true, final object (if any) is ommited
1515  *                      in context_name.
1516  *                      if false, final object (if any) is included in
1517  *                      context_name.
1518  *  \return             dimension of context_name
1519  */ 
1520 // ============================================================================
1521
1522 int
1523 SALOME_NamingService::_createContextNameDir(string path,
1524                                             CosNaming::Name& context_name,
1525                                             vector<string>& splitPath,
1526                                             bool onlyDir)
1527 {
1528   if (path.empty())
1529     return 0;
1530
1531   string::size_type begIdx, endIdx;
1532   const string delims("/");
1533   splitPath.resize(0);
1534   bool endWithDelim = false;
1535
1536   begIdx = path.find_first_not_of(delims);
1537   while (begIdx != string::npos)
1538     {
1539       endIdx = path.find_first_of(delims, begIdx);
1540       if (endIdx == path.length()-1)
1541         endWithDelim = true;
1542       if (endIdx == string::npos)
1543         endIdx = path.length();
1544       int lsub = endIdx - begIdx;
1545       if (lsub >= 1)
1546         splitPath.push_back(path.substr(begIdx, lsub));
1547       begIdx = path.find_first_not_of(delims, endIdx);
1548     }
1549
1550   int dim;
1551   if (onlyDir)                  // only directory part
1552     {
1553       dim = splitPath.size()-1; // omit final object
1554       if (endWithDelim)         // unless the path ends with a delimiter 
1555         dim++;
1556       endWithDelim = true;
1557     }
1558   else
1559     dim = splitPath.size();     // directories and final object
1560
1561   context_name.length(dim);
1562   for (int i=0; i<dim; i++)
1563     {
1564 //       SCRUTE(splitPath[i]);
1565       context_name[i].id = CORBA::string_dup(splitPath[i].c_str());
1566       if (!endWithDelim && (i == dim-1)) // here, the last string is an object
1567         {
1568           context_name[i].kind = CORBA::string_dup("object");
1569 //        MESSAGE("--- " <<splitPath[i] <<".object");
1570         }
1571       else
1572         {
1573           context_name[i].kind = CORBA::string_dup("dir");
1574 //        MESSAGE("--- " <<splitPath[i] <<".dir");
1575         }
1576     }
1577   return dim;
1578 }
1579
1580 // ============================================================================
1581 /*! \brief search a name in current directory.
1582  *
1583  *  Search a name in the current directory. after call, the current directory
1584  *  is changed to the directory containing the last occurence of name found.
1585  *  If no occurence found (see return value), current directory remains
1586  *  unchanged. The call is recursive.
1587  *
1588  * \param  name the name to search.
1589  * \param  occurence_number number of occurence already found (incremented)
1590  */ 
1591 // ============================================================================
1592
1593 void SALOME_NamingService::_Find(const char* name,
1594                                  CORBA::Long& occurence_number)
1595 {
1596   MESSAGE("BEGIN OF _Find "<<  occurence_number << " " << name);
1597
1598   CosNaming::BindingList_var binding_list;
1599   CosNaming::BindingIterator_var binding_iterator;
1600   CosNaming::Binding_var binding;
1601
1602   unsigned long nb = 0 ; // --- only for the use of the BindingIterator,
1603                          //     to access the bindings
1604
1605   CosNaming::NamingContext_var ref_context = _current_context;
1606   CosNaming::NamingContext_var found_context = _current_context;
1607
1608   _current_context->list(nb, binding_list, binding_iterator) ;
1609
1610   if (! CORBA::is_nil(binding_iterator))
1611     {
1612       while (binding_iterator->next_one(binding))
1613         {
1614           CosNaming::Name bindingName = binding->binding_name;
1615           
1616           if (binding->binding_type == CosNaming::ncontext)
1617             {
1618               // --- We work on a directory,
1619               //     the search should be done in this directory
1620               
1621               Change_Directory(bindingName[0].id);
1622               _Find(name, occurence_number);
1623               
1624               // --- We'll go back to the initial context
1625               
1626               _current_context = ref_context ;
1627             }
1628           
1629           else if (binding->binding_type == CosNaming::nobject)
1630             {
1631               // --- We work on an object...
1632               
1633               if (!strcmp( bindingName[0].id, name))
1634                 {
1635                   //MESSAGE("One occurence was found");
1636                   occurence_number++;
1637                   
1638                   // --- We keep in memory the directory where
1639                   //     one occurence was found
1640                   
1641                   found_context = _current_context ;
1642                 }
1643             }
1644         }
1645       
1646       binding_iterator->destroy();
1647     }
1648   // --- We go to the last directory where an occurence was found
1649
1650   _current_context = found_context;
1651
1652   SCRUTE(occurence_number);
1653 }
1654
1655 // ============================================================================
1656 /*! \brief find the current directory path.
1657  * 
1658  *  Parse the naming service tree to find the current context and give the
1659  *  associated directory path (relative to root context).
1660  * \param splitPath 
1661  * \param lengthResult
1662  * \param contextToFind
1663  * \param notFound
1664  */ 
1665 // ============================================================================
1666
1667 void
1668 SALOME_NamingService::
1669 _current_directory(vector<string>& splitPath,
1670                    int& lengthResult,
1671                    CosNaming::NamingContext_var contextToFind,
1672                    bool& notFound)
1673 {
1674   MESSAGE("BEGIN OF _current_Directory");
1675
1676   CosNaming::BindingList_var binding_list;
1677   CosNaming::BindingIterator_var binding_iterator;
1678   CosNaming::Binding_var binding;
1679
1680   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1681                          //     to access the bindings
1682
1683   CosNaming::NamingContext_var ref_context = _current_context;
1684   CosNaming::NamingContext_var temp_context = _current_context;
1685
1686   _current_context->list(nb, binding_list, binding_iterator);
1687
1688   if ( !binding_iterator->_is_nil() )
1689     {
1690       while ((binding_iterator->next_one(binding)) && notFound)
1691         {
1692           CosNaming::Name bindingName = binding->binding_name;
1693
1694           if (binding->binding_type == CosNaming::ncontext)
1695             {
1696               // --- directory, search in it
1697
1698               const char* bindingNameid=bindingName[0].id;
1699               splitPath.push_back(bindingNameid);
1700               lengthResult++;
1701
1702               CORBA::Object_var obj = _current_context->resolve(bindingName);
1703               temp_context = CosNaming::NamingContext::_narrow(obj);
1704
1705               if (temp_context->_is_equivalent(contextToFind))
1706                 {
1707                   MESSAGE("The context is found, we stop the search");
1708                   notFound = false;
1709                   SCRUTE(notFound);
1710                 }
1711
1712               if (notFound)
1713                 {
1714                   SCRUTE(bindingName[0].id);
1715                   Change_Directory(bindingName[0].id);
1716                   _current_directory(splitPath,
1717                                      lengthResult,
1718                                      contextToFind,
1719                                      notFound);
1720
1721                   if (notFound)
1722                     {
1723                       // --- go back to the initial context
1724
1725                       _current_context = ref_context;
1726
1727                       MESSAGE("Just before the delete of "
1728                               << splitPath[lengthResult-1]);
1729                       splitPath.pop_back();
1730                       lengthResult--;
1731                     }
1732                 }
1733             }
1734         }
1735
1736       binding_iterator->destroy();
1737     }
1738
1739   // --- return to the last directory where an occurence was found
1740
1741   _current_context = ref_context ;
1742 }
1743
1744
1745 // ============================================================================
1746 /*! \brief list recursively all objects in the given directory and subdirs.
1747  *
1748  *  get a list of all the objects in the current directory, with recursion
1749  *  on the subdirectories. Only the objects are listed, not the directories.
1750  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1751  *  _current_context must refer to absCurDirectory.
1752  *
1753  *  \param myList          The list that will be filled.
1754  *  \param relativeSubDir  The directory relative to absCurDirectory in which
1755  *                         the objects are found.
1756  *  \param absCurDirectory The current directory, absolute path
1757  */ 
1758 // ============================================================================
1759
1760 void SALOME_NamingService::_list_directory_recurs(vector<string>& myList,
1761                                                   string relativeSubDir,
1762                                                   string absCurDirectory)
1763 {
1764   CosNaming::BindingList_var binding_list;
1765   CosNaming::BindingIterator_var binding_iterator;
1766   CosNaming::Binding_var binding ;
1767
1768   unsigned long nb = 0 ; // --- only for thethe use of BindingIterator
1769                          //     to access the bindings
1770
1771   string absDir;
1772
1773   CosNaming::NamingContext_var ref_context = _current_context;
1774
1775   if (! relativeSubDir.empty())
1776     {
1777       Change_Directory(relativeSubDir.c_str());
1778       absDir = absCurDirectory + "/" + relativeSubDir;
1779     }
1780
1781   else
1782     absDir = absCurDirectory;
1783
1784   SCRUTE(absDir);
1785   _current_context->list(nb, binding_list, binding_iterator) ;
1786
1787   if (! CORBA::is_nil(binding_iterator))
1788     {
1789       while (binding_iterator->next_one(binding))
1790         {
1791           CosNaming::Name bindingName = binding->binding_name;
1792
1793           if (binding->binding_type == CosNaming::ncontext)
1794             {
1795               string relativeSdir(bindingName[0].id);
1796               _list_directory_recurs(myList, relativeSdir, absDir);
1797             }
1798
1799           else if (binding->binding_type == CosNaming::nobject)
1800             {
1801               string objName(bindingName[0].id);
1802               string elt = absDir + "/" + objName;
1803               SCRUTE(elt);
1804               myList.push_back(elt);
1805             }
1806         }
1807
1808       binding_iterator->destroy();
1809     }
1810   if (! relativeSubDir.empty())
1811     {
1812       _current_context = ref_context;
1813     }
1814 }
1815
1816 // ============================================================================
1817 /*! \brief return a stringified reference of root context
1818  *
1819  * \return a stringified reference of root context
1820  */
1821 // ============================================================================
1822
1823 char * SALOME_NamingService::getIORaddr()
1824 {
1825   return _orb->object_to_string(_root_context);
1826 }
1827