serialize.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <ctime>
00014 #include <fstream>
00015 #include <sstream>
00016 #include <streambuf>
00017 
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/CapFactory.h"
00020 #include "zypp/Source.h"
00021 #include "zypp/Url.h"
00022 
00023 #include "zypp/ResObject.h"
00024 #include "zypp/detail/ImplConnect.h"
00025 #include "zypp/detail/ResObjectImplIf.h"
00026 #include "zypp/detail/SelectionImplIf.h"
00027 
00028 #include "serialize.h"
00029 #include "xml_escape_parser.hpp"
00030 
00031 using namespace std;
00033 namespace zypp
00034 { 
00035 namespace storage
00036 { 
00037 
00038 static std::string xml_escape( const std::string &text )
00039 {
00040   iobind::parser::xml_escape_parser parser;
00041   return parser.escape(text);
00042 }
00043 
00044 static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
00045 {
00046   std::string result;
00047   result += "<" + tag + ">";
00048 
00049   if ( escape)
00050    result += xml_escape(text);
00051   else
00052    result += text;
00053 
00054   result += "</" + tag + ">";
00055   return result;
00056 }
00057 
00058 static std::ostream & operator<<( std::ostream & str, const boost::tribool obj )
00059 {
00060   if (obj)
00061     return str << "true";
00062   else if (!obj)
00063     return str << "false";
00064   else
00065     return str << "indeterminate";
00066 }
00067 
00074 static std::string translatedTextToXML(const TranslatedText &text, const std::string &tagname)
00075 {
00076   std::set<Locale> locales = text.locales();
00077   //ERR << "locale contains " << locales.size() << " translations" << std::endl;
00078   std::stringstream out;
00079   for ( std::set<Locale>::const_iterator it = locales.begin(); it != locales.end(); ++it)
00080   {
00081     //ERR << "serializing " << (*it).code() << std::endl;
00082     if ( *it == Locale() )
00083       out << "<" << tagname << ">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << std::endl;
00084     else
00085       out << "<" << tagname << " lang=\"" << (*it).code() << "\">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << std::endl;
00086   }
00087   return out.str();
00088 }
00089 
00090 template<class T>
00091 std::string toXML( const T &obj ); //undefined
00092 
00093 template<> 
00094 std::string toXML( const Edition &edition )
00095 {
00096   stringstream out;
00097   // sad the yum guys did not acll it edition
00098   out << "<version ver=\"" << xml_escape(edition.version()) << "\" rel=\"" << xml_escape(edition.release()) << "\" epoch=\"" << edition.epoch() << "\" />";
00099   return out.str();
00100 }
00101 
00102 template<> 
00103 std::string toXML( const Arch &arch )
00104 {
00105   stringstream out;
00106   out << xml_tag_enclose(xml_escape(arch.asString()), "arch");
00107   return out.str();
00108 }
00109 
00110 template<> 
00111 std::string toXML( const Capability &cap )
00112 {
00113   stringstream out;
00114   CapFactory factory;
00115 
00116   out << "<capability kind=\"" << cap.refers() << "\" >" <<  xml_escape(factory.encode(cap)) << "</capability>" << std::endl;
00117   return out.str();
00118 }
00119 
00120 template<> 
00121 std::string toXML( const CapSet &caps )
00122 {
00123   stringstream out;
00124   CapSet::iterator it = caps.begin();
00125   for ( ; it != caps.end(); ++it)
00126   {
00127     out << toXML((*it));
00128   }
00129   return out.str();
00130 }
00131 
00132 template<> 
00133 std::string toXML( const Dependencies &dep )
00134 {
00135   stringstream out;
00136   if ( dep[Dep::PROVIDES].size() > 0 )
00137     out << "    " << xml_tag_enclose(toXML(dep[Dep::PROVIDES]), "provides") << std::endl;
00138   if ( dep[Dep::PREREQUIRES].size() > 0 )
00139     out << "    " << xml_tag_enclose(toXML(dep[Dep::PREREQUIRES]), "prerequires") << std::endl;
00140   if ( dep[Dep::CONFLICTS].size() > 0 )
00141     out << "    " << xml_tag_enclose(toXML(dep[Dep::CONFLICTS]), "conflicts") << std::endl;
00142   if ( dep[Dep::OBSOLETES].size() > 0 )
00143     out << "    " << xml_tag_enclose(toXML(dep[Dep::OBSOLETES]), "obsoletes") << std::endl;
00144   // why the YUM tag is freshen without s????
00145   if ( dep[Dep::FRESHENS].size() > 0 )
00146     out << "    " << xml_tag_enclose(toXML(dep[Dep::FRESHENS]), "freshens") << std::endl;
00147   if ( dep[Dep::REQUIRES].size() > 0 )
00148     out << "    " << xml_tag_enclose(toXML(dep[Dep::REQUIRES]), "requires") << std::endl;  
00149   if ( dep[Dep::RECOMMENDS].size() > 0 )
00150     out << "    " << xml_tag_enclose(toXML(dep[Dep::RECOMMENDS]), "recommends") << std::endl;
00151   if ( dep[Dep::ENHANCES].size() > 0 )
00152     out << "    " << xml_tag_enclose(toXML(dep[Dep::ENHANCES]), "enhances") << std::endl;
00153   if ( dep[Dep::SUPPLEMENTS].size() > 0 )
00154     out << "    " << xml_tag_enclose(toXML(dep[Dep::SUPPLEMENTS]), "supplements") << std::endl;
00155   if ( dep[Dep::SUGGESTS].size() > 0 )
00156     out << "    " << xml_tag_enclose(toXML(dep[Dep::SUGGESTS]), "suggests") << std::endl;
00157   return out.str();
00158 
00159 }
00160 
00161 template<> 
00162 std::string toXML( const Resolvable::constPtr &obj )
00163 {
00164   stringstream out;
00165 
00166   out << "  <name>" << xml_escape(obj->name()) << "</name>" << std::endl;
00167   // is this shared? uh
00168   out << "  " << toXML(obj->edition()) << std::endl;
00169   out << "  " << toXML(obj->arch()) << std::endl;
00170   out << "  " << toXML(obj->deps()) << std::endl;
00171   return out.str();
00172 }
00173 
00174 template<> 
00175 std::string toXML( const ResObject::constPtr &obj )
00176 {
00177   stringstream out;
00178 
00179   // access implementation
00180   detail::ResImplTraits<ResObject::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
00181   out << translatedTextToXML(pipp->summary(), "summary");
00182   out << translatedTextToXML(pipp->description(), "description");
00183   
00184   out << translatedTextToXML(pipp->insnotify(), "install-notify");
00185   out << translatedTextToXML(pipp->delnotify(), "delete-notify");
00186   //out << "  <license-to-confirm>" << xml_escape(obj->licenseToConfirm()) << "</license-to-confirm>" << std::endl;
00187   out << translatedTextToXML(pipp->licenseToConfirm(), "license-to-confirm");
00188   out << "  <vendor>" << xml_escape(obj->vendor()) << "</vendor>" << std::endl;
00189   out << "  <size>" << static_cast<ByteCount::SizeType>(obj->size()) << "</size>" << std::endl;
00190   out << "  <archive-size>" << static_cast<ByteCount::SizeType>(obj->archivesize()) << "</archive-size>" << std::endl;
00191   out << "  <install-only>" << ( obj->installOnly() ? "true" : "false" ) << "</install-only>" << std::endl;
00192   out << "  <build-time>" << obj->buildtime().asSeconds()  << "</build-time>" << std::endl;
00193   // we assume we serialize on storeObject, set install time to NOW
00194   out << "  <install-time>" << Date::now().asSeconds() << "</install-time>" << std::endl;
00195   
00196   return out.str();
00197 }
00198 
00199 template<> 
00200 std::string toXML( const Package::constPtr &obj )
00201 {
00202   stringstream out;
00203   out << "<package>" << std::endl;
00204   // reuse Resolvable information serialize function
00205   out << toXML(static_cast<Resolvable::constPtr>(obj));
00206   out << toXML(static_cast<ResObject::constPtr>(obj));
00207   //out << "  <do>" << std::endl;
00208   //out << "      " << obj->do_script() << std::endl;
00209   //out << "  </do>" << std::endl;
00210   out << "</package>" << std::endl;
00211   return out.str();
00212 }
00213 
00214 template<> 
00215 std::string toXML( const Script::constPtr &obj )
00216 {
00217   stringstream out;
00218   out << "<script>" << std::endl;
00219   // reuse Resolvable information serialize function
00220   out << toXML(static_cast<Resolvable::constPtr>(obj));
00221   out << toXML(static_cast<ResObject::constPtr>(obj));
00222   out << "  <do>" << std::endl;
00223   out << "  <![CDATA[" << std::endl;
00224   
00225   // read script
00226   ifstream infile;
00227   infile.open(obj->do_script().asString().c_str());
00228   while (infile.good())
00229   {
00230     char c = (char)infile.get();
00231     if (! infile.eof())
00232       out << c;
00233   }
00234   infile.close();
00235   
00236   out << "  ]]>" << std::endl;
00237   out << "  </do>" << std::endl;
00238 
00239   if ( obj->undo_available() )
00240   {
00241     out << "  <undo>" << std::endl;
00242     out << "  <![CDATA[" << std::endl;
00243   
00244   // read script
00245     infile.open(obj->undo_script().asString().c_str());
00246     while (infile.good())
00247     {
00248       char c = (char)infile.get();
00249       if (! infile.eof())
00250         out << c;
00251     }
00252     infile.close();
00253   
00254     out << "  ]]>" << std::endl;
00255     out << "  </undo>" << std::endl;
00256 
00257   }
00258   out << "</script>" << std::endl;
00259   return out.str();
00260 }
00261 
00262 template<> 
00263 std::string toXML( const Message::constPtr &obj )
00264 {
00265   stringstream out;
00266   out << "<message>" << std::endl;
00267   // reuse Resolvable information serialize function
00268   out << toXML(static_cast<Resolvable::constPtr>(obj));
00269   out << toXML(static_cast<ResObject::constPtr>(obj));
00270   out << "  <text>" << xml_escape(obj->text().text()) << "</text>" << std::endl;
00271   out << "</message>" << std::endl;
00272   return out.str();
00273 }
00274 
00275 template<> 
00276 std::string toXML( const Language::constPtr &obj )
00277 {
00278   stringstream out;
00279   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00280   out << "<language version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00281   out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00282   out << toXML(static_cast<ResObject::constPtr>(obj));
00283   out << "</language>" << std::endl;
00284   return out.str();
00285 }
00286 
00287 
00288 template<> 
00289 std::string toXML( const Selection::constPtr &obj )
00290 {
00291   stringstream out;
00292   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00293   out << "<pattern version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00294   
00295   out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00296   out << toXML(static_cast<ResObject::constPtr>(obj));
00297   
00298   //out << "  <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << std::endl;
00299   out << "  <uservisible>" << (obj->visible() ? "true" : "false" ) << "</uservisible>" << std::endl;
00300   out << "  <category>" << xml_escape(obj->category()) << "</category>" << std::endl;
00301   out << "  <icon></icon>" << std::endl;
00302   out << "</pattern>" << std::endl;
00303   return out.str();
00304 }
00305 
00306 template<> 
00307 std::string toXML( const Atom::constPtr &obj )
00308 {
00309   stringstream out;
00310   out << "<atom>" << std::endl;
00311   out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00312   out << toXML(static_cast<ResObject::constPtr>(obj));
00313   out << "</atom>" << std::endl;
00314   return out.str();
00315 }
00316 
00317 template<> 
00318 std::string toXML( const Pattern::constPtr &obj )
00319 {
00320   stringstream out;
00321   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00322   out << "<pattern version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00323 
00324   out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00325   out << toXML(static_cast<ResObject::constPtr>(obj));
00326   
00327   out << "  <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << std::endl;
00328   out << "  <uservisible>" << (obj->userVisible() ? "true" : "false" ) << "</uservisible>" << std::endl;
00329   out << "  <category>" << xml_escape(obj->category()) << "</category>" << std::endl;
00330   out << "  <icon>" << xml_escape(obj->icon().asString()) << "</icon>" << std::endl;
00331   out << "  <script>" << xml_escape(obj->script().asString()) << "</script>" << std::endl;
00332   out << "</pattern>" << std::endl;
00333   return out.str();
00334 }
00335 
00336 template<> 
00337 std::string toXML( const Product::constPtr &obj )
00338 {
00339   stringstream out;
00340   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00341   out << "<product version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\" type=\"" << xml_escape(obj->category()) << "\">" << std::endl;
00342   out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00343   #warning "FIXME description and displayname of products"
00344   
00345   out << toXML(static_cast<ResObject::constPtr>(obj));
00346   
00347   // access implementation
00348   detail::ResImplTraits<Product::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
00349   out << translatedTextToXML(pipp->shortName(), "shortname");
00350   
00351   out << "  <distribution-name>" << xml_escape(obj->distributionName()) << "</distribution-name>" << std::endl;
00352   out << "  <distribution-edition>" << xml_escape(obj->distributionEdition().asString()) << "</distribution-edition>" << std::endl;
00353   out << "  <source>" << xml_escape(obj->source().alias()) << "</source>" << std::endl;  
00354   out << "  <release-notes-url>" << xml_escape(obj->releaseNotesUrl().asString()) << "</release-notes-url>" << std::endl;
00355   
00356   out << "  <update-urls>" << std::endl;
00357   std::list<Url> updateUrls = obj->updateUrls();
00358   for ( std::list<Url>::const_iterator it = updateUrls.begin(); it != updateUrls.end(); ++it)
00359   {
00360     out << "    <update-url>" << xml_escape(it->asString()) << "</update-url>" << std::endl; 
00361   }
00362   out << "  </update-urls>" << std::endl;
00363   
00364   out << "  <extra-urls>" << std::endl;
00365   std::list<Url> extraUrls = obj->extraUrls();
00366   for ( std::list<Url>::const_iterator it = extraUrls.begin(); it != extraUrls.end(); ++it)
00367   {
00368     out << "    <extra-url>" << xml_escape(it->asString()) << "</extra-url>" << std::endl; 
00369   }
00370   out << "  </extra-urls>" << std::endl;
00371   
00372   out << "  <optional-urls>" << std::endl;
00373   std::list<Url> optionalUrls = obj->optionalUrls();
00374   for ( std::list<Url>::const_iterator it = optionalUrls.begin(); it != optionalUrls.end(); ++it)
00375   {
00376     out << "    <optional-url>" << xml_escape(it->asString()) << "</optional-url>" << std::endl; 
00377   }
00378   out << "  </optional-urls>" << std::endl;
00379   
00380   out << "  <product-flags>" << std::endl;
00381   std::list<std::string> flags = obj->flags();
00382   for ( std::list<std::string>::const_iterator it = flags.begin(); it != flags.end(); ++it)
00383   {
00384     out << "    <product-flag>" << xml_escape(*it) << "</product-flag>" << std::endl; 
00385   }
00386   out << "  </product-flags>" << std::endl;
00387   
00388   out << "</product>" << std::endl;
00389 
00390   return out.str();
00391 }
00392 
00393 
00394 std::string castedToXML( const Resolvable::constPtr &resolvable )
00395 {
00396   stringstream out;
00397   if ( isKind<Package>(resolvable) )
00398      out << toXML(asKind<const Package>(resolvable)) << std::endl;
00399   if ( isKind<Patch>(resolvable) )
00400      out << toXML(asKind<const Patch>(resolvable)) << std::endl;
00401   if ( isKind<Message>(resolvable) )
00402      out << toXML(asKind<const Message>(resolvable)) << std::endl;
00403   if ( isKind<Script>(resolvable) )
00404      out << toXML(asKind<const Script>(resolvable)) << std::endl;
00405   if ( isKind<Atom>(resolvable) )
00406      out << toXML(asKind<const Atom>(resolvable)) << std::endl;
00407   if ( isKind<Product>(resolvable) )
00408      out << toXML(asKind<const Product>(resolvable)) << std::endl;
00409   if ( isKind<Pattern>(resolvable) )
00410      out << toXML(asKind<const Pattern>(resolvable)) << std::endl;
00411   if ( isKind<Selection>(resolvable) )
00412      out << toXML(asKind<const Selection>(resolvable)) << std::endl;
00413   if ( isKind<Language>(resolvable) )
00414     out << toXML(asKind<const Language>(resolvable)) << std::endl;
00415   return out.str();
00416 }
00417 
00418 std::string resolvableTypeToString( const Resolvable::constPtr &resolvable, bool plural )
00419 {
00420   return resolvableKindToString(resolvable->kind(), plural);
00421 }
00422 
00423 std::string resolvableKindToString( const Resolvable::Kind &kind, bool plural)
00424 {
00425   std::string k = kind.asString();
00426   if (k.substr(k.size() - 2, 2) == "ch")
00427     return k + (plural?"es":"");
00428   else
00429     return k + (plural?"s":"");
00430 }
00431 
00432 template<> 
00433 std::string toXML( const Patch::constPtr &obj )
00434 {
00435   stringstream out;
00436   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00437   out << "<patch version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl; 
00438   
00439   // reuse Resolvable information serialize function
00440   out << toXML(static_cast<Resolvable::constPtr>(obj));
00441   out << toXML(static_cast<ResObject::constPtr>(obj));
00442   
00443   out << "<id>" << xml_escape(obj->id()) << "</id>" << std::endl;
00444   out << "<timestamp>" << obj->timestamp().asSeconds() << "</timestamp>" << std::endl;
00445   
00446   out << "<category>" << obj->category() << "</category>" << std::endl;
00447   out << "<affects-package-manager>" << ( obj->affects_pkg_manager() ? "true" : "false" ) << "</affects-package-manager>" << std::endl;
00448   out << "<reboot-needed>" << ( obj->reboot_needed() ? "true" : "false" ) << "</reboot-needed>" << std::endl;
00449   out << "<interactive>" << ( obj->interactive() ? "true" : "false" ) << "</interactive>" << std::endl;
00450   
00451   Patch::AtomList at = obj->atoms();
00452   out << "  <atoms>" << std::endl;
00453   for (Patch::AtomList::iterator it = at.begin(); it != at.end(); it++)
00454   {
00455     Resolvable::Ptr one_atom = *it;
00456     out << castedToXML(one_atom) << std::endl;
00457   }
00458   out << "  </atoms>" << std::endl;
00459   out << "</patch>" << std::endl;
00460   return out.str();
00461 }
00462 
00463 template<> 
00464 std::string toXML( const source::SourceInfo &obj )
00465 {
00466   stringstream out;
00467   out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00468   out << "<source version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00469   out << "  <enabled>" << obj.enabled() << "</enabled>" << std::endl;
00470   out << "  <auto-refresh>" << obj.autorefresh() << "</auto-refresh>" << std::endl;
00471   out << "  <product-dir>" << obj.path() << "</product-dir>" << std::endl;
00472   out << "  <cache-dir>" << obj.cacheDir() << "</cache-dir>" << std::endl;
00473   out << "  <type>" << xml_escape(obj.type()) << "</type>" << std::endl;
00474   out << "  <url>" << xml_escape(obj.url().asCompleteString()) << "</url>" << std::endl;
00475   out << "  <alias>" << xml_escape(obj.alias()) << "</alias>" << std::endl;
00476   out << "</source>" << std::endl;
00477   return out.str();
00478 }
00479 
00481 } // namespace storage
00484 } // namespace zypp

Generated on Tue Nov 28 16:49:33 2006 for zypp by  doxygen 1.5.0