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