Ejemplo n.º 1
0
void PluginManager::loadDynamicPlugins(std::string& plugins_path)
{
    LOG_DEBUG("Loading dynamic plugins");
    Poco::Path plugin_directory = Poco::Path::forDirectory(plugins_path);
    plugin_directory.popDirectory();
    plugin_directory.pushDirectory("plugins");
    LOG_DEBUG("Plugin directory: " << plugin_directory.toString());
    std::set<std::string> dll_files;
    Poco::Glob::glob(plugin_directory.append(DynamicLibrary::DL_PREFIX+
                                             "*."+
                                             DynamicLibrary::DL_SUFFIX), 
                     dll_files);

    for (std::set<std::string>::iterator it = dll_files.begin(); 
         it!=dll_files.end(); 
         ++it)
    {
        std::string plugin_file = *it;
        LOG_DEBUG("Loading library " << plugin_file);
        DynamicLibrary* dl = DynamicLibrary::load(plugin_file);
        registerPluginFunction registerPlugin = 
            (registerPluginFunction)dl->getSymbol("registerPlugin");
        if (registerPlugin)
        {
            LOG_DEBUG("Initialize Plugin " << *it);
            registerPlugin(this);
        } else
        {
            LOG_WARN("Couldn't find registerPlugin for " << *it);
        }
    }

}
Ejemplo n.º 2
0
Engine::ModuleSpec Engine::createModule(const String& Filename)
{
	try
	{
		DynamicLibrary* lib = AURORA_NEW DynamicLibrary(Filename);
		Module* (*moduleCreateFunc)();
		// Ugly, ugly cast
		moduleCreateFunc = reinterpret_cast<Module*(*)()>(lib->getSymbol("createInstance"));

		if (moduleCreateFunc)
		{
			Module* m = moduleCreateFunc();
			if (!m)
				throw BadModuleException();
			else
			{
				ModuleSpec spec;
				spec.Category = m->getCategory();
				spec.Name = m->getName();
				spec.Lib = lib;
				spec.Mod = m;
				spec.SourceFilename = Filename;
				spec.Installed = false;

				return spec;
			}
		}
		else throw BadModuleException();
	}
	catch (LibraryCallException&)
	{
		// Something's bad in the module, don't rethrow an internal error to the caller
		throw BadModuleException();
	}
}
Ejemplo n.º 3
0
void DynamicLibraryTest::RunTests()
{
  DynamicLibrary * d = NULL;

  // Try to load "empty" library
  {
    string errorString;
    d = DynamicLibrary::load("", errorString);
    TEST2("Shouldn't be able to load \"\" library", d == NULL); 
    TEST2("Should have non-empty error string", errorString.size() != 0);
  }
   
  // Try to load non-existent library
  string s("non_exisiting_file");
  Path path(s);
  
  TEST2("Make sure file doesn't exist", !path.exists());
 
  { 
    string errorString;
    d = DynamicLibrary::load(s, errorString);
  }

  TEST2("Shouldn't be able to load non-existent library", d == NULL);
  delete d; // just to satisfy coverity, not really needed, but harmless

  // Try to load corrupt library (this source file)
#ifdef WIN32
  s = "lib\\cpp_region.dll";
  path = getPath(s);
#else
  s = "share/test/data/fake.dynamic.library";
  path = getPath(s);
  TEST2("Make sure \"corrupt\" file exists", path.exists());  

  {
    string errorString;
    d = DynamicLibrary::load(std::string(path), errorString);
  }
  TEST2("Shouldn't be able to load corrupt library", d == NULL);

  // Load good library (very inelegant way to handle different suffix on mac and linux)
  s = "lib/libcpp_region.dylib";
  path = getPath(s);
  if (!path.exists())
  {
    s = "lib/libcpp_region.so";
    path = getPath(s);
  }
#endif

  std::cout << "Looking for path '" << path << "'\n";
  TEST2("Make sure file exists", path.exists());
  {
    string errorString;
    d = DynamicLibrary::load(std::string(path), errorString);
    TEST2("Should be able to load good library", d != NULL);
    TEST2("Should have empty error string", errorString.empty());
    if (!errorString.empty())
    {
      std::cout << "Error String: " << errorString << "\n";
    }
  }
  
  
  if (d) {
    // Get existing symbol
    void * sym = d->getSymbol("NTA_initPython");
    TEST2("Should be able to get 'NTA_initPython' symbol", sym != NULL);
    
    // Get non-existing symbol
    sym = d->getSymbol("non exisitng symbol");
    TEST2("Should NOT be able to get 'non exisitng symbol' symbol", sym == NULL);
    delete d;    
  }
}
SteerLib::ModuleMetaInformation * SimulationEngine::_loadModule(const std::string & moduleName, const std::string & searchPath)
{
	// check that the requested moduleName is not already "blacklisted" as a conflict from some other loaded module.
	if (_moduleConflicts.find(moduleName) != _moduleConflicts.end()) {
		std::stringstream conflictingNames;
		std::multimap<std::string, std::string>::iterator iter;
		pair< std::multimap<std::string, std::string>::iterator, std::multimap<std::string, std::string>::iterator > bounds;
		bounds = _moduleConflicts.equal_range(moduleName);
		for ( iter = bounds.first; iter != bounds.second; ++iter ) {
			conflictingNames << "  " << (*iter).second << "\n";
		}
		throw GenericException("Cannot load module \"" + moduleName + "\", because it conflicts with the following modules:\n" + conflictingNames.str());
	}

	ModuleMetaInformation * newMetaInfo = NULL;
	std::map<std::string, ModuleMetaInformation*>::iterator iter;

	// THREE POSSIBLE STATES OF THE MODULE when we are trying to load it:
	//  1. metaInfo not allocated
	//  2. metaInfo allocated, but module not loaded
	//  3. metaInfo allocated and module loaded.
	iter = _moduleMetaInfoByName.find(moduleName);
	if (iter == _moduleMetaInfoByName.end()) {
		// CASE #1: module was not allocated yet.
		// This is the usual case, and module loading can proceed normally.
		// action: go ahead and allocate it here, and then finish loading it below.
		newMetaInfo = new ModuleMetaInformation;
		newMetaInfo->isLoaded = false;
		newMetaInfo->isInitialized = false;
		// note, this syntax inserts the newMetaInfo when it does not already exist (which is the case here).
		_moduleMetaInfoByName[moduleName] = newMetaInfo;
	}
	else {
		newMetaInfo = ((*iter).second);
		if (!newMetaInfo->isLoaded) {
			// CASE #2: module is allocated, not loaded.
			// That means the module was recursively loading dependencies, and somehow 
			// ended up trying to re-load itself. In other words, it is a cyclic dependency.
			// action: throw an exception.
			/// @todo make a more informative error message here.
			throw GenericException("Detected a cyclic dependency while loading a module.  Please examine a stack trace to see more details.");
		}
		else {
			// CASE #4: module is already loaded.
			// action: just return.
			return newMetaInfo;
		}
	}


	// at this point we are ready to "load" the module.
	// "loading" the module means that we can initialize everything in the ModuleMetaInformation struct
	// and update all the engine's data structures that have knowledge of the module.  Essentially,
	// everything except establishing execution order and calling init().

	ModuleInterface * newModule = NULL;
	DynamicLibrary * newModuleLib = NULL;

	// first, check if the requested module is built-in, and create it if it was built in.
	newModule = _createBuiltInModule(moduleName);

	if (newModule == NULL) {
		// In this case, the module was not built-in.
#ifdef _WIN32
		std::string extension = ".dll";
#else
		std::string extension = ".o";
#endif

		std::string moduleFileName = searchPath + moduleName + extension;
		if (!isExistingFile(moduleFileName)) {
			moduleFileName = _options->engineOptions.moduleSearchPath + moduleName + extension;  // if module wasn't found in the searchPath directory, try with the default search path.
			if (!isExistingFile(moduleFileName)) {
				moduleFileName = moduleName + extension;  // if it still wasnt found, try without the search path
				if (!isExistingFile(moduleFileName)) {
					// if it still didn't work, then cause an error.
					throw GenericException("Could not find the module named \"" + moduleName + "\".\n" +
						"  tried user-specified search path: " + searchPath + moduleName + extension +"\n" +
						"  tried engine's search path: " + _options->engineOptions.moduleSearchPath + moduleName + extension +"\n" +
						"  tried the current directory: " + moduleName + extension +"\n");
				}
			}
		}


		// load the dynamic library
		newModuleLib = new DynamicLibrary(moduleFileName);

		// get the "createModule" function from the dynamic library
		typedef ModuleInterface* (*createModuleFuncPtr)();
		createModuleFuncPtr createModule = (createModuleFuncPtr) newModuleLib->getSymbol("createModule", true);

		// create the module itself
		newModule = createModule();
		if (newModule == NULL) {
			throw GenericException("Could not create module \"" + moduleName + "\", createModule() returned NULL.");
		}
	}


	// the next several chunks of code initialize newMetaInfo:

	// get the dependencies and conflicts from the module, and parse them.
	std::istringstream conflicts(newModule->getConflicts());
	std::istringstream dependencies(newModule->getDependencies());
	std::string token;
	while (conflicts >> token) {
		// the token is one of the conflicts declared by the module
		// make sure it does not yet exist in the set of loaded modules
		// and add it to the list of conflicting modules
		if (_moduleMetaInfoByName.find(token) != _moduleMetaInfoByName.end()) {
			// if the token is found here, that means we have a conflict.
			throw GenericException("Cannot load module \"" + moduleName + "\", because it conflicts with already loaded module \"" + (*_moduleMetaInfoByName.find(token)).second->moduleName);
		}
		newMetaInfo->conflicts.insert(token);
		_moduleConflicts.insert( std::pair<std::string, std::string>(token , moduleName));
	}


	// initialize the simpler data of meta information here
	newMetaInfo->moduleName = moduleName;
	newMetaInfo->module = newModule;
	newMetaInfo->dll = newModuleLib;  // note, this will be NULL for a built-in library.

	newMetaInfo->isLoaded = true;

	// at this point, everything in newMetaInfo should be initialized except for:
	//  - isLoaded is still false until we finish loading below
	//  - isInitialized is still false until we call init() later, outside this function
	//  - list of dependencies is not populated until we load the dependencies
	//  - list of modulesDependentOnThis is initialized at this point, but its contents may change, 
	//    if other modules are loaded that are dependent on this.

	// next, add the newMetaInfo and module to the engine's organizational data structures.
	// _moduleMetaInfoByName is updated earlier
	// _modulesInExecutionOrder is updated after loading all dependencies, so that execution order is maintained
	_moduleMetaInfoByReference[newModule] = newMetaInfo;

	//================
	// everything is loaded except for dependencies; recursively load all dependencies here.
	while (dependencies >> token) {
		ModuleMetaInformation * dependency = _loadModule(token,searchPath);
		dependency->modulesDependentOnThis.insert(newMetaInfo);
		newMetaInfo->dependencies.insert(dependency);
	}

	//================
	// If an entry in the moduleOptionsDatabase did not yet exist, then create one.
	// recall that the [] operator for an STL map will create a new entry if one did not exist by that key already,
	_options->moduleOptionsDatabase[newMetaInfo->moduleName];

	//================
	// if all went well up to this point, the module and its dependencies is loaded, so add it to the end of the list of modules
	// (i.e. it executes after all its dependencies) and return!
	_modulesInExecutionOrder.push_back(newModule);
	std::cout << "loaded module " << newMetaInfo->moduleName << "\n";

	return newMetaInfo;
}