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