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