/*############################################################################## Copyright (C) 2011 HPCC Systems. All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . ############################################################################## */ #include "PluginDeploymentEngine.hpp" #include // for path functions //##################################################################################################### //# NOTE: Plugins can no longer be shared and deployed as a component. To avoid version conflicts, # //# any component using a plugin (currently only ecl/attr servers) must deploy any necessary # //# plugins as part of its deployment. # //# This (pre-existing) class merely serves as a base class for components that need plugins. # //##################################################################################################### //--------------------------------------------------------------------------- // CPluginDeploymentEngine //--------------------------------------------------------------------------- CPluginDeploymentEngine::CPluginDeploymentEngine(IEnvDeploymentEngine& envDepEngine, IConstEnvironment& environment, IPropertyTree& process, const char* instanceType/*=NULL*/) : CDeploymentEngine(envDepEngine, environment, process, instanceType) { } //--------------------------------------------------------------------------- // getPluginDirectory // // returns absolute path where plugins are to be deployed //--------------------------------------------------------------------------- void CPluginDeploymentEngine::getPluginDirectory(const char* destPath, StringBuffer& sPluginDest) const { sPluginDest.clear().append(destPath); sPluginDest.replace('\\', '/'); StringBuffer sPluginsDir; //relative path (from ECL server installation directory) for plugins m_process.getProp("@pluginsPath", sPluginsDir); if (sPluginsDir.length()) { sPluginsDir.replace('\\', '/'); sPluginsDir.replace('$', ':'); if (! ::PathIsRelative(sPluginsDir.str())) throw MakeStringExceptionDirect(-1, "Plugins path for ECL server must be relative to its installation directory!"); if (!strncmp(sPluginsDir.str(), "./", 2)) sPluginsDir.remove(0, 2); sPluginDest.append(sPluginsDir); } const char* pchLast = sPluginDest.str() + sPluginDest.length() - 1; if (*pchLast != '/') sPluginDest.append('/'); } //--------------------------------------------------------------------------- // getDefaultPlugins //--------------------------------------------------------------------------- void CPluginDeploymentEngine::getDefaultPlugins(StringArray& plugins, StringBuffer& sPluginsPath, const char* destDir) const { mmapStr2PairStrStr fileMap; CDeploymentEngine::createInstallFileMap(m_process, ".", fileMap); // Get install file list and sort out plugins mmapStr2PairStrStr::const_iterator i; mmapStr2PairStrStr::const_iterator iEnd = fileMap.end(); for (i=fileMap.begin(); i != iEnd; i++) { const char* dest = (*i).first.c_str(); const char* ext = ::PathFindExtension(dest); if (ext && *ext) { if (stricmp(ext, ".ecl")==0 || stricmp(ext, ".eclmod")==0) { if (plugins.find(dest) == NotFound) { plugins.append(dest); sPluginsPath.append(dest).append(';'); } } else // Check that file matches plugin path .\plugins or ./plugins as specified in the release_eclserver file if (strlen(dest) > 2 && *dest == '.' && (*(dest+1)=='\\' || *(dest+1)=='/') && strnicmp(dest+2, "plugins", sizeof("plugins")-1) == 0) { // Append plugin to files list - only care about dlls if (stricmp(ext, ".dll")==0 || stricmp(ext, ".so")==0) { StringBuffer path(destDir); path.append(::PathFindFileName( dest )); if (plugins.find(path.str()) == NotFound) { plugins.append(path.str()); sPluginsPath.append(path.str()).append(';'); } } } } } } //--------------------------------------------------------------------------- // getPlugins //--------------------------------------------------------------------------- void CPluginDeploymentEngine::getPlugins(StringArray& plugins, StringBuffer& sPluginsPath, const char* pluginDest) const { // Iterate through plugin references Owned iter = m_process.getElements("PluginRef"); ForEach(*iter) { // Lookup plugin process const char* pluginName = iter->query().queryProp("@process"); IPropertyTree* pluginProcess = lookupProcess("PluginProcess", pluginName); if (!pluginProcess) throw MakeStringException(0, "Process %s references unknown plugin %s", m_name, pluginName); // Get plugin file list from the plugin process mmapStr2PairStrStr fileMap; CDeploymentEngine::createInstallFileMap(*pluginProcess, pluginDest, fileMap); mmapStr2PairStrStr::const_iterator i; mmapStr2PairStrStr::const_iterator iEnd = fileMap.end(); for (i=fileMap.begin(); i != iEnd; i++) { const char* dest = (*i).first.c_str(); const char* ext = ::PathFindExtension(dest); // Append plugin to files list - only care about dll/so if (ext && (stricmp(ext, ".dll")==0 || stricmp(ext, ".so")==0) && plugins.find(dest) == NotFound) { plugins.append(dest); sPluginsPath.append(dest).append(';'); } } } } //--------------------------------------------------------------------------- // createInstallFileMap //--------------------------------------------------------------------------- int CPluginDeploymentEngine::createInstallFileMap(IPropertyTree& node, const char* destPath, mmapStr2PairStrStr& fileMap) const { CDeploymentEngine::createInstallFileMap(node, destPath, fileMap); //get files for plugin references... // StringBuffer sPluginDest; getPluginDirectory(destPath, sPluginDest);//get absolute path where plugins are to be deployed //process plugin references for this eclserver process and add files for each service used by //each binding before adding files for this esp process Owned iter = m_process.getElements("PluginRef"); ForEach(*iter) { // Lookup plugin process const char* pluginName = iter->query().queryProp("@process"); IPropertyTree* pluginProcess = lookupProcess("PluginProcess", pluginName); if (!pluginProcess) throw MakeStringException(0, "Process %s references unknown plugin %s", m_name, pluginName); // Get plugin file list from the plugin process CDeploymentEngine::createInstallFileMap(*pluginProcess, sPluginDest.str(), fileMap); } return fileMap.size(); }