00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015
00016 #include <boost/tokenizer.hpp>
00017 #include <boost/algorithm/string.hpp>
00018
00019 #include "zypp/ZYppFactory.h"
00020 #include "zypp/base/Logger.h"
00021 #include "zypp/base/Exception.h"
00022 #include "zypp/base/PtrTypes.h"
00023 #include "zypp/base/String.h"
00024
00025 #include "zypp/CapFactory.h"
00026
00027 #include "zypp/source/susetags/ProductMetadataParser.h"
00028 #include "zypp/source/susetags/SuseTagsProductImpl.h"
00029 #include <boost/regex.hpp>
00030
00031 #undef ZYPP_BASE_LOGGER_LOGGROUP
00032 #define ZYPP_BASE_LOGGER_LOGGROUP "ProductMetadataParser"
00033
00034 using namespace std;
00035 using namespace boost;
00036
00037 typedef find_iterator<string::iterator> string_find_iterator;
00038
00040 namespace zypp
00041 {
00042
00043 namespace source
00044 {
00045
00046 namespace susetags
00047 {
00048 ProductMetadataParser::ProductMetadataParser()
00049 {
00050 prodImpl = new SuseTagsProductImpl;
00051 }
00052
00054
00055
00056
00057
00058 void ProductMetadataParser::parse( const Pathname & file_r, Source_Ref source_r )
00059 {
00060 std::ifstream file(file_r.asString().c_str());
00061
00062 if (!file) {
00063 ZYPP_THROW (Exception("Can't read product file :" + file_r.asString()));
00064 }
00065
00066 std::string buffer;
00067 volatile_content = false;
00068 while(file && !file.eof())
00069 {
00070 getline(file, buffer);
00071 boost::regex e("^(([A-Z]+)(\\.([_A-Z0-9a-z]+)){0,1}) (.+)$");
00072 boost::smatch what;
00073 if(boost::regex_match(buffer, what, e, boost::match_extra))
00074 {
00075 if ( what.size() < 5 )
00076 std::cout << "ups!!!!" << std::endl;
00077
00078 std::string key = what[2];
00079 std::string value = what[5];
00080 std::string modifier = what[4];
00081 if(key == "PRODUCT")
00082 prodImpl->_name = value;
00083 else if(key == "VERSION")
00084 prodImpl->_version = value;
00085 else if(key == "DISTPRODUCT")
00086 prodImpl->_dist = value;
00087 else if(key == "DISTVERSION")
00088 prodImpl->_dist_version = value;
00089 else if(key == "BASEPRODUCT")
00090 prodImpl->_base_product = value;
00091 else if(key == "BASEVERSION")
00092 prodImpl->_base_version = value;
00093 else if(key == "YOUTYPE")
00094 prodImpl->_you_type = value;
00095 else if(key == "VENDOR")
00096 prodImpl->_vendor = value;
00097 else if(key == "SHORTLABEL")
00098 prodImpl->_shortlabel = value;
00099 else if(key == "RELNOTESURL")
00100 {
00101
00102 try
00103 {
00104 Url url (value) ;
00105 prodImpl->_release_notes_url = url;
00106 }
00107 catch( ... )
00108 {
00109 prodImpl->_release_notes_url = Url();
00110 }
00111 }
00112 else if(key == "UPDATEURLS")
00113 {
00114 std::list<std::string> items;
00115 boost::algorithm::split(items, value, is_space());
00116 std::list<std::string>::const_iterator
00117 b = items.begin(),
00118 e = items.end(),
00119 i;
00120 for (i = b; i != e; ++i)
00121 {
00122
00123 try
00124 {
00125 Url url = *i;
00126 prodImpl->_update_urls.push_back( url );
00127 }
00128 catch( ... )
00129 {
00130
00131 }
00132 }
00133 }
00134 else if(key == "ARCH")
00135 parseLine( key, modifier, value, prodImpl->_arch);
00136 else if(key == "DEFAULTBASE")
00137 prodImpl->_default_base = value;
00138 else if(key == "PREREQUIRES")
00139 parseDependencies( key, value, prodImpl->_deps, Dep::PREREQUIRES);
00140 else if(key == "REQUIRES")
00141 parseDependencies( key, value, prodImpl->_deps, Dep::REQUIRES);
00142 else if(key == "PROVIDES")
00143 parseDependencies( key, value, prodImpl->_deps, Dep::PROVIDES);
00144 else if(key == "CONFLICTS")
00145 parseDependencies( key, value, prodImpl->_deps, Dep::CONFLICTS);
00146 else if(key == "OBSOLETES")
00147 parseDependencies( key, value, prodImpl->_deps, Dep::OBSOLETES);
00148 else if(key == "RECOMMENDS")
00149 parseDependencies( key, value, prodImpl->_deps, Dep::RECOMMENDS);
00150 else if(key == "SUGGESTS")
00151 parseDependencies( key, value, prodImpl->_deps, Dep::SUGGESTS);
00152 else if(key == "SUPPLEMENTS")
00153 parseDependencies( key, value, prodImpl->_deps, Dep::SUPPLEMENTS);
00154 else if(key == "ENHANCES")
00155 parseDependencies( key, value, prodImpl->_deps, Dep::ENHANCES);
00156 else if(key == "LINGUAS")
00157 parseLine( key, value, prodImpl->_languages);
00158 else if(key == "LABEL")
00159 parseLine( key, modifier, value, prodImpl->_summary);
00160 else if(key == "DESCRDIR")
00161 prodImpl->_description_dir = value;
00162 else if(key == "DATADIR")
00163 prodImpl->_data_dir = value;
00164 else if(key == "FLAGS")
00165 parseLine( key, value, prodImpl->_flags);
00166 else if(key == "LANGUAGE")
00167 prodImpl->_language = value;
00168 else if(key == "TIMEZONE")
00169 prodImpl->_timezone = value;
00170 else if(key == "META")
00171 parseFileCheckSum( key, value, prodImpl->_descr_files_checksums);
00172 else if(key == "KEY")
00173 parseFileCheckSum( key, value, prodImpl->_signing_keys);
00174 else if(key == "VOLATILE_CONTENT")
00175 volatile_content = true;
00176 else
00177 DBG << "Unknown key [" << key << "] with value [" << value << "]" << std::endl;
00178 }
00179 else if (!buffer.empty())
00180 {
00181 DBG << "** No Match found: " << buffer << std::endl;
00182 }
00183 }
00184
00185
00186
00187 try
00188 {
00189
00190
00191
00192 Arch sysarch( getZYpp()->architecture() );
00193 Arch prodarch( Arch_noarch );
00194
00195
00196
00197 std::map< std::string, std::list<std::string> >::const_iterator it = prodImpl->_arch.find( sysarch.asString() );
00198
00199
00200
00201 if (it == prodImpl->_arch.end()) {
00202 WAR << "Product does not fully support systems architecture (" << sysarch << ")" << endl;
00203
00204 for (std::map< std::string, std::list<std::string> >::const_iterator it1 = prodImpl->_arch.begin(); it1 != prodImpl->_arch.end(); ++it1) {
00205 Arch arch( it1->first );
00206 if (!arch.compatibleWith( sysarch )) {
00207 continue;
00208 }
00209 if (arch.compare( prodarch ) > 0) {
00210 prodarch = arch;
00211 it = it1;
00212 }
00213 }
00214 }
00215
00216
00217
00218 if (it == prodImpl->_arch.end()
00219 || it->second.empty())
00220 {
00221 ERR << "Product incompatible with systems architecture (" << sysarch << ")" << endl;
00222 }
00223 else {
00224 MIL << "Found matching/best arch " << it->first << endl;
00225
00226 prodarch = Arch( it->second.front() );
00227 }
00228
00229 MIL << "Product arch is " << prodarch << endl;
00230
00231 NVRAD dataCollect( prodImpl->_dist, Edition( prodImpl->_dist_version ), prodarch, prodImpl->_deps );
00232 result = detail::makeResolvableFromImpl( dataCollect, prodImpl );
00233 }
00234 catch (const Exception & excpt_r)
00235 {
00236 ZYPP_THROW(Exception("Error creating product: " + excpt_r.msg()));
00237 }
00238
00239 prodImpl->_source = source_r;
00240 prodImpl->_category = source_r.baseSource() ? "base" : "add-on";
00241 INT << "Product category set to " << prodImpl->_category << endl;
00242 }
00243
00244 void ProductMetadataParser::parseLine( const string &key, const string &modif, const string &value, map< string, list<string> > &container)
00245 {
00246 if ( modif.size() == 0)
00247 parseLine( key, value, container["default"]);
00248 else
00249 parseLine( key, value, container[modif]);
00250 }
00251
00252 void ProductMetadataParser::parseLine( const std::string &key, const std::string &lang, const std::string &value, TranslatedText &container)
00253 {
00254 if ( lang.size() == 0)
00255 container.setText(value, Locale());
00256 else
00257 container.setText(value, Locale(lang));
00258 }
00259
00260 void ProductMetadataParser::parseLine( const string &key, const string &modif, const string &value, map< string, string > &container)
00261 {
00262 if( modif.size() == 0)
00263 container["default"] = value;
00264 else
00265 container[modif] = value;
00266 }
00267
00268 void ProductMetadataParser::parseLine( const string &key, const string &value, std::list<std::string> &container)
00269 {
00270 str::split( value, std::back_inserter(container), " ");
00271 }
00272
00273 void ProductMetadataParser::parseDependencies( const string &key, const string &value, Dependencies & deps, Dep deptag )
00274 {
00275 std::list<std::string> splitted;
00276 str::split( value, std::back_inserter(splitted), " ");
00277 Resolvable::Kind kind;
00278 std::string name;
00279 CapFactory f;
00280 for (std::list<std::string>::const_iterator it = splitted.begin(); it != splitted.end(); ++it) {
00281 string name = *it;
00282 string::size_type colon = name.find(":");
00283 kind = ResTraits<Package>::kind;
00284 if (colon != string::npos) {
00285 string skind( name, 0, colon );
00286 name.erase( 0, colon+1 );
00287 DBG << "kind " << skind << ", name " << name << endl;
00288 if (skind == "pattern") kind = ResTraits<Pattern>::kind;
00289 else if (skind == "patch") kind = ResTraits<Patch>::kind;
00290 else if (skind == "selection") kind = ResTraits<Selection>::kind;
00291 else if (skind == "product") kind = ResTraits<Product>::kind;
00292 else if (skind != "package") ERR << "Bad kind in content::" << key << " '" << skind << "'" << endl;
00293 }
00294 std::list<std::string>::const_iterator next = it;
00295 ++next;
00296 if (next != splitted.end()) {
00297 string val = *next;
00298 if (val.find_first_of("<>=") != string::npos)
00299 {
00300 if (++next != splitted.end()) {
00301 name += val;
00302 name += *next;
00303 it = next;
00304 }
00305 }
00306 }
00307 try {
00308 deps[deptag].insert( f.parse( kind, name ) );
00309 }
00310 catch (Exception & excpt_r) {
00311 ZYPP_CAUGHT( excpt_r );
00312 ERR << "Ignoring invalid " << key << " entry '" << name << "'" << endl;
00313 }
00314 }
00315 }
00316
00317 void ProductMetadataParser::parseFileCheckSum( const std::string &key, const std::string &value, std::map<std::string, CheckSum> &container)
00318 {
00319 std::list<std::string> splitted;
00320 str::split( value, std::back_inserter(splitted), " ");
00321 if (splitted.size() != 3)
00322 {
00323 ERR << "Parse error in checksum. Expected [type checksum file], got [" << value << "]" << std::endl;
00324 }
00325 else
00326 {
00327 std::string checksum_type = splitted.front();
00328 splitted.pop_front();
00329 std::string checksum_str = splitted.front();
00330 splitted.pop_front();
00331 std::string filename = splitted.front();
00332 splitted.pop_front();
00333 MIL << "Checksum for " << filename << " is " << checksum_str << " (" << checksum_type << ")" << std::endl;
00334 container[filename] = CheckSum(checksum_type, checksum_str);
00335 }
00336 }
00338 }
00341 }
00344 }