]> 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: 2009/01/13 08:45:27 $
7   Version:   $Revision: 1.24 $
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     for (i=mReleasedDynamicallyLoadedPackages.begin();
628          i!=mReleasedDynamicallyLoadedPackages.end();
629          ++i)
630       {
631         if (!i->expired()) UnLoad(*i);
632       }
633     bbtkDebugMessage("package",5,"<== Package::UnLoadReleasedDynamicallyLoadedPackages()"<<std::endl);
634   }
635   //==========================================================================
636
637   //==========================================================================
638   void Package::UnLoad(Package::WeakPointer pack)
639   {
640     std::string packname = pack.lock()->GetName();
641     bbtkDebugMessage("package",6,"==> Package::UnLoad("<<packname<<")"<<std::endl);
642
643     Package* p = pack.lock().get();
644     
645     DynamicLibraryHandler h = p->mDynamicLibraryHandler;
646     
647     // deletes the package
648     p->mDLDeletePackageFunction();
649     
650     // closes the dl handler
651 #if defined(__GNUC__)  
652     dlclose(h);  
653 #elif defined(_WIN32)
654     FreeLibrary(h);
655 #endif
656
657     bbtkDebugMessage("package",1,"==> dynamic library for package '"
658                      <<packname<<"' closed"
659                      <<std::endl);    
660     bbtkDebugMessage("package",6,"   ... dynamic library unloaded"<<std::endl);
661   }
662   //==========================================================================
663
664   //==========================================================================
665   /// Creates an instance of a black box of type <type> with name <name>
666   BlackBox::Pointer Package::NewBlackBox(const std::string& type, 
667                                          const std::string& name) const
668   {
669     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::NewBlackBox(\""<<type<<"\",\""<<name<<"\")"<<bbtkendl);
670     
671     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(type);
672     if (i == mBlackBoxMap.end())  
673     {
674            bbtkDebugDecTab("Kernel",8);
675            return BlackBox::Pointer();
676     }
677     BlackBox::Pointer bb =i->second->NewBlackBox(name);
678     bbtkDebugDecTab("Kernel",8);
679     return bb;   
680
681   }
682   //==========================================================================
683
684
685
686   //==========================================================================
687   /// Creates an instance of an adaptor of input type <typein> and 
688   /// output type <typeout>  with name <name>
689   BlackBox::Pointer Package::NewAdaptor(const DataInfo& typein,
690                                 const DataInfo& typeout,
691                                 const std::string& name) const
692   {
693     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
694                         ">::NewAdaptor("
695                         <<typein<<","
696                         <<typeout<<",\""
697                         <<name<<"\")"<<bbtkendl);
698
699     AdaptorKey key(typein,typeout,
700                    BlackBoxDescriptor::DEFAULT_ADAPTOR);
701     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
702     if (i == mAdaptorMap.end())  
703       {
704         bbtkDebugDecTab("Kernel",8);
705         return BlackBox::Pointer();
706       }
707     BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
708     bbtkDebugDecTab("Kernel",8);
709     return bb;   
710
711   }
712   //==========================================================================
713
714   //==========================================================================
715   /// Creates an instance of an adaptor of input type <typein> and 
716   /// output type <typeout>  with name <name>
717   BlackBox::Pointer Package::NewWidgetAdaptor(const DataInfo& typein,
718                                       const DataInfo& typeout,
719                                       const std::string& name) const
720   {
721     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
722                         ">::NewWidgetAdaptor("
723                         <<typein<<","
724                         <<typeout<<",\""
725                         <<name<<"\")"<<bbtkendl);
726
727     AdaptorKey key(typein,typeout,
728                    BlackBoxDescriptor::DEFAULT_GUI);
729     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
730     if (i == mAdaptorMap.end())  
731       {
732         bbtkDebugDecTab("Kernel",8);
733         return BlackBox::Pointer();
734       }
735     BlackBox::Pointer bb =i->second.lock()->NewBlackBox(name);
736     bbtkDebugDecTab("Kernel",8);
737     return bb;   
738
739   }
740   //==========================================================================
741
742
743
744   //==========================================================================
745   /// Returns true is the package contains 
746   /// an adaptor of input type <typein> and 
747   /// output type <typeout>
748   /// If successfull then adaptor contains the black box type name
749   bool Package::FindWidgetAdaptor(const DataInfo& typein,
750                                   const DataInfo& typeout,
751                                   std::string& adaptor) const
752   {
753     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
754                         ">::FindWidgetAdaptor("
755                         <<typein<<","
756                         <<typeout<<")"<<bbtkendl);
757    
758     AdaptorKey key(/*typein*/
759                    DataInfo(typeid(void),""),
760                    typeout,
761                    BlackBoxDescriptor::DEFAULT_GUI);
762     // First try to find a single widget adaptor
763     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
764     if (i == mAdaptorMap.end())  
765       {
766         bbtkDebugDecTab("Kernel",8);
767         return false;
768       }
769     adaptor = i->second.lock()->GetTypeName();
770     bbtkDebugDecTab("Kernel",8);
771     return true;   
772
773   }
774   //==========================================================================
775
776
777
778   //==========================================================================
779   /// Returns true is the package contains 
780   /// an adaptor of input type <typein> and 
781   /// output type <typeout>
782   /// If successfull then adaptor contains the black box type name
783   bool Package::FindAdaptor(const DataInfo& typein,
784                             const DataInfo& typeout,
785                             std::string& adaptor) const
786   {
787     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<
788                         ">::FindAdaptor("
789                         <<typein<<","
790                         <<typeout<<")"<<bbtkendl);
791     
792     AdaptorKey key(typein,typeout,
793                    BlackBoxDescriptor::DEFAULT_ADAPTOR);
794     AdaptorMapType::const_iterator i = mAdaptorMap.find(key);
795     if (i == mAdaptorMap.end())  
796       {
797         bbtkDebugDecTab("Kernel",8);
798         return false;
799       }
800     adaptor = i->second.lock()->GetTypeName();
801     bbtkDebugDecTab("Kernel",8);
802     return true;   
803
804   }
805   //==========================================================================
806
807
808   //==========================================================================
809   /// Registers a black box descriptor in the package
810   bool Package::RegisterBlackBox(BlackBoxDescriptor::Pointer d) 
811   {
812     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\")"<<std::endl);
813     
814     BlackBoxMapType::iterator i = mBlackBoxMap.find(d->GetTypeName());
815     if (i!=mBlackBoxMap.end())
816       {
817         bbtkWarning("Package<"<<GetName()<<"> : Trying to register box type <"
818                     <<d->GetTypeName()<<"> which is already in the package");
819         return false;
820       }
821
822     mBlackBoxMap[d->GetTypeName()] = d;
823     //    d->Reference();
824     d->SetPackage(GetThisPointer<Package>());
825     
826     // If it is a default adaptor, also register it in the adaptors map
827     if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_ADAPTOR )
828       {
829         bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is an adaptor, inserting it in adaptors map ..."<<std::endl);   
830         
831         TypeInfo typein = d->GetInputDescriptor("In")->GetTypeInfo();
832         TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
833         DataInfo infoin(typein,d->GetInputDescriptor("In")->GetNature());
834         DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
835         AdaptorKey key(infoin,infoout,d->GetKind());
836         
837         AdaptorMapType::const_iterator i;
838         i = mAdaptorMap.find(key);        
839         if (i == mAdaptorMap.end())  
840           {
841             mAdaptorMap[key] = d;
842           }
843         // If already an adaptor registered : error
844         else 
845           {
846             if (i->second.lock()->GetTypeName() != d->GetTypeName()) 
847               {
848                 bbtkError("Package <"<<GetName()<<
849                           "> : trying to register black box <"
850                           <<d->GetTypeName()
851                           <<"> as default adaptor but there is already a default adaptor registered (<"
852                           <<i->second.lock()->GetTypeName()<<">)");
853               }
854           }
855       }
856     // If it is a default adaptor, also register it in the adaptors map
857     else if ( d->GetKind() == BlackBoxDescriptor::DEFAULT_GUI)
858       {
859         bbtkDebugMessage("Kernel",8,"Package<"<<GetName()<<">::RegisterBlackBox(\""<<d->GetTypeName()<<"\") : The box is a widget adaptor, inserting it in adaptors map ..."<<std::endl);   
860         
861         TypeInfo typeout = d->GetOutputDescriptor("Out")->GetTypeInfo();
862         DataInfo infoin(typeid(void),"");
863         DataInfo infoout(typeout,d->GetOutputDescriptor("Out")->GetNature());
864         AdaptorKey key(infoin,infoout,d->GetKind());
865
866         AdaptorMapType::const_iterator i;
867         i = mAdaptorMap.find(key);        
868         if (i == mAdaptorMap.end())  
869           {
870             mAdaptorMap[key] = d;
871           }
872         // If already an adaptor registered : error
873         else 
874           {
875             if (i->second.lock()->GetTypeName() != d->GetTypeName()) 
876               {
877                 bbtkError("Package <"<<GetName()<<
878                           "> : trying to register black box <"
879                           <<d->GetTypeName()
880                           <<"> as default widget adaptor but there is already a default adaptor registered (<"
881                           <<i->second.lock()->GetTypeName()<<">)");
882               }
883           }
884       }
885     
886
887     bbtkDebugDecTab("Kernel",8);
888    
889     return true;
890   }
891   //==========================================================================
892   
893   //===================================================================
894   void Package::CheckBoxes() const
895   {
896     bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
897                 <<" ["<<GetName()<<"]"<<std::endl);
898     BlackBoxMapType::const_iterator i;
899     for (i=mBlackBoxMap.begin();
900          i!=mBlackBoxMap.end();
901          ++i) 
902       {
903         i->second->Check(true);
904       }
905     bbtkMessage("debug",1,"****** Checking Package "<<(void*)this
906                 <<" ["<<GetName()<<"] ... OK"<<std::endl);
907   }
908   //===================================================================
909
910
911   //==========================================================================
912   /// Changes the name of a black box type
913   void Package::ChangeBlackBoxName( const std::string& oldname, const std::string& newname )
914   { 
915     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::ChangeBlackBoxName(\""<<oldname<<"\",\""<<newname<<"\")"<<std::endl);
916     // Looking into the bb map
917     BlackBoxMapType::iterator i = mBlackBoxMap.find(oldname);
918     if (i == mBlackBoxMap.end())  
919       {
920          bbtkDebugDecTab("Kernel",8);
921          bbtkError("ChangeBlackBoxName : The package <"<<GetName()<<"> does not contains the black box <"<<oldname<<">");
922       }
923
924     i->second->SetTypeName(newname);
925     mBlackBoxMap[newname] = i->second;
926     mBlackBoxMap.erase(i);
927
928     bbtkDebugDecTab("Kernel",8);    
929   }
930   //==========================================================================
931
932
933
934   //==========================================================================
935   /// Displays the list of black boxes of the package
936   void Package::PrintBlackBoxes(bool description, bool adaptors) const
937   {
938     unsigned int lmax = 0;
939     std::vector<std::string> names;
940     std::vector<std::string> kinds;
941     std::vector<std::string> descrs;
942
943     BlackBoxMapType::const_iterator i;
944     for (i=mBlackBoxMap.begin();
945          i!=mBlackBoxMap.end();
946          ++i) 
947       {
948         if ( adaptors || 
949              ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) ) 
950           {
951             std::string name("  ");
952             name += i->second->GetTypeName();
953             names.push_back(name);
954
955             std::string kind;
956             if ( i->second->GetKind() == BlackBoxDescriptor::ADAPTOR )
957               {
958                 kind = std::string("[A]");
959               }
960             else if ( i->second->GetKind() == 
961                       BlackBoxDescriptor::DEFAULT_ADAPTOR )
962               {
963                 kind = std::string("[DA]");
964               }
965             kinds.push_back(kind);
966
967             unsigned int l = name.size()+kind.size();
968             if (l>lmax) lmax = l;
969
970             std::string descr;
971             if (description) 
972               {
973                 descr += " : ";
974                 descr += i->second->GetDescription();
975               } 
976             descrs.push_back(descr);
977           }
978       } 
979     
980
981     std::string offs;
982     offs.append(lmax+3,' ');
983     std::vector<std::string>::iterator ni,ci,di;
984     for (ni = names.begin(), ci = kinds.begin(), di = descrs.begin();
985          ni != names.end(); ++ni, ++ci, ++di)
986       {
987         std::string space;
988         space.append(lmax - ni->size() - ci->size(),' ');
989         bbtkMessage("Help",1,*ni << space << *ci );
990         std::string d(*di);
991         unsigned int dmax = 75 - lmax;
992         //      while (d.size() > dmax ) 
993         //  {
994         if (d.size()>dmax) 
995           bbtkMessage("Help",1,d.substr(0,dmax) << "..." << std::endl);
996         else 
997           bbtkMessage("Help",1,d << std::endl);
998         //    d = d.substr(dmax,d.size());
999         //  }
1000       }
1001
1002   }
1003   //==========================================================================
1004
1005   //==========================================================================
1006   /// Displays the list of adaptors of the package
1007   void Package::PrintAdaptors(bool description) const
1008   {
1009     BlackBoxMapType::const_iterator i;
1010     for (i=mBlackBoxMap.begin();
1011          i!=mBlackBoxMap.end();
1012          ++i) 
1013       {
1014         if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD ) 
1015           {
1016             bbtkMessage("Help",1,
1017                         "  "<<i->second->GetTypeName());
1018             if ( i->second->GetKind() == 
1019                  BlackBoxDescriptor::DEFAULT_ADAPTOR )
1020               {
1021                 bbtkMessage("Help",1,
1022                             " [default]");
1023               }  
1024             if (description) 
1025               {
1026                 bbtkMessage("Help",1,
1027                             " : "<<i->second->GetDescription());
1028
1029               } 
1030             bbtkMessage("Help",1,std::endl);
1031           }
1032       } 
1033     /*
1034     AdaptorMapType::const_iterator i;
1035     for (i=mAdaptorMap.begin();
1036          i!=mAdaptorMap.end();
1037          ++i) 
1038       {
1039         bbtkMessage("Help",1,
1040                     "  "<<i->second->GetTypeName());
1041         if (detail_level>0) 
1042           {
1043             bbtkMessage("Help",1,
1044                         " : "<<i->second->GetDescription());
1045   
1046           } 
1047         bbtkMessage("Help",1,std::endl);
1048       }
1049     */ 
1050   }
1051   //==========================================================================
1052
1053   //==========================================================================
1054   /// Prints help on a black box
1055   void Package::HelpBlackBox(const std::string& name, bool full) const
1056   {
1057     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1058                         <<name<<"\")"<<bbtkendl);
1059
1060     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1061     if (i == mBlackBoxMap.end())  
1062       {
1063         bbtkDebugDecTab("Kernel",8);
1064         bbtkError("The package <"<<GetName()<<"> does not contains the black box <"<<name<<">");
1065       }
1066     //    bbtkMessage("Help",1,"["<<GetName()<<"] ");
1067     i->second->GetHelp(full);
1068     bbtkDebugDecTab("Kernel",8);
1069
1070   }
1071   //==========================================================================
1072
1073
1074   //==========================================================================
1075   /// Returns true iff the package contains the box of name boxname
1076   bool Package::ContainsBlackBox(const std::string& name) const 
1077   {
1078     bbtkDebugMessageInc("Kernel",8,"Package<"<<GetName()<<">::HelpBlackBox(\""
1079                         <<name<<"\")"<<bbtkendl);
1080     
1081     BlackBoxMapType::const_iterator i = mBlackBoxMap.find(name);
1082     if (i == mBlackBoxMap.end())  
1083     {
1084       bbtkDebugDecTab("Kernel",8);
1085       return false;
1086     }
1087     bbtkDebugDecTab("Kernel",8);
1088     return true;
1089   }
1090   //==========================================================================
1091
1092
1093  
1094   //==========================================================================
1095   void Package::CreateHtmlPage(const std::string& filename,
1096                                const std::string& caller,
1097                                const std::string& source,
1098                                const std::string& custom_header,
1099                                const std::string& custom_title,
1100                                int detail, 
1101                                int level,
1102                                bool relative_link ) const
1103   {
1104     bbtkDebugMessageInc("Kernel",9,"Package<"<<GetName()<<">::CreateHtmlPage(\""
1105                         <<filename<<"\")"<<bbtkendl);
1106
1107     //---------------------
1108     // Open output file
1109     std::ofstream s;
1110     s.open(filename.c_str());
1111     if (!s.good()) 
1112     {
1113        bbtkError("Package "<<GetName()<<" : CreateHtmlPage : could not open file '"<<filename<<"'");
1114     }
1115     
1116     //----------------------
1117     // Html head
1118     std::string title = "BBTK Package "+GetName()+" "+GetVersion(); 
1119
1120     if (custom_title.length() != 0) title = custom_title;
1121
1122     s << "<html lang=\"en\">\n";
1123     s << "<head>\n";
1124     s << "<title>" << title << "</title>\n";
1125     s << "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n";
1126     s << "<meta name=\"description\" content=\""<<title<<"\">\n";
1127     s << "<meta name=\"generator\" content=\"\">\n";
1128     s << "<link title=\"Top\" rel=\"top\" href=\"#Top\">\n";
1129     //<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
1130     s << "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"><style type=\"text/css\"><!--\n";
1131     s << "pre.display { font-family:inherit }\n";
1132     s << "pre.format  { font-family:inherit }\n";
1133     s << "pre.smalldisplay { font-family:inherit; font-size:smaller }\n";
1134     s << "pre.smallformat  { font-family:inherit; font-size:smaller }\n";
1135     s << "pre.smallexample { font-size:smaller }\n";
1136     s << "pre.smalllisp    { font-size:smaller }\n";
1137     s << "span.sc    { font-variant:small-caps }\n";
1138     s << "span.roman { font-family:serif; font-weight:normal; } \n";
1139     s << "span.sansserif { font-family:sans-serif; font-weight:normal; }\n"; 
1140     s << "--></style>\n";
1141     s << "</head>\n";
1142     //----------------------
1143
1144     //----------------------
1145     // Html body
1146     s << "<body>\n";
1147     s << "<a name=\"Top\"></a>\n"; 
1148     
1149     //----------------------
1150     // Header
1151     if ( custom_header.length() != 0) 
1152       {
1153         if ( custom_header != "none" )
1154           { 
1155             std::ifstream in;
1156             in.open(custom_header.c_str());    
1157             if (!in.good()) 
1158               {
1159                 bbtkError("Could not open file \""<<custom_header<<"\"");
1160               }
1161             char buffer[512];
1162             while (!in.eof()) 
1163               {
1164                 in.getline(buffer,512);
1165                 std::string line(buffer);
1166                 s << line;
1167               }
1168             in.close();
1169             s << "<hr>\n";
1170            
1171             /*   
1172             s << "<object data=\"" << custom_header 
1173               << "\" type = \"text/html\"\"style=\"width: 1200px; height: 400px;\"> Warning: "
1174               << custom_header <<" could not be embedded.</object>\n";
1175             
1176             s << "<hr>\n";
1177             */
1178           }
1179       }
1180
1181     else 
1182       {
1183         s << "<h1 class=\"settitle\">"<<title<<"</h1>\n";
1184         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1185         s << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1186           << GetDescription() << "</TD></TR>\n";
1187         s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  " 
1188           << GetAuthor() << "</TD></TR>\n";
1189         s << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  " 
1190           << GetCategory() << "</TD></TR>\n";
1191         s << "<TR><TD style='vertical-align: top;'><b> Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1192           << GetVersion() << "</TD></TR>\n";
1193         s << "<TR><TD style='vertical-align: top;'><b> bbtk Version </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
1194           << bbtk::GetVersion() << "</TD></TR>\n";
1195         s << "</TABLE>\n";
1196       }
1197
1198     //-------------------
1199     // Table of contents
1200     // Black boxes list
1201     //  s << "<div class=\"contents\">\n";
1202     s << "<p><b> Black Boxes : </b>\n";
1203     s << "<ul>\n";
1204
1205     s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1206
1207     BlackBoxMapType::const_iterator i;
1208     for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i) 
1209       {
1210         if ( i->second->GetKind() != BlackBoxDescriptor::STANDARD) 
1211           continue;
1212         
1213         std::string name = i->second->GetTypeName();
1214         Utilities::html_format(name);
1215         std::string descr = i->second->GetDescription();
1216         //Utilities::html_format(descr);
1217
1218         s << "<TR>";
1219         s << "<TD style='vertical-align: top;'>";
1220         s << "&nbsp;&nbsp;&nbsp;<a name=\"toc_"<<name
1221           <<"\" href=\"#"<<name<<"\">"
1222           <<name<<"</a>";
1223         s << "</TD> ";
1224         s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1225         s << "</TR>\n";
1226       }    
1227     s << "</TABLE>\n";
1228     
1229     
1230     s << "</ul>\n";
1231     s << "</div>\n";
1232     
1233     //-------------------
1234     // Adaptors list
1235     if (mAdaptorMap.size()>0) 
1236       {
1237         //  s << "<div class=\"contents\">\n";
1238         s << "<p><b> Adaptors : </b>\n";
1239         s << "<ul>\n";
1240
1241         //    BlackBoxMapType::const_iterator i;
1242         s << "<p><TABLE cellspacing=0  cellpadding=3>\n";
1243         for (i=mBlackBoxMap.begin(); i!=mBlackBoxMap.end();++i) 
1244           {
1245             if ( i->second->GetKind() == BlackBoxDescriptor::STANDARD) 
1246               continue;
1247     
1248             std::string name = i->second->GetTypeName();
1249             Utilities::html_format(name);
1250             std::string descr = i->second->GetDescription();
1251     
1252             s << "<TR>";
1253             s << "<TD style='vertical-align: top;'>";
1254             s << "&nbsp;&nbsp;&nbsp;<a name=\"toc_"<<name
1255               <<"\" href=\"#"<<name<<"\">"
1256               <<name<<"</a>";
1257             s << "</TD> ";
1258             s << " <TD style='vertical-align: top;'>" << descr << " </TD>";
1259             s << "</TR>\n";
1260           }    
1261         s << "</TABLE>\n";
1262
1263         s << "</ul>\n";
1264         s << "</div>\n";
1265       }
1266     
1267     
1268     //  s << "<div class=\"node\">\n";
1269
1270     //    s << "<p><hr>\n";
1271     //    s << "<a name=\"Top\"></a>\n";
1272     //  s << "Top:&nbsp;<a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
1273     // s << "Previous:&nbsp;<a rel="previous" accesskey="p" href="#dir">(dir)</a>,
1274     // s << "Up:&nbsp;<a rel="up" accesskey="u" href="#dir">(dir)</a>
1275     
1276     //    s << "</div>\n";
1277
1278     //----------------------
1279     // Boxes doc
1280
1281     //-------------------
1282     // Computes output directory from filename to pass it to 
1283     // BlackBoxDescriptor::InsertHtmlHelp
1284     std::string dir;
1285
1286     std::string::size_type slash_position = filename.find_last_of("/\\");
1287
1288
1289         if (slash_position != std::string::npos) {
1290       if (slash_position == 0)
1291          slash_position = 1;  
1292       dir = filename.substr(0,slash_position);
1293     }
1294
1295     for (i=mBlackBoxMap.begin();
1296          i!=mBlackBoxMap.end();
1297          ++i) 
1298       {
1299         i->second->InsertHtmlHelp(s,detail,level,dir,relative_link);
1300       }    
1301
1302     //----------------------
1303     // Footer 
1304     time_t rawtime;
1305     tm * ptm;
1306     time ( &rawtime );
1307     ptm = gmtime ( &rawtime );
1308
1309     s << "<p><hr>\n";
1310     s << "Automatically generated by <b>"<<caller<<"</b> "//from <b>"
1311       //      <<source<<"</b>
1312       <<"on "
1313       << ptm->tm_mday << "/" << ptm->tm_mon << "/" << ptm->tm_year+1900 
1314       << " - " << ptm->tm_hour << ":" << ptm->tm_min << " GMT\n";
1315     s << "</body></html>\n"; 
1316     s.close();
1317     //----------------------
1318
1319     // End
1320     bbtkDebugDecTab("Kernel",9);
1321   }
1322   //==========================================================================
1323   
1324   //==========================================================================
1325   std::string  Package::GetObjectName() const 
1326   { 
1327     return std::string("Package '")+mName+std::string("'"); 
1328   }
1329   //==========================================================================
1330
1331   //==========================================================================
1332   std::string Package::GetObjectInfo() const 
1333   {
1334     std::stringstream i;
1335     i << "  - "<<mBlackBoxMap.size() << " boxes" << std::endl;
1336     if (mDynamicLibraryHandler) 
1337       {
1338         i<< "  - Loaded from dynamic library"<<std::endl;
1339       }
1340     return i.str();
1341   }
1342   //==========================================================================
1343
1344
1345   //==========================================================================
1346   size_t  Package::GetObjectSize() const 
1347   {
1348     size_t s = Superclass::GetObjectSize();
1349     s += Package::GetObjectInternalSize();
1350     return s;
1351   }
1352   //==========================================================================
1353   //==========================================================================
1354   size_t  Package::GetObjectInternalSize() const 
1355   {
1356     size_t s = sizeof(Package);
1357     return s;
1358   }
1359   //==========================================================================
1360   //==========================================================================
1361   size_t  Package::GetObjectRecursiveSize() const 
1362   {
1363     size_t s = Superclass::GetObjectRecursiveSize();
1364     s += Package::GetObjectInternalSize();
1365     
1366     BlackBoxMapType::const_iterator i;
1367     for (i = mBlackBoxMap.begin(); i!=mBlackBoxMap.end(); ++i )
1368       {
1369         s += i->second->GetObjectRecursiveSize();
1370       }
1371     return s;
1372   }
1373   //==========================================================================
1374   
1375   //==========================================================================
1376   std::set<Package::WeakPointer> 
1377   Package::mReleasedDynamicallyLoadedPackages;
1378   //==========================================================================
1379 }
1380