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