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