libzypp 17.31.0
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>
13#include <zypp/base/NonCopyable.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
38 {
39 if ( ! empty() )
40 send( PluginFrame( "PLUGINEND" ) );
41 // ~PluginScript will disconnect all remaining plugins!
42 }
43
44 bool empty() const
45 { return _scripts.empty(); }
46
47 size_t size() const
48 { return _scripts.size(); }
49
50 void load( const Pathname & path_r )
51 {
52 PathInfo pi( path_r );
53 DBG << "+++++++++++++++ load " << pi << endl;
54 if ( pi.isDir() )
55 {
56 std::list<Pathname> entries;
57 if ( filesystem::readdir( entries, pi.path(), false ) != 0 )
58 {
59 WAR << "Plugin dir is not readable: " << pi << endl;
60 return;
61 }
62 for_( it, entries.begin(), entries.end() )
63 {
64 PathInfo pii( *it );
65 if ( pii.isFile() && pii.userMayRX() )
66 doLoad( pii );
67 }
68 }
69 else if ( pi.isFile() )
70 {
71 if ( pi.userMayRX() )
72 doLoad( pi );
73 else
74 WAR << "Plugin file is not executable: " << pi << endl;
75 }
76 else
77 {
78 WAR << "Plugin path is neither dir nor file: " << pi << endl;
79 }
80 DBG << "--------------- load " << pi << endl;
81 }
82
83 void send( const PluginFrame & frame_r )
84 {
85 DBG << "+++++++++++++++ send " << frame_r << endl;
86 for ( auto it = _scripts.begin(); it != _scripts.end(); )
87 {
88 doSend( *it, frame_r );
89 if ( it->isOpen() )
90 ++it;
91 else
92 it = _scripts.erase( it );
93 }
94 DBG << "--------------- send " << frame_r << endl;
95 }
96
97 const std::list<PluginScript> scripts() const
98 { return _scripts; }
99
100 private:
102 void doLoad( const PathInfo & pi_r )
103 {
104 MIL << "Load plugin: " << pi_r << endl;
105 try {
106 PluginScript plugin( pi_r.path() );
107 plugin.open();
108
109 PluginFrame frame( "PLUGINBEGIN" );
110 if ( ZConfig::instance().hasUserData() )
111 frame.setHeader( "userdata", ZConfig::instance().userData() );
112
113 doSend( plugin, frame ); // closes on error
114 if ( plugin.isOpen() )
115 _scripts.push_back( plugin );
116 }
117 catch( const zypp::Exception & e )
118 {
119 WAR << "Failed to load plugin " << pi_r << endl;
120 }
121 }
122
123 PluginFrame doSend( PluginScript & script_r, const PluginFrame & frame_r )
124 {
125 PluginFrame ret;
126
127 try {
128 script_r.send( frame_r );
129 ret = script_r.receive();
130 }
131 catch( const zypp::Exception & e )
132 {
133 ZYPP_CAUGHT(e);
134 WAR << e.asUserHistory() << endl;
135 }
136
137 // Allow using "/bin/cat" as reflector-script for testing
138 if ( ! ( ret.isAckCommand() || ret.isEnomethodCommand() || ( script_r.script() == "/bin/cat" && frame_r.command() != "ERROR" ) ) )
139 {
140 WAR << "Bad plugin response from " << script_r << ": " << ret << endl;
141 WAR << "(Expected " << PluginFrame::ackCommand() << " or " << PluginFrame::enomethodCommand() << ")" << endl;
142 script_r.close();
143 }
144
145 return ret;
146 }
147 private:
148 std::list<PluginScript> _scripts;
149 };
150
152 //
153 // CLASS NAME : PluginExecutor
154 //
156
158 : _pimpl( new Impl() )
159 {}
160
162 {}
163
165 { return _pimpl->empty(); }
166
167 size_t PluginExecutor::size() const
168 { return _pimpl->size(); }
169
170 void PluginExecutor::load( const Pathname & path_r )
171 { _pimpl->load( path_r ); }
172
173 void PluginExecutor::send( const PluginFrame & frame_r )
174 { _pimpl->send( frame_r ); }
175
176 std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj )
177 { return str << obj._pimpl->scripts(); }
178
179} // namespace zypp
Base class for Exception.
Definition: Exception.h:146
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:91
PluginExecutor implementation.
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
const std::list< PluginScript > scripts() const
void send(const PluginFrame &frame_r)
void load(const Pathname &path_r)
Parallel execution of stateful PluginScripts.
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:41
static const std::string & ackCommand()
"ACK" command.
Definition: PluginFrame.cc:241
static const std::string & enomethodCommand()
"_ENOMETHOD" command.
Definition: PluginFrame.cc:253
const std::string & command() const
Return the frame command.
Definition: PluginFrame.cc:286
bool isEnomethodCommand() const
Convenience to identify an _ENOMETHOD command.
Definition: PluginFrame.h:114
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.
Definition: PluginFrame.cc:319
bool isAckCommand() const
Convenience to identify an ACK command.
Definition: PluginFrame.h:106
Interface to plugin scripts using a Stomp inspired communication protocol.
Definition: PluginScript.h:63
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:823
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
bool userMayRX() const
Definition: PathInfo.h:350
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
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:605
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Definition: SerialNumber.cc:52
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:436
#define DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96
#define WAR
Definition: Logger.h:97