libzypp 17.37.17
PluginExecutor.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
11#include <iostream>
12#include <zypp/base/LogTools.h>
14
15#include <zypp/ZConfig.h>
16#include <zypp/PathInfo.h>
17#include <zypp/PluginExecutor.h>
18
19using std::endl;
20
21#undef ZYPP_BASE_LOGGER_LOGGROUP
22#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
23
25namespace zypp
26{
32 {
33 public:
35 {}
36
37 Impl(const Impl &) = delete;
38 Impl(Impl &&) = delete;
39 Impl &operator=(const Impl &) = delete;
40 Impl &operator=(Impl &&) = delete;
41
43 if ( ! empty() )
44 send( PluginFrame( "PLUGINEND" ) );
45 // ~PluginScript will disconnect all remaining plugins!
46 }
47
48 bool empty() const
49 { return _scripts.empty(); }
50
51 size_t size() const
52 { return _scripts.size(); }
53
54 void load( const Pathname & path_r )
55 {
56 PathInfo pi( path_r );
57 DBG << "+++++++++++++++ load " << pi << endl;
58 if ( pi.isDir() )
59 {
60 std::list<Pathname> entries;
61 if ( filesystem::readdir( entries, pi.path(), false ) != 0 )
62 {
63 WAR << "Plugin dir is not readable: " << pi << endl;
64 return;
65 }
66 for_( it, entries.begin(), entries.end() )
67 {
68 PathInfo pii( *it );
69 if ( pii.isFile() && pii.userMayRX() )
70 doLoad( pii );
71 }
72 }
73 else if ( pi.isFile() )
74 {
75 if ( pi.userMayRX() )
76 doLoad( pi );
77 else
78 WAR << "Plugin file is not executable: " << pi << endl;
79 }
80 else
81 {
82 WAR << "Plugin path is neither dir nor file: " << pi << endl;
83 }
84 DBG << "--------------- load " << pi << endl;
85 }
86
87 void send( const PluginFrame & frame_r )
88 {
89 DBG << "+++++++++++++++ send " << frame_r << endl;
90 for ( auto it = _scripts.begin(); it != _scripts.end(); )
91 {
92 doSend( *it, frame_r );
93 if ( it->isOpen() )
94 ++it;
95 else
96 it = _scripts.erase( it );
97 }
98 DBG << "--------------- send " << frame_r << endl;
99 }
100
101 const std::list<PluginScript> scripts() const
102 { return _scripts; }
103
104 private:
106 void doLoad( const PathInfo & pi_r )
107 {
108 MIL << "Load plugin: " << pi_r << endl;
109 try {
110 PluginScript plugin( pi_r.path() );
111 plugin.open();
112
113 PluginFrame frame( "PLUGINBEGIN" );
114 if ( ZConfig::instance().hasUserData() )
115 frame.setHeader( "userdata", ZConfig::instance().userData() );
116
117 doSend( plugin, frame ); // closes on error
118 if ( plugin.isOpen() )
119 _scripts.push_back( plugin );
120 }
121 catch( const zypp::Exception & e )
122 {
123 WAR << "Failed to load plugin " << pi_r << endl;
124 }
125 }
126
127 PluginFrame doSend( PluginScript & script_r, const PluginFrame & frame_r )
128 {
129 PluginFrame ret;
130
131 try {
132 script_r.send( frame_r );
133 ret = script_r.receive();
134 }
135 catch( const zypp::Exception & e )
136 {
137 ZYPP_CAUGHT(e);
138 WAR << e.asUserHistory() << endl;
139 }
140
141 // Allow using "/bin/cat" as reflector-script for testing
142 if ( ! ( ret.isAckCommand() || ret.isEnomethodCommand() || ( script_r.script() == "/bin/cat" && frame_r.command() != "ERROR" ) ) )
143 {
144 WAR << "Bad plugin response from " << script_r << ": " << ret << endl;
145 WAR << "(Expected " << PluginFrame::ackCommand() << " or " << PluginFrame::enomethodCommand() << ")" << endl;
146 script_r.close();
147 }
148
149 return ret;
150 }
151 private:
152 std::list<PluginScript> _scripts;
153 };
154
156 //
157 // CLASS NAME : PluginExecutor
158 //
160
164
167
169 { return _pimpl->empty(); }
170
171 size_t PluginExecutor::size() const
172 { return _pimpl->size(); }
173
174 void PluginExecutor::load( const Pathname & path_r )
175 { _pimpl->load( path_r ); }
176
177 void PluginExecutor::send( const PluginFrame & frame_r )
178 { _pimpl->send( frame_r ); }
179
180 std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj )
181 { return str << obj._pimpl->scripts(); }
182
183} // namespace zypp
Base class for Exception.
Definition Exception.h:153
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:140
PluginExecutor implementation.
Impl & operator=(Impl &&)=delete
PluginFrame doSend(PluginScript &script_r, const PluginFrame &frame_r)
void doLoad(const PathInfo &pi_r)
Launch a plugin sending PLUGINSTART message.
std::list< PluginScript > _scripts
Impl & operator=(const Impl &)=delete
Impl(const Impl &)=delete
const std::list< PluginScript > scripts() const
void send(const PluginFrame &frame_r)
void load(const Pathname &path_r)
RW_pointer< Impl > _pimpl
Implementation class.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
size_t size() const
Number of open plugins.
PluginExecutor()
Default ctor: Empty plugin list.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
~PluginExecutor()
Dtor: Send PLUGINEND and close all plugins.
bool empty() const
Whether no plugins are waiting.
Command frame for communication with PluginScript.
Definition PluginFrame.h:42
static const std::string & ackCommand()
"ACK" command.
static const std::string & enomethodCommand()
"_ENOMETHOD" command.
const std::string & command() const
Return the frame command.
bool isEnomethodCommand() const
Convenience to identify an _ENOMETHOD command.
void setHeader(const std::string &key_r, const std::string &value_r=std::string())
Set header for key_r removing all other occurrences of key_r.
bool isAckCommand() const
Convenience to identify an ACK command.
Interface to plugin scripts using a Stomp inspired communication protocol.
PluginFrame receive() const
Receive a PluginFrame.
void send(const PluginFrame &frame_r) const
Send a PluginFrame.
int close()
Close any open connection.
void open()
Setup connection and execute script.
const Pathname & script() const
Return the script path if set.
bool isOpen() const
Whether we are connected to a script.
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:940
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const Pathname & path() const
Return current Pathname.
Definition PathInfo.h:251
String related utilities and Regular expression matching.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition PathInfo.cc:610
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
#define DBG
Definition Logger.h:99
#define MIL
Definition Logger.h:100
#define WAR
Definition Logger.h:101