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