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