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