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