Salome HOME
Removed includes and libraries of OCC
[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(CORBA::string_dup(bindingName[0].id));
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   string currentDir = Current_Directory();
1101
1102   _list_directory_recurs(dirList, "", currentDir);
1103
1104   return dirList;
1105 }
1106
1107 // ============================================================================
1108 /*! \brief destroy an entry in naming service.
1109  *
1110  *  Destroy an association Path - Object Reference.
1111  *  If the NamingService is out, the exception ServiceUnreachable is thrown 
1112  * \param Path object path
1113  */ 
1114 // ============================================================================
1115
1116 void SALOME_NamingService::Destroy_Name(const char* Path)
1117 throw(ServiceUnreachable)
1118 {
1119   MESSAGE("BEGIN OF Destroy_Name " << Path);
1120
1121   Utils_Locker lock (&_myMutex);
1122
1123   string path(Path);
1124
1125   // --- if path empty, nothing to do
1126
1127   if (path.empty())
1128     return;
1129
1130   // --- if path = '/' not applicable, nothing to do
1131
1132   if (path == "/")
1133     return;
1134
1135   // --- if path begins with '/', set current directory to root context
1136
1137   if (path[0] == '/')
1138     _current_context = _root_context;
1139
1140   // --- context of the directory containing the object
1141
1142   CosNaming::Name context_name;
1143   vector<string> splitPath;
1144   int dimension_resultat = _createContextNameDir(path.c_str(),
1145                                                  context_name,
1146                                                  splitPath,
1147                                                  true);
1148
1149   bool exist = false;
1150
1151   if (dimension_resultat > 0)
1152     {
1153       // --- path contains a directory, not only an object name
1154       //     switch to the new directory (or return if directory not found)
1155
1156       try
1157         {
1158           CORBA::Object_var obj = _current_context->resolve(context_name);
1159           _current_context = CosNaming::NamingContext::_narrow(obj);
1160           exist = true;
1161         }
1162
1163       catch (CosNaming::NamingContext::NotFound &ex)
1164         {
1165           // --- failed to resolve
1166           exist = false;
1167
1168           CosNaming::Name n = ex.rest_of_name;
1169
1170           if (ex.why == CosNaming::NamingContext::missing_node)
1171             INFOS( "Destroy_Name(): " << (char *) n[0].id
1172                    << " (" << (char *) n[0].kind << ") not found" );
1173           if (ex.why == CosNaming::NamingContext::not_context)
1174             INFOS( "Destroy_Name() : " << (char *) n[0].id
1175                    << " (" << (char *) n[0].kind
1176                    << ") is not a context" );
1177           if (ex.why == CosNaming::NamingContext::not_object)
1178             INFOS( "Destroy_Name() : " << (char *) n[0].id
1179                    << " (" << (char *) n[0].kind
1180                    << ") is not an object" );
1181         }
1182
1183       catch (CosNaming::NamingContext::InvalidName &)
1184         {
1185           INFOS("Destroy_Name: CosNaming::NamingContext::InvalidName");
1186         }
1187
1188       catch (CosNaming::NamingContext::CannotProceed &)
1189         {
1190           INFOS("Destroy_Name: CosNaming::NamingContext::CannotProceed");
1191         }
1192
1193       catch (CORBA::SystemException&)
1194         {
1195           INFOS("Destroy_Name : CORBA::SystemException: "
1196                 << "unable to contact the naming service");
1197           throw ServiceUnreachable();
1198         }
1199
1200       if (! exist) return;
1201     }
1202
1203   ASSERT(!CORBA::is_nil(_current_context));
1204
1205   // --- The current directory is now the directory where the object should
1206   //     be destroyed
1207
1208   int sizePath = splitPath.size();
1209   if (sizePath > dimension_resultat)
1210     {
1211       ASSERT(sizePath == dimension_resultat+1);
1212       context_name.length(1);
1213
1214       try
1215         {
1216           // --- the last element is an object and not a directory
1217
1218           context_name[0].id =
1219             CORBA::string_dup(splitPath[dimension_resultat].c_str());
1220           context_name[0].kind = CORBA::string_dup("object");
1221           SCRUTE(context_name[0].id);
1222  
1223           _current_context->unbind(context_name);
1224           MESSAGE("The object " << context_name[0].id << " has been deleted");
1225         }
1226
1227       catch (CosNaming::NamingContext::NotFound& ex)
1228         {
1229           CosNaming::Name n = ex.rest_of_name;
1230
1231           if (ex.why == CosNaming::NamingContext::missing_node)
1232             INFOS( "Destroy_Name() : " << (char *) n[0].id
1233                    << " (" << (char *) n[0].kind << ") not found" );
1234           if (ex.why == CosNaming::NamingContext::not_context)
1235             INFOS( "Destroy_Name() : " << (char *) n[0].id
1236                    << " (" << (char *) n[0].kind
1237                    << ") is not a context" );
1238           if (ex.why == CosNaming::NamingContext::not_object)
1239             INFOS( "Destroy_Name() : " << (char *) n[0].id
1240                    << " (" << (char *) n[0].kind
1241                    << ") is not an object" );
1242           }
1243
1244       catch (CosNaming::NamingContext::CannotProceed&)
1245         {
1246           INFOS( "Destroy_Name(): CosNaming::NamingContext::CannotProceed");
1247         }
1248
1249       catch (CosNaming::NamingContext::InvalidName&)
1250         {
1251           INFOS( "Destroy_Name(): CosNaming::NamingContext::InvalidName");
1252         }
1253
1254       catch (CORBA::SystemException&)
1255         {
1256           INFOS( "Destroy_Name(): CORBA::SystemException: unable to contact"
1257                  << " the naming service");
1258           throw ServiceUnreachable();
1259         }
1260     }
1261 }
1262
1263 // ============================================================================
1264 /*! \brief Destroy an empty directory
1265  *
1266  *  Destroy an empty directory in Naming Service.
1267  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1268  * \param Path directory path
1269  */ 
1270 // ============================================================================
1271
1272 void SALOME_NamingService::Destroy_Directory(const char* Path)
1273 throw(ServiceUnreachable)
1274 {
1275   MESSAGE("BEGIN OF Destroy_Directory " << Path);
1276
1277   Utils_Locker lock (&_myMutex);
1278
1279   string path(Path);
1280
1281   // --- if path empty, nothing to do
1282
1283   if (path.empty())
1284     return;
1285
1286   // --- if path begins with '/', set current directory to root context
1287
1288   if (path[0] == '/')
1289     _current_context = _root_context;
1290
1291   CosNaming::NamingContext_var ref_context = _current_context;
1292
1293   // --- path must ends with '/' for a directory
1294
1295   if (path[path.size() -1] != '/')
1296     path += '/';
1297
1298   // --- context of the directory
1299
1300   CosNaming::Name context_name;
1301   vector<string> splitPath;
1302   int dimension_resultat = _createContextNameDir(path.c_str(),
1303                                                  context_name,
1304                                                  splitPath,
1305                                                  true);
1306   bool exist = false;
1307
1308   if (dimension_resultat > 0)
1309     {
1310       // --- path contains a directory, not only an object name
1311       //     switch to the new directory (or return if directory not found)
1312
1313       try
1314         {
1315           CORBA::Object_var obj = _current_context->resolve(context_name);
1316           _current_context = CosNaming::NamingContext::_narrow(obj);
1317           exist = true;
1318         }
1319
1320       catch (CosNaming::NamingContext::NotFound &ex)
1321         {
1322           // --- failed to resolve
1323           exist = false;
1324
1325           CosNaming::Name n = ex.rest_of_name;
1326
1327           if (ex.why == CosNaming::NamingContext::missing_node)
1328             INFOS( "Destroy_Directory(): " << (char *) n[0].id
1329                    << " (" << (char *) n[0].kind << ") not found" );
1330           if (ex.why == CosNaming::NamingContext::not_context)
1331             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1332                    << " (" << (char *) n[0].kind
1333                    << ") is not a context" );
1334           if (ex.why == CosNaming::NamingContext::not_object)
1335             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1336                    << " (" << (char *) n[0].kind
1337                    << ") is not an object" );
1338         }
1339
1340       catch (CosNaming::NamingContext::InvalidName &)
1341         {
1342           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1343         }
1344
1345       catch (CosNaming::NamingContext::CannotProceed &)
1346         {
1347           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1348         }
1349
1350       catch (CORBA::SystemException&)
1351         {
1352           INFOS("Destroy_Directory : CORBA::SystemException: "
1353                 << "unable to contact the naming service");
1354           throw ServiceUnreachable();
1355         }
1356
1357       if (! exist) return;
1358     }
1359
1360   ASSERT(!CORBA::is_nil(_current_context));
1361
1362   // --- Context Destruction
1363
1364   bool isContextDestroyed = false;
1365   try
1366     {
1367       _current_context->destroy();
1368       MESSAGE( "The context " << path << " has been deleted" );
1369       isContextDestroyed = true;
1370     }
1371
1372   catch (CosNaming::NamingContext::NotEmpty&)
1373     {
1374       INFOS( "Destroy_Directory(): CosNaming::NamingContext::NoEmpty "
1375              << path << " is not empty" );
1376     }
1377
1378   catch (CORBA::SystemException&)
1379     {
1380       INFOS( "Destroy_Directory():CORBA::SystemException : "
1381              << "unable to contact the naming service");
1382       throw ServiceUnreachable();
1383     }
1384
1385   // --- go to the reference directory
1386
1387   _current_context = ref_context ;
1388
1389   ASSERT(!CORBA::is_nil(_current_context));
1390
1391   if (isContextDestroyed)
1392     {
1393       try
1394         {
1395           _current_context->unbind(context_name);
1396           MESSAGE( "The bind to the context "
1397                    << context_name[0].id
1398                    << " has been deleted" );
1399         }
1400
1401       catch (CosNaming::NamingContext::NotFound& ex)
1402         {
1403           CosNaming::Name n = ex.rest_of_name;
1404
1405           if (ex.why == CosNaming::NamingContext::missing_node)
1406             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1407                    << " (" << (char *) n[0].kind << ") not found" );
1408           if (ex.why == CosNaming::NamingContext::not_context)
1409             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1410                    << " (" << (char *) n[0].kind
1411                    << ") is not a context" );
1412           if (ex.why == CosNaming::NamingContext::not_object)
1413             INFOS( "Destroy_Directory() : " << (char *) n[0].id
1414                    << " (" << (char *) n[0].kind
1415                    << ") is not an object" );
1416         }
1417
1418       catch (CosNaming::NamingContext::CannotProceed&)
1419         {
1420           INFOS("Destroy_Directory: CosNaming::NamingContext::CannotProceed");
1421         }
1422
1423       catch (CosNaming::NamingContext::InvalidName&)
1424         {
1425           INFOS("Destroy_Directory: CosNaming::NamingContext::InvalidName");
1426             }
1427
1428       catch (CORBA::SystemException&)
1429         {
1430           INFOS("Destroy_Directory:CORBA::SystemException : unable to contact"
1431                  << " the naming service");
1432           throw ServiceUnreachable();
1433         }
1434     }
1435 }
1436
1437 // ============================================================================
1438 /*! \brief Destroy a directory with its contents.
1439  *
1440  *  Destroy the objects associations in a directory, and the directory itself,
1441  *  if there is no subdirectories. 
1442  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1443  * \param Path the directory path.
1444  */ 
1445 // ============================================================================
1446
1447 void SALOME_NamingService::Destroy_FullDirectory(const char* Path)
1448 throw(ServiceUnreachable)
1449 {
1450   MESSAGE("begin of Destroy_FullDirectory " << Path);
1451   if( Change_Directory(Path) )
1452     {
1453       vector<string> contList = list_directory();
1454
1455       for (unsigned int ind = 0; ind < contList.size(); ind++)
1456         Destroy_Name(contList[ind].c_str());
1457       
1458       Destroy_Directory(Path);
1459     }
1460 }
1461
1462 // ============================================================================
1463 /*! \brief  initialize root context (root directory)
1464  *
1465  * the root context initialisation must be done when the SALOME_NamingService
1466  * instance is created and before any othe call. See constructors.
1467  */ 
1468 // ============================================================================
1469
1470 void SALOME_NamingService::_initialize_root_context()
1471 {
1472   //MESSAGE("Get the root context");
1473
1474   try
1475     {
1476       CORBA::Object_var obj = _orb->resolve_initial_references("NameService");
1477       _root_context = CosNaming::NamingContext::_narrow(obj);
1478       _current_context = _root_context ;
1479       ASSERT(!CORBA::is_nil(_root_context));
1480     }
1481
1482   catch (CORBA::SystemException&)
1483     {
1484       INFOS("CORBA::SystemException: unable to contact the naming service");
1485       throw ServiceUnreachable();
1486     }
1487
1488   catch (...)
1489     {
1490       INFOS("Unknown Exception: unable to contact the naming service");
1491       throw ServiceUnreachable();
1492     }
1493 }
1494
1495 // ============================================================================
1496 /*! \brief transform a string path in CosNaming structure.
1497  *
1498  *  Transform a path given as a string in a CosNaming structure.
1499  *  \param path         a relative or absolute path, with or without an object.
1500  *                      An absolute path begins with '/'.
1501  *                      A path without an object ends with '/'.
1502  *  \param context_name CosNaming structure to put the path.
1503  *  \param splitPath    a vector of string with subdirectories and final
1504  *                      object, if any.
1505  *  \param onlyDir      if true, final object (if any) is ommited
1506  *                      in context_name.
1507  *                      if false, final object (if any) is included in
1508  *                      context_name.
1509  *  \return             dimension of context_name
1510  */ 
1511 // ============================================================================
1512
1513 int
1514 SALOME_NamingService::_createContextNameDir(string path,
1515                                             CosNaming::Name& context_name,
1516                                             vector<string>& splitPath,
1517                                             bool onlyDir)
1518 {
1519   if (path.empty())
1520     return 0;
1521
1522   string::size_type begIdx, endIdx;
1523   const string delims("/");
1524   splitPath.resize(0);
1525   bool endWithDelim = false;
1526
1527   begIdx = path.find_first_not_of(delims);
1528   while (begIdx != string::npos)
1529     {
1530       endIdx = path.find_first_of(delims, begIdx);
1531       if (endIdx == path.length()-1)
1532         endWithDelim = true;
1533       if (endIdx == string::npos)
1534         endIdx = path.length();
1535       int lsub = endIdx - begIdx;
1536       if (lsub >= 1)
1537         splitPath.push_back(path.substr(begIdx, lsub));
1538       begIdx = path.find_first_not_of(delims, endIdx);
1539     }
1540
1541   int dim;
1542   if (onlyDir)                  // only directory part
1543     {
1544       dim = splitPath.size()-1; // omit final object
1545       if (endWithDelim)         // unless the path ends with a delimiter 
1546         dim++;
1547       endWithDelim = true;
1548     }
1549   else
1550     dim = splitPath.size();     // directories and final object
1551
1552   context_name.length(dim);
1553   for (int i=0; i<dim; i++)
1554     {
1555 //       SCRUTE(splitPath[i]);
1556       context_name[i].id = CORBA::string_dup(splitPath[i].c_str());
1557       if (!endWithDelim && (i == dim-1)) // here, the last string is an object
1558         {
1559           context_name[i].kind = CORBA::string_dup("object");
1560 //        MESSAGE("--- " <<splitPath[i] <<".object");
1561         }
1562       else
1563         {
1564           context_name[i].kind = CORBA::string_dup("dir");
1565 //        MESSAGE("--- " <<splitPath[i] <<".dir");
1566         }
1567     }
1568   return dim;
1569 }
1570
1571 // ============================================================================
1572 /*! \brief search a name in current directory.
1573  *
1574  *  Search a name in the current directory. after call, the current directory
1575  *  is changed to the directory containing the last occurence of name found.
1576  *  If no occurence found (see return value), current directory remains
1577  *  unchanged. The call is recursive.
1578  *
1579  * \param  name the name to search.
1580  * \param  occurence_number number of occurence already found (incremented)
1581  */ 
1582 // ============================================================================
1583
1584 void SALOME_NamingService::_Find(const char* name,
1585                                  CORBA::Long& occurence_number)
1586 {
1587   MESSAGE("BEGIN OF _Find "<<  occurence_number << " " << name);
1588
1589   CosNaming::BindingList_var binding_list;
1590   CosNaming::BindingIterator_var binding_iterator;
1591   CosNaming::Binding_var binding;
1592
1593   unsigned long nb = 0 ; // --- only for the use of the BindingIterator,
1594                          //     to access the bindings
1595
1596   CosNaming::NamingContext_var ref_context = _current_context;
1597   CosNaming::NamingContext_var found_context = _current_context;
1598
1599   _current_context->list(nb, binding_list, binding_iterator) ;
1600
1601   if (! CORBA::is_nil(binding_iterator))
1602     {
1603       while (binding_iterator->next_one(binding))
1604         {
1605           CosNaming::Name bindingName = binding->binding_name;
1606           
1607           if (binding->binding_type == CosNaming::ncontext)
1608             {
1609               // --- We work on a directory,
1610               //     the search should be done in this directory
1611               
1612               Change_Directory(bindingName[0].id);
1613               _Find(name, occurence_number);
1614               
1615               // --- We'll go back to the initial context
1616               
1617               _current_context = ref_context ;
1618             }
1619           
1620           else if (binding->binding_type == CosNaming::nobject)
1621             {
1622               // --- We work on an object...
1623               
1624               if (!strcmp( bindingName[0].id, name))
1625                 {
1626                   //MESSAGE("One occurence was found");
1627                   occurence_number++;
1628                   
1629                   // --- We keep in memory the directory where
1630                   //     one occurence was found
1631                   
1632                   found_context = _current_context ;
1633                 }
1634             }
1635         }
1636       
1637       binding_iterator->destroy();
1638     }
1639   // --- We go to the last directory where an occurence was found
1640
1641   _current_context = found_context;
1642
1643   SCRUTE(occurence_number);
1644 }
1645
1646 // ============================================================================
1647 /*! \brief find the current directory path.
1648  * 
1649  *  Parse the naming service tree to find the current context and give the
1650  *  associated directory path (relative to root context).
1651  * \param splitPath 
1652  * \param lengthResult
1653  * \param contextToFind
1654  * \param notFound
1655  */ 
1656 // ============================================================================
1657
1658 void
1659 SALOME_NamingService::
1660 _current_directory(vector<string>& splitPath,
1661                    int& lengthResult,
1662                    CosNaming::NamingContext_var contextToFind,
1663                    bool& notFound)
1664 {
1665   MESSAGE("BEGIN OF _current_Directory");
1666
1667   CosNaming::BindingList_var binding_list;
1668   CosNaming::BindingIterator_var binding_iterator;
1669   CosNaming::Binding_var binding;
1670
1671   unsigned long nb = 0 ; // --- only for the BindingIterator use,
1672                          //     to access the bindings
1673
1674   CosNaming::NamingContext_var ref_context = _current_context;
1675   CosNaming::NamingContext_var temp_context = _current_context;
1676
1677   _current_context->list(nb, binding_list, binding_iterator);
1678
1679   if ( !binding_iterator->_is_nil() )
1680     {
1681       while ((binding_iterator->next_one(binding)) && notFound)
1682         {
1683           CosNaming::Name bindingName = binding->binding_name;
1684
1685           if (binding->binding_type == CosNaming::ncontext)
1686             {
1687               // --- directory, search in it
1688
1689               splitPath.push_back(CORBA::string_dup(bindingName[0].id));
1690               lengthResult++;
1691
1692               CORBA::Object_var obj = _current_context->resolve(bindingName);
1693               temp_context = CosNaming::NamingContext::_narrow(obj);
1694
1695               if (temp_context->_is_equivalent(contextToFind))
1696                 {
1697                   MESSAGE("The context is found, we stop the search");
1698                   notFound = false;
1699                   SCRUTE(notFound);
1700                 }
1701
1702               if (notFound)
1703                 {
1704                   SCRUTE(bindingName[0].id);
1705                   Change_Directory(bindingName[0].id);
1706                   _current_directory(splitPath,
1707                                      lengthResult,
1708                                      contextToFind,
1709                                      notFound);
1710
1711                   if (notFound)
1712                     {
1713                       // --- go back to the initial context
1714
1715                       _current_context = ref_context;
1716
1717                       MESSAGE("Just before the delete of "
1718                               << splitPath[lengthResult-1]);
1719                       splitPath.pop_back();
1720                       lengthResult--;
1721                     }
1722                 }
1723             }
1724         }
1725
1726       binding_iterator->destroy();
1727     }
1728
1729   // --- return to the last directory where an occurence was found
1730
1731   _current_context = ref_context ;
1732 }
1733
1734
1735 // ============================================================================
1736 /*! \brief list recursively all objects in the given directory and subdirs.
1737  *
1738  *  get a list of all the objects in the current directory, with recursion
1739  *  on the subdirectories. Only the objects are listed, not the directories.
1740  *  If the NamingService is out, the exception ServiceUnreachable is thrown.
1741  *  _current_context must refer to absCurDirectory.
1742  *
1743  *  \param myList          The list that will be filled.
1744  *  \param relativeSubDir  The directory relative to absCurDirectory in which
1745  *                         the objects are found.
1746  *  \param absCurDirectory The current directory, absolute path
1747  */ 
1748 // ============================================================================
1749
1750 void SALOME_NamingService::_list_directory_recurs(vector<string>& myList,
1751                                                   string relativeSubDir,
1752                                                   string absCurDirectory)
1753 {
1754   CosNaming::BindingList_var binding_list;
1755   CosNaming::BindingIterator_var binding_iterator;
1756   CosNaming::Binding_var binding ;
1757
1758   unsigned long nb = 0 ; // --- only for thethe use of BindingIterator
1759                          //     to access the bindings
1760
1761   string absDir;
1762
1763   CosNaming::NamingContext_var ref_context = _current_context;
1764
1765   if (! relativeSubDir.empty())
1766     {
1767       Change_Directory(relativeSubDir.c_str());
1768       absDir = absCurDirectory + "/" + relativeSubDir;
1769     }
1770
1771   else
1772     absDir = absCurDirectory;
1773
1774   SCRUTE(absDir);
1775   _current_context->list(nb, binding_list, binding_iterator) ;
1776
1777   if (! CORBA::is_nil(binding_iterator))
1778     {
1779       while (binding_iterator->next_one(binding))
1780         {
1781           CosNaming::Name bindingName = binding->binding_name;
1782
1783           if (binding->binding_type == CosNaming::ncontext)
1784             {
1785               string relativeSdir(bindingName[0].id);
1786               _list_directory_recurs(myList, relativeSdir, absDir);
1787             }
1788
1789           else if (binding->binding_type == CosNaming::nobject)
1790             {
1791               string objName(bindingName[0].id);
1792               string elt = absDir + "/" + objName;
1793               SCRUTE(elt);
1794               myList.push_back(elt);
1795             }
1796         }
1797
1798       binding_iterator->destroy();
1799     }
1800   if (! relativeSubDir.empty())
1801     {
1802       _current_context = ref_context;
1803     }
1804 }
1805
1806 // ============================================================================
1807 /*! \brief return a stringified reference of root context
1808  *
1809  * \return a stringified reference of root context
1810  */
1811 // ============================================================================
1812
1813 char * SALOME_NamingService::getIORaddr()
1814 {
1815   return _orb->object_to_string(_root_context);
1816 }
1817