LCOV - code coverage report
Current view: top level - lunchbox - pluginRegistry.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 92 131 70.2 %
Date: 2014-10-01 Functions: 19 27 70.4 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009, Cedric Stalder <cedric.stalder@gmail.com>
       3             :  *               2010-2013, Stefan Eilemann <eile@eyescale.ch>
       4             :  *
       5             :  * This file is part of Collage <https://github.com/Eyescale/Collage>
       6             :  *
       7             :  * This library is free software; you can redistribute it and/or modify it under
       8             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       9             :  * by the Free Software Foundation.
      10             :  *
      11             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      13             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      14             :  * details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public License
      17             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      18             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             :  */
      20             : 
      21             : #include "pluginRegistry.h"
      22             : 
      23             : #include "algorithm.h"
      24             : #include "compressorInfo.h"
      25             : #include "debug.h"
      26             : #include "file.h"
      27             : #include "log.h"
      28             : #include "plugin.h"
      29             : #include "pluginVisitor.h"
      30             : 
      31             : #ifdef _WIN32
      32             : #  include "os.h" // GetModuleFileName
      33             : #  include <direct.h>
      34             : #  define getcwd _getcwd
      35             : #else
      36             : #  include <unistd.h>   // for getcwd
      37             : #endif
      38             : 
      39             : #ifndef MAXPATHLEN
      40             : #  define MAXPATHLEN 1024
      41             : #endif
      42             : 
      43             : namespace lunchbox
      44             : {
      45             : namespace detail
      46             : {
      47             : class PluginRegistry
      48             : {
      49             : public:
      50           1 :     PluginRegistry()
      51           1 :     {
      52           1 :         char* env = getenv( "EQ_PLUGIN_PATH" );
      53           1 :         std::string envString( env ? env : "" );
      54             : 
      55           1 :         if( envString.empty( ))
      56             :         {
      57             :             char cwd[MAXPATHLEN];
      58           1 :             directories.push_back( getcwd( cwd, MAXPATHLEN ));
      59             : 
      60             : #ifdef _WIN32
      61             :             if( GetModuleFileName( 0, cwd, MAXPATHLEN ) > 0 )
      62             :                 directories.push_back( lunchbox::getDirname( cwd ));
      63             : #else
      64             : #  ifdef Darwin
      65             :             env = getenv( "DYLD_LIBRARY_PATH" );
      66             : #  else
      67           1 :             env = getenv( "LD_LIBRARY_PATH" );
      68             : #  endif
      69           1 :         if( env )
      70           1 :             envString = env;
      71             : #  endif
      72             :         }
      73             : 
      74             : #ifdef _WIN32
      75             :         const char separator = ';';
      76             : #else
      77           1 :         const char separator = ':';
      78             : #endif
      79             : 
      80           4 :         while( !envString.empty( ))
      81             :         {
      82           2 :             size_t nextPos = envString.find( separator );
      83           2 :             if ( nextPos == std::string::npos )
      84           1 :                 nextPos = envString.size();
      85             : 
      86           2 :             std::string path = envString.substr( 0, nextPos );
      87           2 :             if ( nextPos == envString.size( ))
      88           1 :                 envString = "";
      89             :             else
      90           1 :                 envString = envString.substr( nextPos + 1, envString.size() );
      91             : 
      92           2 :             if( !path.empty( ))
      93           1 :                 directories.push_back( path );
      94           3 :         }
      95           1 :     }
      96             : 
      97           1 :     ~PluginRegistry()
      98           1 :     {
      99           1 :         LBASSERTINFO( plugins.empty(), "Plugin registry not de-initialized" );
     100           1 :     }
     101             : 
     102             :     Strings directories;
     103             :     Plugins plugins;
     104             : };
     105             : }
     106             : 
     107           1 : PluginRegistry::PluginRegistry()
     108           1 :     : impl_( new detail::PluginRegistry )
     109           1 : {}
     110             : 
     111           1 : PluginRegistry::~PluginRegistry()
     112             : {
     113           1 :     delete impl_;
     114           1 : }
     115             : 
     116          14 : const Strings& PluginRegistry::getDirectories() const
     117             : {
     118          14 :     return impl_->directories;
     119             : }
     120             : 
     121           1 : void  PluginRegistry::addDirectory( const std::string& path )
     122             : {
     123           1 :     impl_->directories.push_back( path );
     124           1 : }
     125             : 
     126           0 : void PluginRegistry::removeDirectory( const std::string& path )
     127             : {
     128           0 :     Strings::iterator i = find( impl_->directories, path );
     129           0 :     if( i != impl_->directories.end( ))
     130           0 :         impl_->directories.erase( i );
     131           0 : }
     132             : 
     133           1 : bool PluginRegistry::addLunchboxPlugins()
     134             : {
     135             : #ifdef LUNCHBOX_DSO_NAME
     136             :     return
     137           4 :         addPlugin( LUNCHBOX_DSO_NAME ) || // Found by LDD
     138             :         // Hard-coded compile locations as backup:
     139           1 :         addPlugin( std::string( LUNCHBOX_BUILD_DIR ) + "lib/" +
     140           3 :                    LUNCHBOX_DSO_NAME ) ||
     141             : #  ifdef NDEBUG
     142             :         addPlugin( std::string( LUNCHBOX_BUILD_DIR ) +
     143             :                    "lib/Release/" + LUNCHBOX_DSO_NAME )
     144             : #  else
     145           1 :         addPlugin( std::string( LUNCHBOX_BUILD_DIR ) + "lib/Debug/" +
     146           1 :                    LUNCHBOX_DSO_NAME )
     147             : #  endif
     148             :         ;
     149             : #endif
     150             :     return false;
     151             : }
     152             : 
     153           1 : void PluginRegistry::init()
     154             : {
     155             :     // for each directory
     156          12 :     for( StringsCIter i = impl_->directories.begin();
     157           8 :          i != impl_->directories.end(); ++i )
     158             :     {
     159           3 :         const std::string& dir = *i;
     160           3 :         LBLOG( LOG_PLUGIN ) << "Searching plugins in " << dir << std::endl;
     161             : 
     162             : #ifdef _WIN32
     163             :         const Strings& files = searchDirectory( dir, ".*Compressor.*\\.dll" );
     164             :         const char DIRSEP = '\\';
     165             : #elif defined (Darwin)
     166             :         const Strings& files = searchDirectory( dir,
     167             :                                                 "lib.*Compressor.*\\.dylib" );
     168             :         const char DIRSEP = '/';
     169             : #else
     170           3 :         const Strings& files = searchDirectory( dir, "lib.*Compressor.*\\.so" );
     171           3 :         const char DIRSEP = '/';
     172             : #endif
     173             :         // for each file found in the directory
     174           3 :         for( StringsCIter j = files.begin(); j != files.end(); ++j )
     175             :         {
     176             :             // build path + name of library
     177           0 :             const std::string libraryName = dir.empty() ? *j : dir+DIRSEP+*j;
     178           0 :             addPlugin( libraryName );
     179           0 :         }
     180           3 :     }
     181           1 : }
     182             : 
     183             : namespace
     184             : {
     185           1 : Plugin* _loadPlugin( const std::string& filename, const Strings& directories )
     186             : {
     187           1 :     if( filename.size() < 3 )
     188           0 :         return 0;
     189             : 
     190           1 :     Plugin* plugin = new Plugin( filename );
     191           1 :     if( plugin->isGood( ))
     192           1 :         return plugin;
     193           0 :     delete plugin;
     194             : 
     195           0 :     if( filename[0] == '/' || filename[1] == ':' /* Win drive letter */ )
     196           0 :         return 0;
     197             : 
     198           0 :     for( StringsCIter i = directories.begin(); i != directories.end(); ++i )
     199             :     {
     200           0 :         const std::string& dir = *i;
     201           0 :         plugin = new Plugin( dir + "/" + filename );
     202           0 :         if( plugin->isGood( ))
     203           0 :             return plugin;
     204           0 :         delete plugin;
     205             :     }
     206           0 :     return 0;
     207             : }
     208             : }
     209             : 
     210           1 : bool PluginRegistry::addPlugin( const std::string& filename )
     211             : {
     212           1 :     Plugin* plugin = _loadPlugin( filename, impl_->directories );
     213           1 :     if( !plugin )
     214           0 :         return false;
     215             : 
     216           1 :     const CompressorInfos& infos = plugin->getInfos();
     217           1 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i)
     218             :     {
     219           0 :         const CompressorInfos& infos2 = (*i)->getInfos();
     220             : 
     221             :         // Simple test to avoid loading the same dll twice
     222           0 :         if( infos.front().name == infos2.front().name )
     223             :         {
     224           0 :             delete plugin;
     225           0 :             return true;
     226             :         }
     227             :     }
     228             : 
     229           1 :     impl_->plugins.push_back( plugin );
     230           1 :     LBLOG( LOG_PLUGIN ) << "Found " << plugin->getInfos().size()
     231           1 :                         << " compression engines in " << filename << std::endl;
     232           1 :     return true;
     233             : }
     234             : 
     235           1 : void PluginRegistry::exit()
     236             : {
     237           2 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i)
     238             :     {
     239           1 :         Plugin* plugin = *i;
     240           1 :         delete plugin;
     241             :     }
     242             : 
     243           1 :     impl_->plugins.clear();
     244           1 : }
     245             : 
     246             : namespace
     247             : {
     248         304 : template< class P,  class I > class Finder : public PluginVisitorT< P, I >
     249             : {
     250             : public:
     251         304 :     explicit Finder( const uint32_t name ) : plugin( 0 ), name_( name ) {}
     252        4104 :     virtual VisitorResult visit( P& candidate, I& info )
     253             :     {
     254        4104 :         if( info.name != name_ )
     255        3800 :             return TRAVERSE_CONTINUE;
     256             : 
     257         304 :         plugin = &candidate;
     258         304 :         return TRAVERSE_TERMINATE;
     259             :     }
     260             : 
     261             :     P* plugin;
     262             : private:
     263             :     const uint32_t name_;
     264             : };
     265             : }
     266             : 
     267         304 : Plugin* PluginRegistry::findPlugin( const uint32_t name )
     268             : {
     269         304 :     Finder< Plugin, EqCompressorInfo > finder( name );
     270         304 :     accept( finder );
     271         304 :     return finder.plugin;
     272             : }
     273             : 
     274           0 : const Plugin* PluginRegistry::findPlugin( const uint32_t name ) const
     275             : {
     276           0 :     Finder< const Plugin, const EqCompressorInfo > finder( name );
     277           0 :     accept( finder );
     278           0 :     return finder.plugin;
     279             : }
     280             : 
     281         304 : VisitorResult PluginRegistry::accept( PluginVisitor& visitor )
     282             : {
     283         304 :     VisitorResult result = TRAVERSE_CONTINUE;
     284         304 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i )
     285         304 :         switch( (*i)->accept( visitor ))
     286             :         {
     287             :         case TRAVERSE_TERMINATE:
     288         304 :             return TRAVERSE_TERMINATE;
     289             :         case TRAVERSE_PRUNE:
     290           0 :             result = TRAVERSE_PRUNE;
     291             :         default:
     292           0 :             break;
     293             :         }
     294             : 
     295           0 :     return result;
     296             : }
     297           0 : VisitorResult PluginRegistry::accept( ConstPluginVisitor& visitor ) const
     298             : {
     299           0 :     VisitorResult result = TRAVERSE_CONTINUE;
     300           0 :     for( PluginsCIter i = impl_->plugins.begin(); i != impl_->plugins.end(); ++i )
     301           0 :         switch( (*i)->accept( visitor ))
     302             :         {
     303             :         case TRAVERSE_TERMINATE:
     304           0 :             return TRAVERSE_TERMINATE;
     305             :         case TRAVERSE_PRUNE:
     306           0 :             result = TRAVERSE_PRUNE;
     307             :         case TRAVERSE_CONTINUE:
     308           0 :             break;
     309             :         }
     310             : 
     311           0 :     return result;
     312             : }
     313             : 
     314           2 : const Plugins& PluginRegistry::getPlugins() const
     315             : {
     316           2 :     return impl_->plugins;
     317             : }
     318             : 
     319          90 : }

Generated by: LCOV version 1.10