TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/ofx/OfxhPluginCache.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License :
00003  *
00004  * Copyright (c) 2007-2009, The Open Effects Association Ltd.  All Rights Reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * Redistributions of source code must retain the above copyright notice,
00010  *    this list of conditions and the following disclaimer.
00011  * Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions and the following disclaimer in the documentation
00013  *    and/or other materials provided with the distribution.
00014  * Neither the name The Open Effects Association Ltd, nor the names of its
00015  *    contributors may be used to endorse or promote products derived from this
00016  *    software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00022  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00025  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 #ifndef _TUTTLE_HOST_OFX_PLUGINCACHE_HPP_
00030 #define _TUTTLE_HOST_OFX_PLUGINCACHE_HPP_
00031 
00032 #include "property/OfxhSet.hpp"
00033 #include "OfxhPluginAPICache.hpp"
00034 #include "OfxhPluginBinary.hpp"
00035 
00036 #include <ofxCore.h>
00037 
00038 #include <boost/serialization/string.hpp>
00039 #include <boost/serialization/set.hpp>
00040 #include <boost/serialization/list.hpp>
00041 #include <boost/ptr_container/serialize_ptr_list.hpp>
00042 #include <boost/foreach.hpp>
00043 
00044 #include <string>
00045 #include <set>
00046 #include <algorithm>
00047 #include <iostream>
00048 
00049 namespace tuttle {
00050 namespace host {
00051 namespace ofx {
00052 
00053 struct PluginCacheSupportedApi;
00054 
00055 /**
00056  * Where we keep our plugins.
00057  */
00058 class OfxhPluginCache
00059 {
00060 public:
00061         typedef OfxhPluginCache This;
00062         typedef boost::ptr_list<OfxhPluginBinary> OfxhPluginBinaryList;
00063 
00064 protected:
00065         std::list<std::string> _pluginPath; ///< list of directories to look in
00066         std::set<std::string> _nonrecursePath; ///< list of directories to look in (non-recursively)
00067         std::list<std::string> _pluginDirs; ///< list of directories we found
00068         
00069         OfxhPluginBinaryList _binaries; ///< all the binaries we know about, we own these
00070         std::list<OfxhPlugin*> _plugins; ///< all the plugins inside the binaries, we don't own these, populated from _binaries
00071         std::map<std::string, OfxhPlugin*> _pluginsByID;
00072         std::map<OfxhPluginIdent, bool> _loadedMap; ///< Used to check if a plugin is loaded twice
00073         std::set<std::string> _knownBinFiles;
00074 
00075         std::list<PluginCacheSupportedApi> _apiHandlers;
00076 
00077         // internal state
00078         bool _ignoreCache;
00079         std::string _cacheVersion;
00080         bool _dirty;
00081         bool _enablePluginSeek; ///< Turn off to make all seekPluginFile() calls return an empty string
00082 
00083 public:
00084         /// ctor, which inits _pluginPath to default locations and not much else
00085         OfxhPluginCache();
00086 
00087         /// dtor
00088         ~OfxhPluginCache();
00089 
00090 protected:
00091         void scanDirectory( std::set<std::string>& foundBinFiles, const std::string& dir, bool recurse );
00092 
00093         void addPlugin( OfxhPlugin* plugin );
00094 
00095 public:
00096         friend std::ostream& operator<<( std::ostream& os, const This& g );
00097 
00098 public:
00099         /// get the plugin by id.  vermaj and vermin can be specified.  if they are not it will
00100         /// pick the highest found version.
00101         OfxhPlugin*       getPluginById( const std::string& id, int vermaj = -1, int vermin = -1 );
00102         const OfxhPlugin* getPluginById( const std::string& id, int vermaj = -1, int vermin = -1 ) const { return const_cast<This&>( *this ).getPluginById( id, vermaj, vermin ); }
00103 
00104         /// get the list in which plugins are sought
00105         const std::list<std::string>& getPluginPath() const
00106         {
00107                 return _pluginPath;
00108         }
00109 
00110         /// was the cache outdated?
00111         bool isDirty() const
00112         {
00113                 return _dirty;
00114         }
00115 
00116         void setDirty()
00117         {
00118                 //TUTTLE_TLOG( TUTTLE_INFO, "OfxhPluginCache::setDirty()" );
00119                 _dirty = true;
00120         }
00121 
00122         /// add a directory to the plugin path
00123         void addDirectoryToPath( const std::string& f, bool recurse = true )
00124         {
00125                 _pluginPath.push_back( f );
00126                 if( !recurse )
00127                 {
00128                         _nonrecursePath.insert( f );
00129                 }
00130         }
00131 
00132         /// specify which subdirectory of /usr/OFX or equivilant
00133         /// (as well as 'Plugins') to look in for plugins.
00134         void setPluginHostPath( const std::string& hostId );
00135 
00136         /// set the version string to write to the cache,
00137         /// and also that we expect on cachess read in
00138         void setCacheVersion( const std::string& cacheVersion )
00139         {
00140                 _cacheVersion = cacheVersion;
00141         }
00142 
00143         // populate the cache.  must call scanPluginFiles() after to check for changes.
00144         //void readCache( std::istream& is );
00145 
00146         // seek a particular file on the OFX plugin path
00147         std::string seekPluginFile( const std::string& baseName ) const;
00148 
00149         /// Sets behaviour of seekPluginFile().
00150         /// Enable (the default): normal operation; disable: returns an empty string instead
00151         void setPluginSeekEnabled( bool enabled )
00152         {
00153                 _enablePluginSeek = enabled;
00154         }
00155 
00156         /// scan for plugins
00157         void scanPluginFiles();
00158         
00159         /// Remove all plugins
00160         void clearPluginFiles();
00161 
00162         /// register an API cache handler
00163         void registerAPICache( APICache::OfxhPluginAPICacheI& apiCache );
00164 
00165         /// find the API cache handler for the given api/apiverson
00166         APICache::OfxhPluginAPICacheI* findApiHandler( const std::string& api, int apiver );
00167 
00168         /// obtain a list of plugins to walk through
00169         const std::list<OfxhPlugin*>& getPlugins() const
00170         {
00171                 return _plugins;
00172         }
00173 
00174         OfxhPluginBinaryList& getBinaries()
00175         {
00176                 return _binaries;
00177         }
00178 
00179 private:
00180         friend class boost::serialization::access;
00181         template<class Archive>
00182         void serialize( Archive& ar, const unsigned int version )
00183         {
00184                 // ar & BOOST_SERIALIZATION_NVP(_pluginPath);
00185                 // ar & BOOST_SERIALIZATION_NVP(_nonrecursePath);
00186                 // ar & BOOST_SERIALIZATION_NVP(_pluginDirs);
00187                 ar& BOOST_SERIALIZATION_NVP( _binaries );
00188                 // ar & BOOST_SERIALIZATION_NVP(_plugins); // just a link, don't save this
00189                 // ar& BOOST_SERIALIZATION_NVP( _knownBinFiles );
00190 
00191                 if( typename Archive::is_loading() )
00192                 {
00193                         BOOST_FOREACH( OfxhPluginBinary& pluginBinary, _binaries )
00194                         {
00195                                 _knownBinFiles.insert( pluginBinary.getFilePath() );
00196                                 BOOST_FOREACH( OfxhPlugin& plugin, pluginBinary.getPlugins() )
00197                                 {
00198                                         APICache::OfxhPluginAPICacheI* apiCache = findApiHandler( plugin.getPluginApi(), plugin.getApiVersion() );
00199                                         plugin.setApiHandler( *apiCache );
00200                                         _plugins.push_back( &plugin );
00201                                 }
00202                         }
00203                 }
00204         }
00205 
00206 };
00207 
00208 }
00209 }
00210 }
00211 
00212 #endif