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