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