]> Creatis software - bbtk.git/blob - kernel/src/bbtkPackage.cxx
Fixed Window deletion mechanism
[bbtk.git] / kernel / src / bbtkPackage.cxx
1
2 /*=========================================================================                                                                               
3   Program:   bbtk
4   Module:    $RCSfile: bbtkPackage.cxx,v $
5   Language:  C++
6   Date:      $Date: 2009/05/28 08:12:06 $
7   Version:   $Revision: 1.26 $
8 =========================================================================*/
9
10 /* ---------------------------------------------------------------------
11
12 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
13 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
14 *
15 *  This software is governed by the CeCILL-B license under French law and 
16 *  abiding by the rules of distribution of free software. You can  use, 
17 *  modify and/ or redistribute the software under the terms of the CeCILL-B 
18 *  license as circulated by CEA, CNRS and INRIA at the following URL 
19 *  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
20 *  or in the file LICENSE.txt.
21 *
22 *  As a counterpart to the access to the source code and  rights to copy,
23 *  modify and redistribute granted by the license, users are provided only
24 *  with a limited warranty  and the software's author,  the holder of the
25 *  economic rights,  and the successive licensors  have only  limited
26 *  liability. 
27 *
28 *  The fact that you are presently reading this means that you have had
29 *  knowledge of the CeCILL-B license and that you accept its terms.
30 * ------------------------------------------------------------------------ */                                                                         
31
32 /**
33  *\file
34  *\brief Class bbtk::Package : registers black boxes descriptors and is able to create instances of the black boxes registered.
35  */
36 #include "bbtkPackage.h"
37 #include "bbtkMessageManager.h"
38 #include "bbtkConfigurationFile.h"
39 #include <fstream>
40 #include <time.h>
41 #include "bbtkUtilities.h"
42
43 namespace bbtk
44 {
45   
46
47
48   //==========================================================================
49   /// Creates a new package
50   Package::Pointer Package::New(const std::string& name,
51                                 const std::string& author,
52                                 const std::string& description,
53                                 const std::string& version) 
54   {
55     bbtkDebugMessage("object",1,"##> Package::New('"<<name<<"',...)"
56                      <<bbtkendl);
57     Package::Pointer p = MakePointer(new Package(name,
58                                                author,
59                                                description,
60                                                version));
61     bbtkDebugMessage("object",2,"<## Package::New('"<<name<<"',...)"
62                      <<bbtkendl);
63     return p;
64   }
65   //==========================================================================
66
67   //==========================================================================
68   /// Ctor with the name of the package
69   Package::Package(const std::string& name,
70                    const std::string& author,
71                    const std::string& description,
72                    const std::string& version) 
73     :
74     mDynamicLibraryHandler(0),
75     mName(name),
76     mAuthor(author),
77     mDescription(description),
78     mVersion(version)
79   {
80     bbtkDebugMessage("object",2,"==> Package('"<<name<<"',...)"
81                      <<bbtkendl);
82     std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
83     char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
84     std::string url = default_doc_dir; 
85     if (c != '/' && c !='\\') url = url + "/";
86     url = url +  "temp_dir/" + name + "/index.html";    
87     
88     SetDocURL(url);
89     SetDocRelativeURL("Relative url not set");
90
91     /*
92     std::string relurl(BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH));
93     relurl += "/packages/"+name+"/bbdoc/index.html";
94     std::string url = ConfigurationFile::GetInstance().Get_url()
95       + relurl; 
96     SetDocURL(url);
97     SetDocRelativeURL(relurl);   
98     */
99
100     //    std::cout  << "   url=["<<url<<"]"<<std::endl;
101     //    std::cout  << "relurl=["<<relurl<<"]"<<std::endl;
102     bbtkDebugMessage("object",2,"<== Package::Package('"<<name<<"',...) OK"
103                      <<bbtkendl);
104
105   }
106   //==========================================================================
107
108
109
110   //==========================================================================
111   /// Dtor
112   Package::~Package()
113   {
114     bbtkDebugMessage("object",2,"==> ~Package(\""<<mName<<"\")"<<bbtkendl);
115   }
116   //==========================================================================
117
118
119   //==========================================================================
120   void PackageReleaseBlackBoxDescriptorInternal(Package::WeakPointer pack,
121                                                 const std::string& descname)
122   {
123     // Try to release descriptor
124     std::string packname = pack.lock()->GetName();
125
126     bbtkDebugMessage("package",5,"--- Releasing descriptor '"
127                      <<packname<<"::"<<descname<<"'"<<bbtkendl);
128
129
130     Package::BlackBoxMapType::iterator desc = 
131       pack.lock()->GetBlackBoxMap().find(descname);
132     if (desc ==  pack.lock()->GetBlackBoxMap().end())
133       {
134         bbtkDebugMessage("package",5,
135                          "    Descriptor has already been released"
136                          <<bbtkendl);
137         return;
138       }
139     //    bbtkDebugMessage("package",3,
140     //               "    Trying unreferencing it ... "<<std::endl);
141     BlackBoxDescriptor::WeakPointer pdesc = desc->second;
142     desc->second.reset();
143     // if it is dead : remove it 
144     if (pdesc.expired()) 
145       {
146         bbtkDebugMessage("package",2," ==> '"<<packname<<"::"<<descname<<"' Descriptor expired"<<bbtkendl);
147         if (pack.expired()) 
148           {
149             bbtkDebugMessage("package",2,
150                              "     ... and caused its package death"
151                              <<bbtkendl);
152             return;
153           }
154         desc = pack.lock()->GetBlackBoxMap().find(descname);
155         if (desc !=  pack.lock()->GetBlackBoxMap().end())
156           pack.lock()->GetBlackBoxMap().erase(desc);
157       }
158     else 
159       {
160         bbtkDebugMessage("package",5,"    ... Descriptor still alive ("
161                          <<pdesc.use_count()<<" refs)"
162                          <<bbtkendl);
163         pack.lock()->GetBlackBoxMap()[descname] = pdesc.lock();
164       }
165   }
166   //==========================================================================
167
168
169   //==========================================================================
170   /// Release
171   void Package::Release(Package::WeakPointer pack)
172   {
173     std::string packname = pack.lock()->mName;
174     bbtkDebugMessage("package",1,"==> Package::Release('"<<
175                      packname<<"')"<<bbtkendl);
176
177     long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
178     long ndesc = pack.lock()->GetBlackBoxMap().size();
179     long nrefs = pack.use_count();
180
181     bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
182                      <<ndesc<<" descr / dyn="
183                      <<dyn<<std::endl);
184
185     // A package is "free" from any external reference iff :
186     // i) It is not dynamically loaded and nrefs == ndesc 
187     // (each desc references its package) or
188     // ii) It is dynamically loaded and nrefs == ndesc + 1
189     // (A dynamic library holds a static pointer on the package it contains
190     //  which is allocated when the PACKAGENAMEGetPackage() func is called,
191     //  and descallocated (reset) by PACKAGENAMEDeletePackage())
192     if (nrefs == ndesc + dyn) 
193       {
194         bbtkDebugMessage("package",5,
195                          " -> No more external ref : checking descriptors"
196                          <<bbtkendl);
197         // We must take care that removing refs on descriptors 
198         // can lead to their deletion which can in turn unref 
199         // internal boxes which can release their descriptors hence 
200         // call Package::ReleaseBlackBoxDescriptor 
201         // As a consequence during descriptors release :
202         // 1) The map can change dynamically : we cannot iterate over it 
203         //    as any iterator can become invalid
204         // 2) The package can auto-destruct : we must test its existence 
205         //    after each release
206         // We must also take care of not locking the package pointer 
207         // or any ref count check in Package::ReleaseBlackBoxDescriptor
208         // would be wrong
209
210         // The list of descriptors names at start
211         std::vector<std::string> descnamelist;
212         BlackBoxMapType::iterator i;
213         for (i=pack.lock()->mBlackBoxMap.begin();
214              i!= pack.lock()->mBlackBoxMap.end();
215              ++i)
216           descnamelist.push_back(i->first);
217
218         // Iterator over the initial names
219         std::vector<std::string>::iterator descname;
220         for (descname=descnamelist.begin();
221              descname!=descnamelist.end();
222              ++descname)
223           {
224             // Is package still alive ?
225             if (pack.expired()) 
226               {
227                 bbtkDebugMessage("package",1,"--- Package::Release('"<<
228                                  packname
229                                  <<"') : package expired during release : bailing out"<<bbtkendl);
230                 break;
231               }
232             
233             PackageReleaseBlackBoxDescriptorInternal(pack,*descname);
234             
235           }
236
237         //
238         UnLoadDynamicLibrary(pack);
239         // Unload orphan dl packages 
240         Package::UnLoadReleasedDynamicallyLoadedPackages();
241         
242
243         
244         
245       }
246     
247 #ifdef BBTK_COMPILE_DEBUG_MESSAGES
248
249     bbtkDebugMessage("package",2,"<== Package::Release('"<<
250                      packname<<"')"<<bbtkendl);
251
252     if (!pack.expired())
253       {
254         long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
255         long ndesc = pack.lock()->GetBlackBoxMap().size();
256         long nrefs = pack.use_count();
257         
258         bbtkDebugMessage("package",1," ... Package still alive ("
259                          <<nrefs<<" refs / "
260                          <<ndesc<<" descr / dyn="
261                          <<dyn<<")"<<std::endl);
262       }
263     else 
264       {
265         bbtkDebugMessage("package",1," ... Package has been released"
266                          <<std::endl);
267       }
268 #endif
269   }
270   //==========================================================================
271
272   //==========================================================================
273   /// "Releases" the package
274   /// Signals the package that it can free the given descriptor
275   /// if they are no more used and free itself if it is no
276   /// more used
277   /// Note : Any non-weak pointer on the package must have been freed
278   void Package::ReleaseBlackBoxDescriptor(Package::WeakPointer pack,
279                                           BlackBoxDescriptor::WeakPointer descr)
280   {
281     std::string packname = pack.lock()->mName;
282     std::string dname = descr.lock()->GetTypeName();    
283     bbtkDebugMessage("package",3,"==> Package::ReleaseBlackBoxDescriptor('"<<
284                      packname<<"','"<<dname<<"') : refs="
285                      <<descr.use_count()<<bbtkendl);
286
287     long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
288     long ndesc = pack.lock()->GetBlackBoxMap().size();
289     long nrefs = pack.use_count();
290
291     bbtkDebugMessage("package",5," "<<nrefs<<" refs / "
292                      <<ndesc<<" descr / dynamically loaded = "
293                      <<dyn<<std::endl);
294
295     // A package is "free" from any external reference iff :
296     // i) It is not dynamically loaded and nrefs == ndesc 
297     // (each desc references its package) or
298     // ii) It is dynamically loaded and nrefs == ndesc + 1
299     // (A dynamic library holds a static pointer on the package it contains
300     //  which is allocated when the PACKAGENAMEGetPackage() func is called,
301     //  and descallocated (reset) by PACKAGENAMEDeletePackage())
302     if (nrefs == ndesc + dyn) 
303       {
304         PackageReleaseBlackBoxDescriptorInternal(pack,dname);
305       }
306     
307     // If the package is released and dynamically loaded 
308     // then put it in the static list mReleasedDynamicallyLoadedPackages
309     UnLoadDynamicLibrary(pack,false);
310         
311     bbtkDebugMessage("package",4,"<== Package::ReleaseBlackBoxDescriptor('"<<
312                      packname<<"','"<<dname<<"'): refs="
313                      <<descr.use_count()<<bbtkendl);
314     /*
315     if (!pack.expired())
316       {
317         long dyn = pack.lock()->mDynamicLibraryHandler ? 1:0; 
318         long ndesc = pack.lock()->GetBlackBoxMap().size();
319         long nrefs = pack.use_count();
320         
321         bbtkDebugMessage("package",3," ... Package still alive ("
322                          <<nrefs<<" refs / "
323                          <<ndesc<<" descr / dyn="
324                          <<dyn<<")"<<std::endl);
325       }
326     else 
327       {
328         bbtkDebugMessage("package",3,"   ... Package has been released"
329                          <<std::endl);
330       }  
331     */
332   }
333   //==========================================================================    
334
335   //==========================================================================
336   /// Opens a dynamic library which contains a bbtk package
337   /// Returns the handler 
338   /// Load the package management symbols from the lib
339   /// returns false if a problem occured hence can be used 
340   /// to test that a dyn lib is a valid bbtk package lib
341   /// NB : The BBTK version exported from the library 
342   ///      is tested against the current bbtk version
343   DynamicLibraryHandler Package::OpenDynamicLibrary
344   ( const std::string& libname,
345     const std::string& package_name,
346     DLGetPackageFunction& getpack,
347     DLDeletePackageFunction& delpack)
348   {
349     bbtkDebugMessage("package",3,"==> Package::OpenDynamicLibrary("
350                      <<libname<<")"<<std::endl);
351 #if defined(__GNUC__)
352
353     // Open shared lib
354     void *handler;
355     handler = dlopen(libname.c_str(),
356                      BBTK_RTLD_TIME | BBTK_RTLD_SCOPE );
357     if (!handler)
358       {
359         bbtkMessage("package",2,
360                     "Could not open shared library [" <<libname<<"] : "
361                     <<dlerror() << std::endl);
362         return 0;
363       }
364
365     bbtkDebugMessage("package",3,"* Shared lib ["<<libname<<"] open"<<std::endl);
366
367     // Loads the Package bbtk version function 
368     std::string getvername(package_name);
369     getvername += 
370       BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
371     DLGetPackageBBTKVersionFunction getbbtkversion 
372       = (DLGetPackageBBTKVersionFunction)(dlsym(handler,getvername.c_str()));
373     if (!getbbtkversion)
374       {
375         bbtkDebugMessage("package",3,"***"<<std::endl);
376         bbtkMessage("package",2,
377                     "Shared library ["<<libname
378                     <<"] is not a valid bbtk package."
379                     <<" Symbol ["<<getvername<<"] :"<<dlerror()<< std::endl);
380         dlclose(handler);
381         return 0;
382       }
383
384     bbtkDebugMessage("package",3,"* Symbol ["<<getvername
385                      <<"] found"<<std::endl);
386     // version matches ?
387     if (getbbtkversion() != bbtk::GetVersion())
388       {
389         bbtkMessage("package",2,
390                     "Shared library ["<<libname
391                     <<"] was build with bbtk version "
392                     <<getbbtkversion()
393                     <<" but the current program runs with version "
394                     <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
395         dlclose(handler);
396         return 0;
397         
398       }
399
400     bbtkDebugMessage("package",3,"* Package bbtk version '"<<getbbtkversion()<<"' matches"<<std::endl);
401             // Loads the Package get function
402     std::string getpackname(package_name);
403     getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
404     getpack = (DLGetPackageFunction)(dlsym(handler, getpackname.c_str()));
405     if (!getpack)
406       {
407         bbtkMessage("package",2,
408                     "Shared library ["<<libname
409                     <<"] is not a valid bbtk package."
410                     <<" Symbol ["<<getpackname<<"] :"<<dlerror()<< std::endl);
411         dlclose(handler);
412         return 0;
413       }
414   
415     bbtkDebugMessage("package",3,"* Symbol ["<<getpackname<<"] found"<<std::endl);
416     // Loads the Package delete function
417                                           
418     std::string delpackname(package_name);
419     delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
420     delpack = (DLDeletePackageFunction)(dlsym(handler, delpackname.c_str()));
421     if (!delpack)
422       {
423         bbtkMessage("package",2,
424                     "Shared library ["<<libname
425                     <<"] is not a valid bbtk package."
426                     <<" Symbol ["<<delpackname<<"] :"<<dlerror()<< std::endl);
427         dlclose(handler);
428         return 0;
429       }
430     bbtkDebugMessage("package",3,"* Symbol ["<<delpackname<<"] found"<<std::endl);                
431 #elif defined(_WIN32)
432     
433     HINSTANCE handler;
434     
435     SetErrorMode(0);
436     // Open shared lib
437     handler = LoadLibrary(libname.c_str());
438     if (!handler)
439       {
440         bbtkMessage("package",2,
441                     "Could not open shared library [" <<libname<<"]"
442                     << std::endl);
443         DWORD dwErrorCode = 0;
444         dwErrorCode = GetLastError();
445         bbtkMessage("package",2,
446                 "Windows Error: [" << dwErrorCode <<"]"
447                 << std::endl);
448          
449         return 0;
450       }
451     
452     // Loads the Package bbtk version function 
453     std::string getvername(package_name);
454     getvername += 
455       BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_BBTK_VERSION_FUNCTION_NAME);
456     DLGetPackageBBTKVersionFunction getbbtkversion 
457       = (DLGetPackageBBTKVersionFunction)(GetProcAddress(handler,
458                                                         getvername.c_str()));
459     if (!getbbtkversion)
460       {
461         FreeLibrary(handler);
462         bbtkMessage("package",2,
463                     "Shared library ["<<libname
464                     <<"] is not a valid bbtk package."
465                     <<" Symbol ["<<getbbtkversion<<"] not found"<< std::endl);
466         return 0;
467       }
468     
469     // version matches ?
470     if (getbbtkversion() != bbtk::GetVersion())
471       {
472         FreeLibrary(handler);
473         bbtkMessage("package",2,
474                     "Shared library ["<<libname
475                     <<"] was build with bbtk version "
476                     <<getbbtkversion()
477                     <<" but the current program runs with version "
478                     <<bbtk::GetVersion()<<" : cannot load it"<<std::endl);
479         return 0;
480         
481       }
482
483      // Loads the Package get function
484     std::string getpackname(package_name);
485     getpackname += BBTK_STRINGIFY_SYMBOL(BBTK_GET_PACKAGE_FUNCTION_NAME);
486     getpack = (DLGetPackageFunction)(GetProcAddress(handler, getpackname.c_str()));
487     if (!getpack)
488       {
489         FreeLibrary(handler);
490         bbtkMessage("package",2,
491                     "Shared library ["<<libname
492                     <<"] is not a valid bbtk package."
493                     <<" Symbol ["<<getpackname<<"] not found"<< std::endl);
494         return 0;
495       }
496     
497     // Loads the Package delete function
498     std::string delpackname(package_name);
499     delpackname += BBTK_STRINGIFY_SYMBOL(BBTK_DEL_PACKAGE_FUNCTION_NAME);
500     delpack = (DLDeletePackageFunction)(GetProcAddress(handler, delpackname.c_str()));
501     if (!delpack)
502       {
503         FreeLibrary(handler);
504         bbtkMessage("package",2,
505                     "Shared library ["<<libname
506                     <<"] is not a valid bbtk package."
507                     <<" Symbol ["<<delpackname<<"] not found"<< std::endl);
508         return 0;
509       }
510                                          
511 #else
512     bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
513 #endif
514     
515     return handler;
516   }
517   //==========================================================================
518   
519   //==========================================================================
520   /// Loads a package from a dynamic library
521   Package::Pointer Package::CreateFromDynamicLibrary(const std::string& libname,
522                                                      const std::string& pkgname,
523                                                      const std::string& path)
524   {
525     bbtkDebugMessage("package",1,"==> Package::CreateFromDynamicLibrary("
526                      <<libname<<")"<<std::endl);
527
528     DLGetPackageFunction gf;
529     DLDeletePackageFunction df;
530     DynamicLibraryHandler h = Package::OpenDynamicLibrary(libname,
531                                                           pkgname,
532                                                           gf,df);
533     if (h==0) return Package::Pointer(); 
534     Package::Pointer p = gf();
535     p->mDynamicLibraryHandler = h;
536     p->mDLDeletePackageFunction = df;
537     
538     std::string separator =
539       ConfigurationFile::GetInstance().Get_file_separator ();
540     //BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
541     std::string docreldoc = 
542       separator + "bbdoc" + separator + pkgname + separator + "index.html";
543     std::string reldoc = 
544       ".." + separator + ".." + docreldoc;
545     std::string doc = path + separator + ".." + separator
546       + BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH)
547       + docreldoc;
548     
549     p->SetDocURL(doc);
550     p->SetDocRelativeURL(reldoc);
551     
552     bbtkDebugMessage("package",2,"<== Package::CreateFromDynamicLibrary("
553                      <<libname<<") .. OK"<<std::endl);
554     return p;
555   }
556   //==========================================================================
557
558
559
560
561   //==========================================================================
562   /// UnLoads the package dynamic library (if any)
563   void Package::UnLoadDynamicLibrary(Package::WeakPointer pack, bool doit)
564   {
565     if (pack.expired() || (!pack.lock()->mDynamicLibraryHandler))
566       return;
567     
568     
569     std::string packname = pack.lock()->GetName();
570     bbtkDebugMessage("package",5,"==> Package::UnLoadDynamicLibrary('"
571                      <<packname<<"')"
572                      <<std::endl);
573     
574     if (!pack.lock()->GetBlackBoxMap().empty())
575       {
576         
577         bbtkDebugMessage("package",5,"   Package not empty ... abort"
578                          <<std::endl);
579         return;
580         /*
581         bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
582                         <<"BlackBoxMap not empty "
583                         <<BBTK_INTERNAL_ERROR_MESSAGE);
584         */
585         
586       }
587
588     if (pack.use_count()!=1)
589       {
590         bbtkGlobalError("Package::UnLoadDynamicLibrary('"<<packname<<") : "
591                         <<"empty dl package with external refs"
592                         <<BBTK_INTERNAL_ERROR_MESSAGE);
593       } 
594
595     if (doit) 
596       {
597         UnLoad(pack);
598         bbtkDebugMessage("package",5,"==> dynamic library for package '"
599                          <<packname<<"' closed"
600                          <<std::endl);    
601       }
602     else 
603       {
604         mReleasedDynamicallyLoadedPackages.insert(pack);
605         bbtkDebugMessage("package",1,"==> package '"<<packname
606                          <<"' put in the 'to unload' list"
607                          <<std::endl);
608
609       }
610
611     bbtkDebugMessage("package",5,"<== Package::UnLoadDynamicLibrary('"
612                      <<packname<<"')"
613                      <<std::endl);
614     
615   }
616   //==========================================================================
617
618   //==========================================================================
619   /// UnLoads released packages that were loaded dynamically
620   /// see UnLoadDynamicLibrary and ReleaseBlackBoxDescriptor
621   void Package::UnLoadReleasedDynamicallyLoadedPackages()
622   {
623     bbtkDebugMessage("package",5,"==> Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
624
625     std::set<Package::WeakPointer>::iterator i;
626
627 //JCP- 21-04-09
628         if(mReleasedDynamicallyLoadedPackages.size()>0){
629                 for (i=mReleasedDynamicallyLoadedPackages.begin();
630                 i!=mReleasedDynamicallyLoadedPackages.end();
631                 ++i)
632                 {
633                 if (!i->expired()) UnLoad(*i);
634                 }
635         }
636 //JCP- 21-04-09
637     bbtkDebugMessage("package",5,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
638   }
639   //==========================================================================
640
641   //==========================================================================
642   void Package::UnLoad(Package::WeakPointer pack)
643   {
644     std::string packname = pack.lock()->GetName();
645     bbtkDebugMessage("package",6,"==> Package::UnLoad("<<packname<<")"<<std::endl);
646
647     Package* p = pack.lock().get();
648     
649     DynamicLibraryHandler h = p->mDynamicLibraryHandler;
650     
651     // deletes the package
652     p->mDLDeletePackageFunction();
653     
654     // closes the dl handler
655 #if defined(__GNUC__)  
656     dlclose(h);  
657 #elif defined(_WIN32)
658     FreeLibrary(h);
659 #endif
660
661     bbtkDebugMessage("package",1,"==> dynamic library for package '"
662                      <<packname<<"' closed"
663                      <<std::endl);    
664     bbtkDebugMessage("package",6,"   ... dynamic library unloaded"<<std::endl);
665   }
666   //==========================================================================
667
668   //==========================================================================
669   /// Creates an instance of a black box of type <type> with name <name>
670   BlackBox::Pointer Package::NewBlackBox(const std::string& type, 
671                                          const std::string& name) const
672   {
673     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
674     
675     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
676     if (i == mBlackBoxMap.end())  
677     {
678            bbtkDebugDecTab("Kernel",8);
679            return BlackBox::Pointer();
680     }
681     BlackBox::Pointer bb =i->second->NewBlackBox(name);
682     bbtkDebugDecTab("Kernel",8);
683     return bb;   
684
685   }
686   //==========================================================================
687
688
689
690   //==========================================================================
691   /// Creates an instance of an adaptor of input type <typein> and 
692   /// output type <typeout>  with name <name>
693   BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
694                                 const DataInfo& typeout,
695                                 const std::string& name) const
696   {
697     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
698                         ">::NewAdaptor("
699                         <<typein<<","
700                         <<typeout<<",\""
701                         <<name<<"\")"<<bbtkendl);
702
703     AdaptorKey key(typein,typeout,
704                    BlackBoxDescriptor::DEFAULT_ADAPTOR);
705     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
706     if (i == mAdaptorMap.end())  
707       {
708         bbtkDebugDecTab("Kernel",8);
709         return BlackBox::Pointer();
710       }
711     BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
712     bbtkDebugDecTab("Kernel",8);
713     return bb;   
714
715   }
716   //==========================================================================
717
718   //==========================================================================
719   /// Creates an instance of an adaptor of input type <typein> and 
720   /// output type <typeout>  with name <name>
721   BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
722                                       const DataInfo& typeout,
723                                       const std::string& name) const
724   {
725     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
726                         ">::NewWidgetAdaptor("
727                         <<typein<<","
728                         <<typeout<<",\""
729                         <<name<<"\")"<<bbtkendl);
730
731     AdaptorKey key(typein,typeout,
732                    BlackBoxDescriptor::DEFAULT_GUI);
733     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
734     if (i == mAdaptorMap.end())  
735       {
736         bbtkDebugDecTab("Kernel",8);
737         return BlackBox::Pointer();
738       }
739     BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
740     bbtkDebugDecTab("Kernel",8);
741     return bb;   
742
743   }
744   //==========================================================================
745
746
747
748   //==========================================================================
749   /// Returns true is the package contains 
750   /// an adaptor of input type <typein> and 
751   /// output type <typeout>
752   /// If successfull then adaptor contains the black box type name
753   bool Package::FindWidgetAdaptor(const DataInfo& typein,
754                                   const DataInfo& typeout,
755                                   std::string& adaptor) const
756   {
757     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
758                         ">::FindWidgetAdaptor("
759                         <<typein<<","
760                         <<typeout<<")"<<bbtkendl);
761    
762     AdaptorKey key(/*typein*/
763                    DataInfo(typeid(void),""),
764                    typeout,
765                    BlackBoxDescriptor::DEFAULT_GUI);
766     // First try to find a single widget adaptor
767     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
768     if (i == mAdaptorMap.end())  
769       {
770         bbtkDebugDecTab("Kernel",8);
771         return false;
772       }
773     adaptor = i->second.lock()->GetTypeName();
774     bbtkDebugDecTab("Kernel",8);
775     return true;   
776
777   }
778   //==========================================================================
779
780
781
782   //==========================================================================
783   /// Returns true is the package contains 
784   /// an adaptor of input type <typein> and 
785   /// output type <typeout>
786   /// If successfull then adaptor contains the black box type name
787   bool Package::FindAdaptor(const DataInfo& typein,
788                             const DataInfo& typeout,
789                             std::string& adaptor) const
790   {
791     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
792                         ">::FindAdaptor("
793                         <<typein<<","
794                         <<typeout<<")"<<bbtkendl);
795     
796     AdaptorKey key(typein,typeout,
797                    BlackBoxDescriptor::DEFAULT_ADAPTOR);
798     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
799     if (i == mAdaptorMap.end())  
800       {
801         bbtkDebugDecTab("Kernel",8);
802         return false;
803       }
804     adaptor = i->second.lock()->GetTypeName();
805     bbtkDebugDecTab("Kernel",8);
806     return true;   
807
808   }
809   //==========================================================================
810
811
812   //==========================================================================
813   /// Registers a black box descriptor in the package
814   bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d) 
815   {
816     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
817     
818     BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
819     if (i!=mBlackBoxMap.end())
820       {
821         bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
822                     <<d->GetTypeName()<<"> which is already in the package");
823         return false;
824       }
825
826     mBlackBoxMap[d->GetTypeName()] = d;
827     //    d->Reference();
828     d->SetPackage(GetThisPointer<Package>());
829     
830     // If it is a default adaptor, also register it in the adaptors map
831     if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
832       {
833         bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);   
834         
835         TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
836         TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
837         DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
838         DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
839         AdaptorKey key(infoin,infoout,d->GetKind());
840         
841         AdaptorMapType::const_iterator i;
842         i = mAdaptorMap.find(key);        
843         if (i == mAdaptorMap.end())  
844           {
845             mAdaptorMap[key] = d;
846           }
847         // If already an adaptor registered : error
848         else 
849           {
850             if (i->second.lock()->GetTypeName() != d->GetTypeName()) 
851               {
852                 bbtkError("Package <"<<GetName()<<
853                           "> : trying to register black box <"
854                           <<d->GetTypeName()
855                           <<"> as default adaptor but there is already a default adaptor registered (<"
856                           <<i->second.lock()->GetTypeName()<<">)");
857               }
858           }
859       }
860     // If it is a default adaptor, also register it in the adaptors map
861     else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
862       {
863         bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);   
864         
865         TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
866         DataInfo infoin(typeid(void),"");
867         DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
868         AdaptorKey key(infoin,infoout,d->GetKind());
869
870         AdaptorMapType::const_iterator i;
871         i = mAdaptorMap.find(key);        
872         if (i == mAdaptorMap.end())  
873           {
874             mAdaptorMap[key] = d;
875           }
876         // If already an adaptor registered : error
877         else 
878           {
879             if (i->second.lock()->GetTypeName() != d->GetTypeName()) 
880               {
881                 bbtkError("Package <"<<GetName()<<
882                           "> : trying to register black box <"
883                           <<d->GetTypeName()
884                           <<"> as default widget adaptor but there is already a default adaptor registered (<"
885                           <<i->second.lock()->GetTypeName()<<">)");
886               }
887           }
888       }
889     
890
891     bbtkDebugDecTab("Kernel",8);
892    
893     return true;
894   }
895   //==========================================================================
896   
897   //===================================================================
898   void Package::CheckBoxes() const
899   {
900     bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
901                 <<" ["<<GetName()<<"]"<<std::endl);
902     BlackBoxMapType::const_iterator i;
903     for (i=mBlackBoxMap.begin();
904          i!=mBlackBoxMap.end();
905          ++i) 
906       {
907         i->second->Check(true);
908       }
909     bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
910                 <<" ["<<GetName()<<"] ... OK"<<std::endl);
911   }
912   //===================================================================
913
914
915   //==========================================================================
916   /// Changes the name of a black box type
917   void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
918   { 
919     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
920     // Looking into the bb map
921     BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
922     if (i == mBlackBoxMap.end())  
923       {
924          bbtkDebugDecTab("Kernel",8);
925          bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
926       }
927
928     i->second->SetTypeName(newname);
929     mBlackBoxMap[newname] = i->second;
930     mBlackBoxMap.erase(i);
931
932     bbtkDebugDecTab("Kernel",8);    
933   }
934   //==========================================================================
935
936
937
938   //==========================================================================
939   /// Displays the list of black boxes of the package
940   void Package::PrintBlackBoxes(bool description, bool adaptors) const
941   {
942     unsigned int lmax = 0;
943     std::vector<std::string> names;
944     std::vector<std::string> kinds;
945     std::vector<std::string> descrs;
946
947     BlackBoxMapType::const_iterator i;
948     for (i=mBlackBoxMap.begin();
949          i!=mBlackBoxMap.end();
950          ++i) 
951       {
952         if ( adaptors || 
953              ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) ) 
954           {
955             std::string name("  ");
956             name += i->second->GetTypeName();
957             names.push_back(name);
958
959             std::string kind;
960             if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
961               {
962                 kind = std::string("[A]");
963               }
964             else if ( i->second->GetKind() == 
965                       BlackBoxDescriptor::DEFAULT_ADAPTOR )
966               {
967                 kind = std::string("[DA]");
968               }
969             kinds.push_back(kind);
970
971             unsigned int l = name.size()+kind.size();
972             if (l>lmax) lmax = l;
973
974             std::string descr;
975             if (description) 
976               {
977                 descr += " : ";
978                 descr += i->second->GetDescription();
979               } 
980             descrs.push_back(descr);
981           }
982       } 
983     
984
985     std::string offs;
986     offs.append(lmax+3,' ');
987     std::vector<std::string>::iterator ni,ci,di;
988     for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
989          ni != names.end(); ++ni, ++ci, ++di)
990       {
991         std::string space;
992         space.append(lmax - ni->size() - ci->size(),' ');
993         bbtkMessage("Help",1,*ni << space << *ci );
994         std::string d(*di);
995         unsigned int dmax = 75 - lmax;
996         //      while (d.size() > dmax ) 
997         //  {
998         if (d.size()>dmax) 
999           bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
1000         else 
1001           bbtkMessage("Help",1,d << std::endl);
1002         //    d = d.substr(dmax,d.size());
1003         //  }
1004       }
1005
1006   }
1007   //==========================================================================
1008
1009   //==========================================================================
1010   /// Displays the list of adaptors of the package
1011   void Package::PrintAdaptors(bool description) const
1012   {
1013     BlackBoxMapType::const_iterator i;
1014     for (i=mBlackBoxMap.begin();
1015          i!=mBlackBoxMap.end();
1016          ++i) 
1017       {
1018         if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD ) 
1019           {
1020             bbtkMessage("Help",1,
1021                         "  "<<i->second->GetTypeName());
1022             if ( i->second->GetKind() == 
1023                  BlackBoxDescriptor::DEFAULT_ADAPTOR )
1024               {
1025                 bbtkMessage("Help",1,
1026                             " [default]");
1027               }  
1028             if (description) 
1029               {
1030                 bbtkMessage("Help",1,
1031                             " : "<<i->second->GetDescription());
1032
1033               } 
1034             bbtkMessage("Help",1,std::endl);
1035           }
1036       } 
1037     /*
1038     AdaptorMapType::const_iterator i;
1039     for (i=mAdaptorMap.begin();
1040          i!=mAdaptorMap.end();
1041          ++i) 
1042       {
1043         bbtkMessage("Help",1,
1044                     "  "<<i->second->GetTypeName());
1045         if (detail_level>0) 
1046           {
1047             bbtkMessage("Help",1,
1048                         " : "<<i->second->GetDescription());
1049   
1050           } 
1051         bbtkMessage("Help",1,std::endl);
1052       }
1053     */ 
1054   }
1055   //==========================================================================
1056
1057   //==========================================================================
1058   /// Prints help on a black box
1059   void Package::HelpBlackBox(const std::string& name, bool full) const
1060   {
1061     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1062                         <<name<<"\")"<<bbtkendl);
1063
1064     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1065     if (i == mBlackBoxMap.end())  
1066       {
1067         bbtkDebugDecTab("Kernel",8);
1068         bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1069       }
1070     //    bbtkMessage("Help",1,"["<<GetName()<<"] ");
1071     i->second->GetHelp(full);
1072     bbtkDebugDecTab("Kernel",8);
1073
1074   }
1075   //==========================================================================
1076
1077
1078   //==========================================================================
1079   /// Returns true iff the package contains the box of name boxname
1080   bool Package::ContainsBlackBox(const std::string& name) const 
1081   {
1082     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1083                         <<name<<"\")"<<bbtkendl);
1084     
1085     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1086     if (i == mBlackBoxMap.end())  
1087     {
1088       bbtkDebugDecTab("Kernel",8);
1089       return false;
1090     }
1091     bbtkDebugDecTab("Kernel",8);
1092     return true;
1093   }
1094   //==========================================================================
1095
1096
1097  
1098   //==========================================================================
1099   void Package::CreateHtmlPage(const std::string& filename,
1100                                const std::string& caller,
1101                                const std::string& source,
1102                                const std::string& custom_header,
1103                                const std::string& custom_title,
1104                                int detail, 
1105                                int level,
1106                                bool relative_link ) const
1107   {
1108     bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1109                         <<filename<<"\")"<<bbtkendl);
1110
1111     //---------------------
1112     // Open output file
1113     std::ofstream s;
1114     s.open(filename.c_str());
1115     if (!s.good()) 
1116     {
1117        bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1118     }
1119     
1120     //----------------------
1121     // Html head
1122     std::string title = "BBTK Package "+GetName()+" "+GetVersion(); 
1123
1124     if (custom_title.length() != 0) title = custom_title;
1125
1126     s << "<html lang=\"en\">\n";
1127     s << "<head>\n";
1128     s << "<title>" << title << "</title>\n";
1129     s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1130     s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1131     s << "<meta name=\"generator\" content=\"\">\n";
1132     s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1133     //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1134     s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1135     s << "pre.display { font-family:inherit }\n";
1136     s << "pre.format  { font-family:inherit }\n";
1137     s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1138     s << "pre.smallformat  { font-family:inherit; font-size:smaller }\n";
1139     s << "pre.smallexample { font-size:smaller }\n";
1140     s << "pre.smalllisp    { font-size:smaller }\n";
1141     s << "span.sc    { font-variant:small-caps }\n";
1142     s << "span.roman { font-family:serif; font-weight:normal; } \n";
1143     s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n"; 
1144     s << "--></style>\n";
1145     s << "</head>\n";
1146     //----------------------
1147
1148     //----------------------
1149     // Html body
1150     s << "<body>\n";
1151     s << "<a name=\"Top\"></a>\n"; 
1152     
1153     //----------------------
1154     // Header
1155     if ( custom_header.length() != 0) 
1156       {
1157         if ( custom_header != "none" )
1158           { 
1159             std::ifstream in;
1160             in.open(custom_header.c_str());    
1161             if (!in.good()) 
1162               {
1163                 bbtkError("Could not open file \""<<custom_header<<"\"");
1164               }
1165             char buffer[512];
1166             while (!in.eof()) 
1167               {
1168                 in.getline(buffer,512);
1169                 std::string line(buffer);
1170                 s << line;
1171               }
1172             in.close();
1173             s << "<hr>\n";
1174            
1175             /*   
1176             s << "<object data=\"" << custom_header 
1177               << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1178               << custom_header <<" could not be embedded.</object>\n";
1179             
1180             s << "<hr>\n";
1181             */
1182           }
1183       }
1184
1185     else 
1186       {
1187         s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1188         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1189         s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1190           << GetDescription() << "</TD></TR>\n";
1191         s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  " 
1192           << GetAuthor() << "</TD></TR>\n";
1193         s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  " 
1194           << GetCategory() << "</TD></TR>\n";
1195         s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1196           << GetVersion() << "</TD></TR>\n";
1197         s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1198           << bbtk::GetVersion() << "</TD></TR>\n";
1199         s << "</TABLE>\n";
1200       }
1201
1202     //-------------------
1203     // Table of contents
1204     // Black boxes list
1205     //  s << "<div class=\"contents\">\n";
1206     s << "<p><b> Black Boxes : </b>\n";
1207     s << "<ul>\n";
1208
1209     s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1210
1211     BlackBoxMapType::const_iterator i;
1212     for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i) 
1213       {
1214         if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD) 
1215           continue;
1216         
1217         std::string name = i->second->GetTypeName();
1218         Utilities::html_format(name);
1219         std::string descr = i->second->GetDescription();
1220         //Utilities::html_format(descr);
1221
1222         s << "<TR>";
1223         s << "<TD style='vertical-align: top;'>";
1224         s << "&nbsp;&nbsp;&nbsp;<a name=\"toc_"<<name
1225           <<"\" href=\"#"<<name<<"\">"
1226           <<name<<"</a>";
1227         s << "</TD> ";
1228         s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1229         s << "</TR>\n";
1230       }    
1231     s << "</TABLE>\n";
1232     
1233     
1234     s << "</ul>\n";
1235     s << "</div>\n";
1236     
1237     //-------------------
1238     // Adaptors list
1239     if (mAdaptorMap.size()>0) 
1240       {
1241         //  s << "<div class=\"contents\">\n";
1242         s << "<p><b> Adaptors : </b>\n";
1243         s << "<ul>\n";
1244
1245         //    BlackBoxMapType::const_iterator i;
1246         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1247         for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i) 
1248           {
1249             if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) 
1250               continue;
1251     
1252             std::string name = i->second->GetTypeName();
1253             Utilities::html_format(name);
1254             std::string descr = i->second->GetDescription();
1255     
1256             s << "<TR>";
1257             s << "<TD style='vertical-align: top;'>";
1258             s << "&nbsp;&nbsp;&nbsp;<a name=\"toc_"<<name
1259               <<"\" href=\"#"<<name<<"\">"
1260               <<name<<"</a>";
1261             s << "</TD> ";
1262             s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1263             s << "</TR>\n";
1264           }    
1265         s << "</TABLE>\n";
1266
1267         s << "</ul>\n";
1268         s << "</div>\n";
1269       }
1270     
1271     
1272     //  s << "<div class=\"node\">\n";
1273
1274     //    s << "<p><hr>\n";
1275     //    s << "<a name=\"Top\"></a>\n";
1276     //  s << "Top:&nbsp;<a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1277     // s << "Previous:&nbsp;<a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1278     // s << "Up:&nbsp;<a rel="up" accesskey="u" href="#dir">(dir)</a>
1279     
1280     //    s << "</div>\n";
1281
1282     //----------------------
1283     // Boxes doc
1284
1285     //-------------------
1286     // Computes output directory from filename to pass it to 
1287     // BlackBoxDescriptor::InsertHtmlHelp
1288     std::string dir;
1289
1290     std::string::size_type slash_position = filename.find_last_of("/\\");
1291
1292
1293         if (slash_position != std::string::npos) {
1294       if (slash_position == 0)
1295          slash_position = 1;  
1296       dir = filename.substr(0,slash_position);
1297     }
1298
1299     for (i=mBlackBoxMap.begin();
1300          i!=mBlackBoxMap.end();
1301          ++i) 
1302       {
1303         i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1304       }    
1305
1306     //----------------------
1307     // Footer 
1308     time_t rawtime;
1309     tm * ptm;
1310     time ( &rawtime );
1311     ptm = gmtime ( &rawtime );
1312
1313     s << "<p><hr>\n";
1314     s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1315       //      <<source<<"</b>
1316       <<"on "
1317       << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900 
1318       << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1319     s << "</body></html>\n"; 
1320     s.close();
1321     //----------------------
1322
1323     // End
1324     bbtkDebugDecTab("Kernel",9);
1325   }
1326   //==========================================================================
1327   
1328   //==========================================================================
1329   std::string  Package::GetObjectName() const 
1330   { 
1331     return std::string("Package '")+mName+std::string("'"); 
1332   }
1333   //==========================================================================
1334
1335   //==========================================================================
1336   std::string Package::GetObjectInfo() const 
1337   {
1338     std::stringstream i;
1339     i << "  - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1340     if (mDynamicLibraryHandler) 
1341       {
1342         i<< "  - Loaded from dynamic library"<<std::endl;
1343       }
1344     return i.str();
1345   }
1346   //==========================================================================
1347
1348
1349   //==========================================================================
1350   size_t  Package::GetObjectSize() const 
1351   {
1352     size_t s = Superclass::GetObjectSize();
1353     s += Package::GetObjectInternalSize();
1354     return s;
1355   }
1356   //==========================================================================
1357   //==========================================================================
1358   size_t  Package::GetObjectInternalSize() const 
1359   {
1360     size_t s = sizeof(Package);
1361     return s;
1362   }
1363   //==========================================================================
1364   //==========================================================================
1365   size_t  Package::GetObjectRecursiveSize() const 
1366   {
1367     size_t s = Superclass::GetObjectRecursiveSize();
1368     s += Package::GetObjectInternalSize();
1369     
1370     BlackBoxMapType::const_iterator i;
1371     for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1372       {
1373         s += i->second->GetObjectRecursiveSize();
1374       }
1375     return s;
1376   }
1377   //==========================================================================
1378   
1379   //==========================================================================
1380   std::set<Package::WeakPointer> 
1381   Package::mReleasedDynamicallyLoadedPackages;
1382   //==========================================================================
1383 }
1384