00001 // 00002 // File: ConnectionHandler.cc 00003 // Created by: <Detro /> aka Ivan De Marino 00004 // <detro@mandolinux.org, demarino@studenti.unina.it, demarino@na.astro.it> 00005 // Created on: Tue Nov 16 01:22:38 2004 00006 // 00007 00008 #ifndef _TFACTORY_H_ 00009 #define _TFACTORY_H_ 00010 #include "TFactoryException.h" 00011 #include <dlfcn.h> // Libreria "Dynamic Lynking Loader" 00012 00013 /** 00014 * @class TFactory TFactory.h 00015 * Questa Classe Template ha il compito di @b Istanziare @b a @b Run-Time Classi 00016 * la cui Dichiarazione e Definizione non e' avvenuta a @b Compile-Time. 00017 * In sostanza, si parla di realizzare un sistema per la gestione 00018 * di quelli che, in gergo, si chiamano @b Plug-In: mini-programmi che 00019 * si aggiungono ad altri piu' grandi per aumentarne le funzionalita'. 00020 * 00021 * E' una "Factory" di Classi @a Plug-In. <br> 00022 * Carica da libreria SO la definizione di una Classe che ha come 00023 * Classe di Base il Parametro passato alla Factory: in questo modo e' 00024 * sufficiente, per realizzare classi Plug-In, che le Classi da Istanziare 00025 * a Run-Time implementino un'interfaccia comune. 00026 * 00027 * Per la precisione, e' anche necessario che nella libreria SO che 00028 * contiene la classe sia presente una funzione cosė definita: <br> <br> 00029 * 00030 * <code> 00031 * extern "C" <br> 00032 * <ClassName> *buildObject(void) { return new <ClassName>; } <br> 00033 * </code> <br> 00034 * 00035 * @c buildObject(void) crea effettivamente una istanza della Classe Plug-In. 00036 * 00037 * Questa soluzione permette quindi di caricare nuove Classi senza 00038 * bisogno ne di ricompilare, ne di modificare il codice. */ 00039 template <class T> 00040 class TFactory { 00041 public: 00042 TFactory(const string &); 00043 ~TFactory(); 00044 T build () ; 00045 void closeSo(); 00046 00047 private: 00048 /* Handler della SO caricata */ 00049 void *handler; 00050 /* Puntatore alla funzione (o, meglio, al "simbolo") 00051 * ritornato da "dlsym" */ 00052 T (*builder)(void); 00053 void openSo(const string &); 00054 }; 00055 00056 /** 00057 * Costruttore TFactory. 00058 * Si occupa anche di recuperare i Simboli (@c "buildObject" ) 00059 * necessari all'istanziazione di una nuova T Class. 00060 * 00061 * @param soLibPath Path alla Libreria SO da dove caricare la definizione 00062 * della Classe */ 00063 template <class T> 00064 TFactory<T>::TFactory(const string &soLibPath) { 00065 try { 00066 /* Caricamento della SO */ 00067 openSo(soLibPath); 00068 /* Casting necessario per una corretta assegnazione 00069 * della funzione al relativo puntatore */ 00070 *(void **) (&builder) = dlsym(handler, "buildObject"); 00071 /* Controlla che il Simbolo Cercato ("buildObject") sia 00072 * stato trovato... */ 00073 if ( builder == NULL ) { // Errore nel caricamento della funzione 00074 /* ...in caso negativo, lancia un TFactoryException */ 00075 string exceptionMessage("<TFactory msg> ERROR: "); 00076 exceptionMessage += dlerror(); 00077 throw TFactoryException(exceptionMessage); 00078 } 00079 } 00080 catch ( TFactoryException &e ) { 00081 throw e; 00082 } 00083 cout << "<TFactory msg> Plug-In Loaded. Library-Path: "<< soLibPath << endl; 00084 } 00085 00086 /** Distruttore TFactory */ 00087 template <class T> 00088 TFactory<T>::~TFactory() {} 00089 00090 /** 00091 * Restituisce una istanza della Classe contenuta nella SO. 00092 * L'oggetto restituito e' UP-Castato alla Classe Base "T" 00093 * (parametro del Template) 00094 * @return Una nuova istanza di T (T = Parametro di TFactory) */ 00095 template <class T> 00096 T TFactory<T>::build() { 00097 return ( (*builder)() ); // Ritorna la nuova istanza di T 00098 } 00099 00100 /** 00101 * Carica la libreria SO. 00102 * 00103 * @param soLibPath Libreria SO da caricare */ 00104 template <class T> 00105 void TFactory<T>::openSo(const string &soLibPath) { 00106 /* Apertura della Libreria SO */ 00107 handler = dlopen( soLibPath.data(), RTLD_NOW); 00108 00109 if (!handler) { 00110 string exceptionMessage("<TFactory msg> ERROR: "); 00111 exceptionMessage += dlerror(); 00112 throw TFactoryException(exceptionMessage); 00113 } 00114 } 00115 00116 /** Chiude la libreria SO */ 00117 template <class T> 00118 void TFactory<T>::closeSo() { 00119 if (handler) { 00120 dlclose(handler); 00121 handler = NULL; 00122 } 00123 } 00124 00125 #endif