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