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