WvStreams
modulemgr.cc
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * XPLC - Cross-Platform Lightweight Components
00004  * Copyright (C) 2002-2004, Net Integration Technologies, Inc.
00005  * Copyright (C) 2002-2004, Pierre Phaneuf
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020  * USA
00021  */
00022 
00023 #include <assert.h>
00024 #include "modulemgr.h"
00025 #include <xplc/IModuleLoader.h>
00026 
00027 #include "config.h"
00028 
00029 #ifdef HAVE_STDINT_H
00030 # include <stdint.h>
00031 #endif
00032 #ifdef HAVE_LIMITS_H
00033 # include <limits.h>
00034 #endif
00035 
00036 #if !defined(WIN32)
00037 # if HAVE_DIRENT_H
00038 #  include <dirent.h>
00039 #  define NAMLEN(dirent) strlen((dirent)->d_name)
00040 # else
00041 #  define dirent direct
00042 #  define NAMLEN(dirent) (dirent)->d_namlen
00043 #  if HAVE_SYS_NDIR_H
00044 #   include <sys/ndir.h>
00045 #  endif
00046 #  if HAVE_SYS_DIR_H
00047 #   include <sys/dir.h>
00048 #  endif
00049 #  if HAVE_NDIR_H
00050 #   include <ndir.h>
00051 #  endif
00052 # endif
00053 #else
00054 # include <io.h>
00055 #endif
00056 
00057 #include <stdio.h>
00058 
00059 UUID_MAP_BEGIN(ModuleManagerFactory)
00060   UUID_MAP_ENTRY(IObject)
00061   UUID_MAP_ENTRY(IModuleManagerFactory)
00062   UUID_MAP_END
00063 
00064 UUID_MAP_BEGIN(ModuleManager)
00065   UUID_MAP_ENTRY(IObject)
00066   UUID_MAP_ENTRY(IServiceHandler)
00067   UUID_MAP_END
00068 
00069 struct ModuleNode {
00070   ModuleNode* next;
00071   IModule* module;
00072   ModuleNode(IModule* aModule, ModuleNode* aNext):
00073     next(aNext), module(aModule) {
00074     assert(module);
00075   }
00076   ~ModuleNode() {
00077     if(module)
00078       module->release();
00079   }
00080 };
00081 
00082 IServiceHandler* ModuleManagerFactory::createModuleManager(const char* directory) {
00083 #if !defined(WIN32)
00084   DIR* dir;
00085   struct dirent* ent;
00086   char fname[PATH_MAX];
00087   IServiceManager* servmgr = XPLC_getServiceManager();
00088   IModuleLoader* loader;
00089   ModuleNode* modules = 0;
00090 
00091   if(!servmgr)
00092     return 0;
00093 
00094   loader = mutate<IModuleLoader>(servmgr->getObject(XPLC_moduleLoader));
00095   servmgr->release();
00096   if(!loader)
00097     return 0;
00098 
00099   dir = opendir(directory);
00100   if(!dir) {
00101     loader->release();
00102     return 0;
00103   }
00104 
00105   rewinddir(dir);
00106   while((ent = readdir(dir))) {
00107     IModule* module;
00108 
00109     snprintf(fname, PATH_MAX, "%s/%s", directory, ent->d_name);
00110 
00111     module = loader->loadModule(fname);
00112     if(module) {
00113       ModuleNode* node = new ModuleNode(module, modules);
00114 
00115       if(node)
00116         modules = node;
00117     }
00118   }
00119 
00120   loader->release();
00121 
00122   closedir(dir);
00123 
00124   return new ModuleManager(modules);
00125 
00126 #else
00127 
00128   intptr_t dir;
00129   _finddata_t ent;
00130   char fname[4096];
00131   char pattern[4096];
00132   IServiceManager* servmgr = XPLC_getServiceManager();
00133   IModuleLoader* loader;
00134   ModuleNode* modules = 0;
00135 
00136   if(!servmgr)
00137     return 0;
00138 
00139   loader = mutate<IModuleLoader>(servmgr->getObject(XPLC_moduleLoader));
00140   servmgr->release();
00141   if(!loader)
00142     return 0;
00143 
00144   snprintf(pattern, sizeof(pattern), "%s/*.*", directory);
00145 
00146   dir = _findfirst(pattern, &ent);
00147 
00148   if(!dir) {
00149     loader->release();
00150     return 0;
00151   }
00152 
00153   do {
00154     IModule* module;
00155 
00156     _snprintf(fname, sizeof(fname), "%s/%s", directory, ent.name);
00157 
00158     module = loader->loadModule(fname);
00159     if(module) {
00160       ModuleNode* node = new ModuleNode(module, modules);
00161 
00162       if(node)
00163         modules = node;
00164     }
00165   } while(_findnext(dir, &ent) == 0);
00166 
00167   loader->release();
00168 
00169   _findclose(dir);
00170 
00171   return new ModuleManager(modules);
00172 #endif
00173 }
00174 
00175 ModuleManager::ModuleManager(ModuleNode* aModules):
00176   modules(aModules) {
00177 }
00178 
00179 IObject* ModuleManager::getObject(const UUID& cid) {
00180   ModuleNode* node = modules;
00181 
00182   while(node) {
00183     IObject* obj = node->module->getObject(cid);
00184 
00185     if(obj)
00186       return obj;
00187 
00188     node = node->next;
00189   }
00190 
00191   return 0;
00192 }
00193 
00194 ModuleManager::~ModuleManager() {
00195   ModuleNode* node = modules;
00196 
00197   while(node) {
00198     ModuleNode* next = node->next;
00199 
00200     delete node;
00201 
00202     node = next;
00203   }
00204 }
00205