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