libzypp  14.48.5
RepoindexFileReader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <unordered_map>
14 
15 #include "zypp/base/String.h"
16 #include "zypp/base/Logger.h"
17 #include "zypp/base/Gettext.h"
18 #include "zypp/base/InputStream.h"
19 
20 #include "zypp/Pathname.h"
21 
22 #include "zypp/parser/xml/Reader.h"
24 
25 #include "zypp/RepoInfo.h"
26 
28 
29 
30 #undef ZYPP_BASE_LOGGER_LOGGROUP
31 #define ZYPP_BASE_LOGGER_LOGGROUP "parser"
32 
33 using std::endl;
34 
35 namespace zypp
36 {
37  namespace parser
38  {
39  using xml::Reader;
40  using xml::XmlString;
41 
43  namespace
44  {
45  class VarReplacer : private base::NonCopyable
46  {
47  public:
49  void setVar( const std::string & key_r, const std::string & val_r )
50  {
51  MIL << "*** Inject " << key_r << " = " << val_r;
52  _vars[key_r] = replace( val_r );
53  MIL << " (" << _vars[key_r] << ")" << endl;
54  }
55 
56  std::string replace( const std::string & val_r ) const
57  {
58  std::string::size_type vbeg = val_r.find( "%{", 0 );
59  if ( vbeg == std::string::npos )
60  return val_r;
61 
62  str::Str ret;
63  std::string::size_type cbeg = 0;
64  for( ; vbeg != std::string::npos; vbeg = val_r.find( "%{", vbeg ) )
65  {
66  std::string::size_type nbeg = vbeg+2;
67  std::string::size_type nend = val_r.find( "}", nbeg );
68  if ( nend == std::string::npos )
69  {
70  WAR << "Incomplete variable in '" << val_r << "'" << endl;
71  break;
72  }
73  const auto & iter = _vars.find( val_r.substr( nbeg, nend-nbeg ) );
74  if ( iter != _vars.end() )
75  {
76  if ( cbeg < vbeg )
77  ret << val_r.substr( cbeg, vbeg-cbeg );
78  ret << iter->second;
79  cbeg = nend+1;
80  }
81  else
82  WAR << "Undefined variable %{" << val_r.substr( nbeg, nend-nbeg ) << "} in '" << val_r << "'" << endl;
83  vbeg = nend+1;
84  }
85  if ( cbeg < val_r.size() )
86  ret << val_r.substr( cbeg );
87 
88  return ret;
89  }
90  private:
91  std::unordered_map<std::string,std::string> _vars;
92  };
93  } // namespace
95 
97  //
98  // CLASS NAME : RepoindexFileReader::Impl
99  //
101  {
102  public:
108  Impl(const InputStream &is, const ProcessResource & callback);
109 
113  bool consumeNode( Reader & reader_r );
114 
115  private:
116  bool getAttrValue( const std::string & key_r, Reader & reader_r, std::string & value_r )
117  {
118  const XmlString & s( reader_r->getAttribute( key_r ) );
119  if ( s.get() )
120  {
121  value_r = _replacer.replace( s.asString() );
122  return !value_r.empty();
123  }
124  value_r.clear();
125  return false;
126  }
127 
128  private:
131  VarReplacer _replacer;
132  };
134 
136  const ProcessResource & callback)
137  : _callback(callback)
138  {
139  Reader reader( is );
140  MIL << "Reading " << is.path() << endl;
141  reader.foreachNode( bind( &RepoindexFileReader::Impl::consumeNode, this, _1 ) );
142  }
143 
144  // --------------------------------------------------------------------------
145 
146  /*
147  * xpath and multiplicity of processed nodes are included in the code
148  * for convenience:
149  *
150  * // xpath: <xpath> (?|*|+)
151  *
152  * if multiplicity is ommited, then the node has multiplicity 'one'.
153  */
154 
155  // --------------------------------------------------------------------------
156 
157  bool RepoindexFileReader::Impl::consumeNode( Reader & reader_r )
158  {
159  if ( reader_r->nodeType() == XML_READER_TYPE_ELEMENT )
160  {
161  // xpath: /repoindex
162  if ( reader_r->name() == "repoindex" )
163  {
164  while ( reader_r.nextNodeAttribute() )
165  _replacer.setVar( reader_r->localName().asString(), reader_r->value().asString() );
166  return true;
167  }
168 
169  // xpath: /repoindex/data (+)
170  if ( reader_r->name() == "repo" )
171  {
172  RepoInfo info;
173  // Set some defaults that are not contained in the repo information
174  info.setAutorefresh( true );
175  info.setEnabled(false);
176 
177  std::string attrValue;
178 
179  // required alias
180  // mandatory, so we can allow it in var replacement without reset
181  if ( getAttrValue( "alias", reader_r, attrValue ) )
182  {
183  info.setAlias( attrValue );
184  _replacer.setVar( "alias", attrValue );
185  }
186  else
187  throw ParseException(str::form(_("Required attribute '%s' is missing."), "alias"));
188 
189  // required url
190  // SLES HACK: or path, but beware of the hardcoded '/repo' prefix!
191  {
192  std::string urlstr;
193  std::string pathstr;
194  getAttrValue( "url", reader_r, urlstr );
195  getAttrValue( "path", reader_r, pathstr );
196  if ( urlstr.empty() )
197  {
198  if ( pathstr.empty() )
199  throw ParseException(str::form(_("One or both of '%s' or '%s' attributes is required."), "url", "path"));
200  else
201  info.setPath( Pathname("/repo") / pathstr );
202  }
203  else
204  {
205  if ( pathstr.empty() )
206  info.setBaseUrl( Url(urlstr) );
207  else
208  {
209  Url url( urlstr );
210  url.setPathName( Pathname(url.getPathName()) / "repo" / pathstr );
211  info.setBaseUrl( url );
212  }
213  }
214  }
215 
216  // optional name
217  if ( getAttrValue( "name", reader_r, attrValue ) )
218  info.setName( attrValue );
219 
220  // optional targetDistro
221  if ( getAttrValue( "distro_target", reader_r, attrValue ) )
222  info.setTargetDistribution( attrValue );
223 
224  // optional priority
225  if ( getAttrValue( "priority", reader_r, attrValue ) )
226  info.setPriority( str::strtonum<unsigned>( attrValue ) );
227 
228 
229  // optional enabled
230  if ( getAttrValue( "enabled", reader_r, attrValue ) )
231  info.setEnabled( str::strToBool( attrValue, info.enabled() ) );
232 
233  // optional autorefresh
234  if ( getAttrValue( "autorefresh", reader_r, attrValue ) )
235  info.setAutorefresh( str::strToBool( attrValue, info.autorefresh() ) );
236 
237  DBG << info << endl;
238 
239  // ignore the rest
240  _callback(info);
241  return true;
242  }
243  }
244 
245  return true;
246  }
247 
248 
250  //
251  // CLASS NAME : RepoindexFileReader
252  //
254 
256  const Pathname & repoindex_file, const ProcessResource & callback)
257  :
258  _pimpl(new Impl(InputStream(repoindex_file), callback))
259  {}
260 
262  const InputStream &is, const ProcessResource & callback )
263  : _pimpl(new Impl(is, callback))
264  {}
265 
267  {}
268 
269 
270  } // ns parser
271 } // ns zypp
272 
273 // vim: set ts=2 sts=2 sw=2 et ai:
Interface to gettext.
#define MIL
Definition: Logger.h:47
function< bool(const RepoInfo &)> ProcessResource
Callback definition.
ProcessResource _callback
Function for processing collected data.
void setAutorefresh(bool autorefresh)
enable or disable autorefresh
Definition: RepoInfoBase.cc:91
void setPriority(unsigned newval_r)
Set repository priority for solver.
Definition: RepoInfo.cc:302
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:598
void setEnabled(bool enabled)
enable or disable the repository
Definition: RepoInfoBase.cc:88
void setAlias(const std::string &alias)
set the repository alias
Definition: RepoInfoBase.cc:94
What is known about a repository.
Definition: RepoInfo.h:72
Url url
Definition: MediaCurl.cc:180
Helper to create and pass std::istream.
Definition: InputStream.h:56
void setBaseUrl(const Url &url)
Clears current base URL list and adds url.
Definition: RepoInfo.cc:437
bool enabled() const
If enabled is false, then this repository must be ignored as if does not exists, except when checking...
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
std::unordered_map< std::string, std::string > _vars
const ProcessCredentials & _callback
Interface of repoindex.xml file reader.
RepoindexFileReader(const zypp::Pathname &repoindexFile, const ProcessResource &callback)
CTOR.
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:758
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
void setPath(const Pathname &path)
set the product path.
Definition: RepoInfo.cc:446
#define WAR
Definition: Logger.h:48
const Pathname & path() const
Path to the input file or empty if no file.
Definition: InputStream.h:111
#define _(MSG)
Definition: Gettext.h:29
SolvableIdType size_type
Definition: PoolMember.h:147
void setTargetDistribution(const std::string &targetDistribution)
Sets the distribution for which is this repository meant.
Definition: RepoInfo.cc:468
bool autorefresh() const
If true, the repostory must be refreshed before creating resolvables from it.
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition: String.h:437
Impl(const InputStream &is, const ProcessResource &callback)
CTOR.
void setName(const std::string &name)
set the repository name
Definition: RepoInfoBase.cc:97
bool getAttrValue(const std::string &key_r, Reader &reader_r, std::string &value_r)
bool consumeNode(Reader &reader_r)
Callback provided to the XML parser.
RW_pointer< Impl, rw_pointer::Scoped< Impl > > _pimpl
Url manipulation class.
Definition: Url.h:87
#define DBG
Definition: Logger.h:46