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