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