libzypp  17.32.4
PluginFrame.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <utility>
14 #include <zypp/base/LogTools.h>
15 #include <zypp/base/String.h>
16 
17 #include <zypp/PluginFrame.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 {
27 
29  //
30  // CLASS NAME : PluginFrame::Impl
31  //
34  {
35  public:
36  Impl()
37  {}
38 
39  Impl( const std::string & command_r )
40  { setCommand( command_r ); }
41 
42  Impl( const std::string & command_r, std::string &&body_r )
43  : _body(std::move( body_r ))
44  { setCommand( command_r ); }
45 
46  Impl( const std::string & command_r, HeaderInitializerList contents_r )
47  { setCommand( command_r ); addHeader( contents_r ); }
48 
49  Impl( const std::string & command_r, std::string &&body_r, HeaderInitializerList contents_r )
50  : _body(std::move( body_r ))
51  { setCommand( command_r ); addHeader( contents_r ); }
52 
53  Impl( std::istream & stream_r );
54 
55  public:
56  bool empty() const
57  { return _command.empty() && _body.empty(); }
58 
59  const std::string & command() const
60  { return _command; }
61 
62  void setCommand( const std::string & command_r )
63  {
64  if ( command_r.find( '\n' ) != std::string::npos )
65  ZYPP_THROW( PluginFrameException( "Multiline command", command_r ) );
66  _command = command_r;
67  }
68 
69  const std::string & body() const
70  { return _body; }
71 
72  std::string & bodyRef()
73  { return _body; }
74 
75  void setBody( const std::string & body_r )
76  { _body = body_r; }
77 
78  public:
79  using constKeyRange = std::pair<HeaderListIterator, HeaderListIterator>;
80  using KeyRange = std::pair<HeaderList::iterator, HeaderList::iterator>;
81 
83  { return _header; }
84 
85  const HeaderList & headerList() const
86  { return _header; }
87 
88  const std::string & getHeader( const std::string & key_r ) const
89  {
90  constKeyRange r( _header.equal_range( key_r ) );
91  if ( r.first == r.second )
92  ZYPP_THROW( PluginFrameException( "No value for key", key_r ) );
93  const std::string & ret( r.first->second );
94  if ( ++r.first != r.second )
95  ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
96  return ret;
97  }
98 
99  const std::string & getHeader( const std::string & key_r, const std::string & default_r ) const
100  {
101  constKeyRange r( _header.equal_range( key_r ) );
102  if ( r.first == r.second )
103  return default_r;
104  const std::string & ret( r.first->second );
105  if ( ++r.first != r.second )
106  ZYPP_THROW( PluginFrameException( "Multiple values for key", key_r ) );
107  return ret;
108  }
109 
110  const std::string & getHeaderNT( const std::string & key_r, const std::string & default_r ) const
111  {
112  HeaderListIterator iter( _header.find( key_r ) );
113  return iter != _header.end() ? iter->second : default_r;
114  }
115 
116  HeaderList::value_type mkHeaderPair( const std::string & key_r, const std::string & value_r )
117  {
118  if ( key_r.find_first_of( ":\n" ) != std::string::npos )
119  ZYPP_THROW( PluginFrameException( "Illegal char in header key", key_r ) );
120  if ( value_r.find_first_of( '\n' ) != std::string::npos )
121  ZYPP_THROW( PluginFrameException( "Illegal char in header value", value_r ) );
122  return HeaderList::value_type( key_r, value_r );
123  }
124 
125  void setHeader( const std::string & key_r, const std::string & value_r )
126  {
127  clearHeader( key_r );
128  addHeader( key_r, value_r );
129  }
130 
131  void addHeader( const std::string & key_r, const std::string & value_r )
132  {
133  _header.insert( mkHeaderPair( key_r, value_r ) );
134  }
135 
136  void addHeader( HeaderInitializerList contents_r )
137  {
138  for ( const auto & el : contents_r )
139  addHeader( el.first, el.second );
140  }
141 
142  void clearHeader( const std::string & key_r )
143  {
144  _header.erase( key_r );
145  }
146 
147  public:
148  std::ostream & writeTo( std::ostream & stream_r ) const;
149 
150  private:
151  std::string _command;
152  std::string _body;
154 
155  public:
157  static shared_ptr<Impl> nullimpl()
158  {
159  static shared_ptr<Impl> _nullimpl( new Impl );
160  return _nullimpl;
161  }
162  private:
163  friend Impl * rwcowClone<Impl>( const Impl * rhs );
165  Impl * clone() const
166  { return new Impl( *this ); }
167  };
169 
171  inline std::ostream & operator<<( std::ostream & str, const PluginFrame::Impl & obj )
172  {
173  return str << "PluginFrame[" << obj.command() << "](" << obj.headerList().size() << "){" << obj.body().size() << "}";
174  }
175 
176  PluginFrame::Impl::Impl( std::istream & stream_r )
177  {
178  //DBG << "Parse from " << stream_r << endl;
179  if ( ! stream_r )
180  ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
181 
182  // JFYI: stream status after getline():
183  // Bool | Bits
184  // ------|---------------
185  // true | [g___] >FOO< : FOO line was \n-terminated
186  // true | [_e__] >BAA< : BAA before EOF, but not \n-terminated
187  // false | [_eF_] >< : No valid data to consume
188 
189  //command
190  _command = str::getline( stream_r );
191  if ( ! stream_r.good() )
192  ZYPP_THROW( PluginFrameException( "Missing NL after command" ) );
193 
194  // header
195  do {
196  std::string data = str::getline( stream_r );
197  if ( ! stream_r.good() )
198  ZYPP_THROW( PluginFrameException( "Missing NL after header" ) );
199 
200  if ( data.empty() )
201  break; // --> empty line sep. header and body
202 
203  std::string::size_type sep( data.find( ':') );
204  if ( sep == std::string::npos )
205  ZYPP_THROW( PluginFrameException( "Missing colon in header" ) );
206 
207  _header.insert( HeaderList::value_type( data.substr(0,sep), data.substr(sep+1) ) );
208  } while ( true );
209 
210  // data
211  _body = str::receiveUpTo( stream_r, '\0' );
212  if ( ! stream_r.good() )
213  ZYPP_THROW( PluginFrameException( "Missing NUL after body" ) );
214  }
215 
216  std::ostream & PluginFrame::Impl::writeTo( std::ostream & stream_r ) const
217  {
218  //DBG << "Write " << *this << " to " << stream_r << endl;
219  if ( ! stream_r )
220  ZYPP_THROW( PluginFrameException( "Bad Stream" ) );
221 
222  // command
223  stream_r << _command << endl;
224  // header
225  for_( it, _header.begin(), _header.end() )
226  stream_r << it->first << ':' << it->second << endl;
227  // body
228  stream_r << endl
229  << _body << '\0';
230 
231  if ( ! stream_r )
232  ZYPP_THROW( PluginFrameException( "Write error" ) );
233  return stream_r;
234  }
235 
237  //
238  // CLASS NAME : PluginFrame
239  //
241 
242  const std::string & PluginFrame::ackCommand()
243  {
244  static std::string _val( "ACK" );
245  return _val;
246  }
247 
248  const std::string & PluginFrame::errorCommand()
249  {
250  static std::string _val( "ERROR" );
251  return _val;
252  }
253 
254  const std::string & PluginFrame::enomethodCommand()
255  {
256  static std::string _val( "_ENOMETHOD" );
257  return _val;
258  }
259 
261  : _pimpl( Impl::nullimpl() )
262  {}
263 
264  PluginFrame::PluginFrame( const std::string & command_r )
265  : _pimpl( new Impl( command_r ) )
266  {}
267 
268  PluginFrame::PluginFrame( const std::string & command_r, std::string body_r )
269  : _pimpl( new Impl( command_r, std::move(body_r) ) )
270  {}
271 
272  PluginFrame::PluginFrame( const std::string & command_r, HeaderInitializerList contents_r )
273  : _pimpl( new Impl( command_r, contents_r ) )
274  {}
275 
276  PluginFrame::PluginFrame( const std::string & command_r, std::string body_r, HeaderInitializerList contents_r )
277  : _pimpl( new Impl( command_r, std::move(body_r), contents_r ) )
278  {}
279 
280  PluginFrame::PluginFrame( std::istream & stream_r )
281  : _pimpl( new Impl( stream_r ) )
282  {}
283 
284  bool PluginFrame::empty() const
285  { return _pimpl->empty(); }
286 
287  const std::string & PluginFrame::command() const
288  { return _pimpl->command(); }
289 
290  void PluginFrame::setCommand( const std::string & command_r )
291  { _pimpl->setCommand( command_r ); }
292 
293  const std::string & PluginFrame::body() const
294  { return _pimpl->body(); }
295 
296  std::string & PluginFrame::bodyRef()
297  { return _pimpl->bodyRef(); }
298 
299  void PluginFrame::setBody( const std::string & body_r )
300  { _pimpl->setBody( body_r ); }
301 
302  std::ostream & PluginFrame::writeTo( std::ostream & stream_r ) const
303  { return _pimpl->writeTo( stream_r ); }
304 
306  { return _pimpl->headerList(); }
307 
309  { return _pimpl->headerList(); }
310 
311  const std::string & PluginFrame::getHeader( const std::string & key_r ) const
312  { return _pimpl->getHeader( key_r ); }
313 
314  const std::string & PluginFrame::getHeader( const std::string & key_r, const std::string & default_r ) const
315  { return _pimpl->getHeader( key_r, default_r ); }
316 
317  const std::string & PluginFrame::getHeaderNT( const std::string & key_r, const std::string & default_r ) const
318  { return _pimpl->getHeaderNT( key_r, default_r ); }
319 
320  void PluginFrame::setHeader( const std::string & key_r, const std::string & value_r )
321  { _pimpl->setHeader( key_r, value_r ); }
322 
323  void PluginFrame::addHeader( const std::string & key_r, const std::string & value_r )
324  { _pimpl->addHeader( key_r, value_r ); }
325 
327  { _pimpl->addHeader( contents_r ); }
328 
329  void PluginFrame::clearHeader( const std::string & key_r )
330  { _pimpl->clearHeader( key_r ); }
331 
333 
334  std::ostream & operator<<( std::ostream & str, const PluginFrame & obj )
335  { return str << *obj._pimpl; }
336 
337  bool operator==( const PluginFrame & lhs, const PluginFrame & rhs )
338  {
339  return ( lhs._pimpl == rhs._pimpl )
340  || (( lhs.command() == rhs.command() ) && ( lhs.headerList() == rhs.headerList() ) && ( lhs.body() == rhs.body() ));
341  }
342 
344 } // namespace zypp
std::ostream & writeTo(std::ostream &stream_r) const
Write frame to stream.
Definition: PluginFrame.cc:302
PluginFrame()
Default ctor (empty frame)
Definition: PluginFrame.cc:260
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition: PluginFrame.cc:157
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:429
std::pair< HeaderListIterator, HeaderListIterator > constKeyRange
Definition: PluginFrame.cc:79
Command frame for communication with PluginScript.
Definition: PluginFrame.h:40
void setCommand(const std::string &command_r)
Set the frame command.
Definition: PluginFrame.cc:290
const std::string & command() const
Return the frame command.
Definition: PluginFrame.cc:287
std::multimap< std::string, std::string > HeaderList
The header list.
Definition: PluginFrame.h:135
void clearHeader(const std::string &key_r)
Definition: PluginFrame.cc:142
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
const std::string & getHeaderNT(const std::string &key_r, const std::string &default_r=std::string()) const
Not throwing version returing one of the matching header values or default_r string.
Definition: PluginFrame.cc:317
String related utilities and Regular expression matching.
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Definition: SerialNumber.cc:52
bool empty() const
Whether this is an empty frame.
Definition: PluginFrame.cc:284
Definition: Arch.h:363
Impl(const std::string &command_r)
Definition: PluginFrame.cc:39
void addHeader(const std::string &key_r, const std::string &value_r=std::string())
Add header for key_r leaving already existing headers for key_r unchanged.
Definition: PluginFrame.cc:323
bool operator==(const SetRelation::Enum &lhs, const SetCompare &rhs)
static const std::string & errorCommand()
"ERROR" command.
Definition: PluginFrame.cc:248
void setCommand(const std::string &command_r)
Definition: PluginFrame.cc:62
const std::string & getHeader(const std::string &key_r, const std::string &default_r) const
Definition: PluginFrame.cc:99
std::ostream & writeTo(std::ostream &stream_r) const
Definition: PluginFrame.cc:216
std::pair< HeaderList::iterator, HeaderList::iterator > KeyRange
Definition: PluginFrame.cc:80
static const std::string & enomethodCommand()
"_ENOMETHOD" command.
Definition: PluginFrame.cc:254
void addHeader(HeaderInitializerList contents_r)
Definition: PluginFrame.cc:136
const std::string & body() const
Return the frame body.
Definition: PluginFrame.cc:293
Base class for PluginFrame Exception.
Impl(const std::string &command_r, HeaderInitializerList contents_r)
Definition: PluginFrame.cc:46
Impl(const std::string &command_r, std::string &&body_r)
Definition: PluginFrame.cc:42
std::string getline(std::istream &str, const Trim trim_r)
Return stream content up to (but not returning) the next newline.
Definition: String.cc:479
static const std::string & ackCommand()
"ACK" command.
Definition: PluginFrame.cc:242
RWCOW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: PluginFrame.h:250
void setHeader(const std::string &key_r, const std::string &value_r)
Definition: PluginFrame.cc:125
HeaderList & headerList()
Definition: PluginFrame.cc:82
void setBody(const std::string &body_r)
Set the frame body.
Definition: PluginFrame.cc:299
Impl * clone() const
clone for RWCOW_pointer
Definition: PluginFrame.cc:165
HeaderList::value_type mkHeaderPair(const std::string &key_r, const std::string &value_r)
Definition: PluginFrame.cc:116
const std::string & getHeaderNT(const std::string &key_r, const std::string &default_r) const
Definition: PluginFrame.cc:110
void addHeader(const std::string &key_r, const std::string &value_r)
Definition: PluginFrame.cc:131
const std::initializer_list< std::pair< std::string, std::string > > & HeaderInitializerList
Definition: PluginFrame.h:45
const std::string & getHeader(const std::string &key_r) const
Definition: PluginFrame.cc:88
std::string receiveUpTo(std::istream &str, const char delim_r, bool returnDelim_r)
Return stream content up to the next ocurrence of delim_r or EOF delim_r, if found, is always read from the stream.
Definition: String.cc:489
Impl(const std::string &command_r, std::string &&body_r, HeaderInitializerList contents_r)
Definition: PluginFrame.cc:49
HeaderList::const_iterator HeaderListIterator
Header list iterator.
Definition: PluginFrame.h:138
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:320
HeaderList & headerList()
Modifyalble header list for internal use only.
Definition: PluginFrame.cc:305
const std::string & getHeader(const std::string &key_r) const
Return header value for key_r.
Definition: PluginFrame.cc:311
const HeaderList & headerList() const
Definition: PluginFrame.cc:85
std::ostream & operator<<(std::ostream &str, const PluginFrame::Impl &obj)
Definition: PluginFrame.cc:171
PluginFrame implementation.
Definition: PluginFrame.cc:33
std::string & bodyRef()
Return a reference to the frame body.
Definition: PluginFrame.cc:296
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
SolvableIdType size_type
Definition: PoolMember.h:126
void clearHeader(const std::string &key_r)
Remove all headers for key_r.
Definition: PluginFrame.cc:329
std::string & bodyRef()
Definition: PluginFrame.cc:72
void setBody(const std::string &body_r)
Definition: PluginFrame.cc:75
const std::string & command() const
Definition: PluginFrame.cc:59
const std::string & body() const
Definition: PluginFrame.cc:69