libzypp 17.37.10

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
19 using std::endl;
20
21#undef ZYPP_BASE_LOGGER_LOGGROUP
22#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
23
25 namespace zypp
26{
31 class PluginExecutor::Impl : private base::NonCopyable
32 {
33 public:
34 Impl()
35 {}
36
37 Impl(const Impl &) = delete;
38 Impl(Impl &&) = delete;
39 Impl &operator=(const Impl &) = delete;
40 Impl &operator=(Impl &&) = delete;
41
42 ~Impl() {
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
161 PluginExecutor::PluginExecutor()
162 : _pimpl( new Impl() )
163 {}
164
165 PluginExecutor::~PluginExecutor()
166 {}
167
168 bool PluginExecutor::empty() const
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
PluginExecutor.h
ZConfig.h
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::Exception::asUserHistory
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:140
zypp::PluginExecutor::Impl
PluginExecutor implementation.
Definition PluginExecutor.cc:32
zypp::PluginExecutor::Impl::Impl
Impl(Impl &&)=delete
zypp::PluginExecutor::Impl::~Impl
~Impl()
Definition PluginExecutor.cc:42
zypp::PluginExecutor::Impl::operator=
Impl & operator=(Impl &&)=delete
zypp::PluginExecutor::Impl::empty
bool empty() const
Definition PluginExecutor.cc:48
zypp::PluginExecutor::Impl::doSend
PluginFrame doSend(PluginScript &script_r, const PluginFrame &frame_r)
Definition PluginExecutor.cc:127
zypp::PluginExecutor::Impl::doLoad
void doLoad(const PathInfo &pi_r)
Launch a plugin sending PLUGINSTART message.
Definition PluginExecutor.cc:106
zypp::PluginExecutor::Impl::_scripts
std::list< PluginScript > _scripts
Definition PluginExecutor.cc:152
zypp::PluginExecutor::Impl::operator=
Impl & operator=(const Impl &)=delete
zypp::PluginExecutor::Impl::Impl
Impl()
Definition PluginExecutor.cc:34
zypp::PluginExecutor::Impl::size
size_t size() const
Definition PluginExecutor.cc:51
zypp::PluginExecutor::Impl::Impl
Impl(const Impl &)=delete
zypp::PluginExecutor::Impl::scripts
const std::list< PluginScript > scripts() const
Definition PluginExecutor.cc:101
zypp::PluginExecutor::Impl::send
void send(const PluginFrame &frame_r)
Definition PluginExecutor.cc:87
zypp::PluginExecutor::Impl::load
void load(const Pathname &path_r)
Definition PluginExecutor.cc:54
zypp::PluginExecutor::_pimpl
RW_pointer< Impl > _pimpl
Implementation class.
Definition PluginExecutor.h:81
zypp::PluginExecutor::load
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
Definition PluginExecutor.cc:174
zypp::PluginExecutor::size
size_t size() const
Number of open plugins.
Definition PluginExecutor.cc:171
zypp::PluginExecutor::PluginExecutor
PluginExecutor()
Default ctor: Empty plugin list.
Definition PluginExecutor.cc:161
zypp::PluginExecutor::send
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
Definition PluginExecutor.cc:177
zypp::PluginExecutor::~PluginExecutor
~PluginExecutor()
Dtor: Send PLUGINEND and close all plugins.
Definition PluginExecutor.cc:165
zypp::PluginExecutor::empty
bool empty() const
Whether no plugins are waiting.
Definition PluginExecutor.cc:168
zypp::PluginFrame
Command frame for communication with PluginScript.
Definition PluginFrame.h:42
zypp::PluginFrame::ackCommand
static const std::string & ackCommand()
"ACK" command.
Definition PluginFrame.cc:384
zypp::PluginFrame::enomethodCommand
static const std::string & enomethodCommand()
"_ENOMETHOD" command.
Definition PluginFrame.cc:396
zypp::PluginFrame::command
const std::string & command() const
Return the frame command.
Definition PluginFrame.cc:439
zypp::PluginFrame::isEnomethodCommand
bool isEnomethodCommand() const
Convenience to identify an _ENOMETHOD command.
Definition PluginFrame.h:122
zypp::PluginFrame::setHeader
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:478
zypp::PluginFrame::isAckCommand
bool isAckCommand() const
Convenience to identify an ACK command.
Definition PluginFrame.h:114
zypp::PluginScript
Interface to plugin scripts using a Stomp inspired communication protocol.
Definition PluginScript.h:63
zypp::PluginScript::receive
PluginFrame receive() const
Receive a PluginFrame.
Definition PluginScript.cc:522
zypp::PluginScript::send
void send(const PluginFrame &frame_r) const
Send a PluginFrame.
Definition PluginScript.cc:519
zypp::PluginScript::close
int close()
Close any open connection.
Definition PluginScript.cc:516
zypp::PluginScript::open
void open()
Setup connection and execute script.
Definition PluginScript.cc:507
zypp::PluginScript::script
const Pathname & script() const
Return the script path if set.
Definition PluginScript.cc:489
zypp::PluginScript::isOpen
bool isOpen() const
Whether we are connected to a script.
Definition PluginScript.cc:495
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:940
zypp::filesystem::PathInfo
Wrapper class for stat/lstat.
Definition PathInfo.h:226
zypp::filesystem::PathInfo::userMayRX
bool userMayRX() const
Definition PathInfo.h:358
zypp::filesystem::PathInfo::path
const Pathname & path() const
Return current Pathname.
Definition PathInfo.h:251
zypp::filesystem::PathInfo::isDir
bool isDir() const
Definition PathInfo.h:296
zypp::filesystem::PathInfo::isFile
bool isFile() const
Definition PathInfo.h:295
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:47
str
String related utilities and Regular expression matching.
zypp::base::NonCopyable
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
zypp::filesystem::readdir
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
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition Application.cc:20
zypp::operator<<
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Definition SerialNumber.cc:52
for_
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
DBG
#define DBG
Definition Logger.h:99
MIL
#define MIL
Definition Logger.h:100
WAR
#define WAR
Definition Logger.h:101
PathInfo.h
LogTools.h
NonCopyable.h