libzypp 9.41.1

PluginExecutor.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00011 #include <iostream>
00012 #include "zypp/base/LogTools.h"
00013 #include "zypp/base/NonCopyable.h"
00014 
00015 #include "zypp/ZConfig.h"
00016 #include "zypp/PathInfo.h"
00017 #include "zypp/PluginExecutor.h"
00018 
00019 using std::endl;
00020 
00021 #undef  ZYPP_BASE_LOGGER_LOGGROUP
00022 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
00023 
00025 namespace zypp
00026 {
00031   class PluginExecutor::Impl : private base::NonCopyable
00032   {
00033   public:
00034     Impl()
00035     {}
00036 
00037     ~Impl()
00038     {
00039       if ( ! empty() )
00040         send( PluginFrame( "PLUGINEND" ) );
00041       // ~PluginScript will disconnect all remaining plugins!
00042     }
00043 
00044     bool empty() const
00045     { return _scripts.empty(); }
00046 
00047     size_t size() const
00048     { return _scripts.size(); }
00049 
00050     void load( const Pathname & path_r )
00051     {
00052       PathInfo pi( path_r );
00053       DBG << "+++++++++++++++ load " << pi << endl;
00054       if ( pi.isDir() )
00055       {
00056         std::list<Pathname> entries;
00057         if ( filesystem::readdir( entries, pi.path(), false ) != 0 )
00058         {
00059           WAR << "Plugin dir is not readable: " << pi << endl;
00060           return;
00061         }
00062         for_( it, entries.begin(), entries.end() )
00063         {
00064           PathInfo pii( *it );
00065           if ( pii.isFile() && pii.userMayRX() )
00066             doLoad( pii );
00067         }
00068       }
00069       else if ( pi.isFile() )
00070       {
00071         if ( pi.userMayRX() )
00072           doLoad( pi );
00073         else
00074           WAR << "Plugin file is not executable: " << pi << endl;
00075       }
00076       else
00077       {
00078         WAR << "Plugin path is neither dir nor file: " << pi << endl;
00079       }
00080       DBG << "--------------- load " << pi << endl;
00081     }
00082 
00083     void send( const PluginFrame & frame_r )
00084     {
00085       DBG << "+++++++++++++++ send " << frame_r << endl;
00086       for ( std::list<PluginScript>::iterator it = _scripts.begin(); it != _scripts.end(); )
00087       {
00088         doSend( *it, frame_r );
00089         if ( it->isOpen() )
00090           ++it;
00091         else
00092           it = _scripts.erase( it );
00093       }
00094       DBG << "--------------- send " << frame_r << endl;
00095     }
00096 
00097     const std::list<PluginScript> scripts() const
00098     { return _scripts; }
00099 
00100   private:
00102     void doLoad( const PathInfo & pi_r )
00103     {
00104       MIL << "Load plugin: " << pi_r << endl;
00105       try {
00106         PluginScript plugin( pi_r.path() );
00107         plugin.open();
00108 
00109         PluginFrame frame( "PLUGINBEGIN" );
00110         if ( ZConfig::instance().hasUserData() )
00111           frame.setHeader( "userdata", ZConfig::instance().userData() );
00112 
00113         doSend( plugin, frame );        // closes on error
00114         if ( plugin.isOpen() )
00115           _scripts.push_back( plugin );
00116       }
00117       catch( const zypp::Exception & e )
00118       {
00119         WAR << "Failed to load plugin " << pi_r << endl;
00120       }
00121     }
00122 
00123     PluginFrame doSend( PluginScript & script_r, const PluginFrame & frame_r )
00124     {
00125       PluginFrame ret;
00126 
00127       try {
00128         script_r.send( frame_r );
00129         ret = script_r.receive();
00130       }
00131       catch( const zypp::Exception & e )
00132       {
00133         ZYPP_CAUGHT(e);
00134         WAR << e.asUserHistory() << endl;
00135       }
00136 
00137       // Allow using "/bin/cat" as reflector-script for testing
00138       if ( ! ( ret.isAckCommand() || ret.isEnomethodCommand() || ( script_r.script() == "/bin/cat" && frame_r.command() != "ERROR" ) ) )
00139       {
00140         WAR << "Bad plugin response from " << script_r << ": " << ret << endl;
00141         WAR << "(Expected " << PluginFrame::ackCommand() << " or " << PluginFrame::enomethodCommand() << ")" << endl;
00142         script_r.close();
00143       }
00144 
00145       return ret;
00146     }
00147   private:
00148     std::list<PluginScript> _scripts;
00149   };
00150 
00152   //
00153   //    CLASS NAME : PluginExecutor
00154   //
00156 
00157   PluginExecutor::PluginExecutor()
00158     : _pimpl( new Impl() )
00159   {}
00160 
00161   PluginExecutor::~PluginExecutor()
00162   {}
00163 
00164   bool PluginExecutor::empty() const
00165   { return _pimpl->empty(); }
00166 
00167   size_t PluginExecutor::size() const
00168   { return _pimpl->size(); }
00169 
00170   void PluginExecutor::load( const Pathname & path_r )
00171   { _pimpl->load( path_r ); }
00172 
00173   void PluginExecutor::send( const PluginFrame & frame_r )
00174   { _pimpl->send( frame_r ); }
00175 
00176   std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj )
00177   { return str << obj._pimpl->scripts(); }
00178 
00179 } // namespace zypp