1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/store/serialize.cc
18 #include <boost/logic/tribool.hpp>
20 #include "zypp/base/Logger.h"
23 #include "zypp/ResObject.h"
24 #include "zypp/repo/ScriptProvider.h"
26 #include "serialize.h"
28 #include "xml_escape_parser.hpp"
31 ///////////////////////////////////////////////////////////////////
33 { /////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
37 static void copyFileToStream( const Pathname & file_r, std::ostream & out_r )
39 std::ifstream infile( file_r.c_str() );
42 char c = (char)infile.get();
49 static string xml_escape( const string &text )
51 iobind::parser::xml_escape_parser parser;
52 return parser.escape(text);
55 static string xml_tag_enclose( const string &text, const string &tag, bool escape = false )
58 result += "<" + tag + ">";
61 result += xml_escape(text);
65 result += "</" + tag + ">";
69 static ostream & operator<<( ostream & str, const boost::tribool obj )
74 return str << "false";
76 return str << "indeterminate";
80 * helper function that builds
81 * <tagname lang="code">text</tagname>
85 static string translatedTextToXML(const TranslatedText &text, const string &tagname)
87 set<Locale> locales = text.locales();
88 //ERR << "locale contains " << locales.size() << " translations" << endl;
90 for ( set<Locale>::const_iterator it = locales.begin(); it != locales.end(); ++it)
92 //ERR << "serializing " << (*it).code() << endl;
93 if ( *it == Locale() )
94 out << "<" << tagname << ">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << endl;
96 out << "<" << tagname << " lang=\"" << (*it).code() << "\">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << endl;
102 string toXML( const T &obj ); //undefined
105 string toXML( const Edition &edition )
108 // sad the yum guys did not acll it edition
109 out << "<version ver=\"" << xml_escape(edition.version()) << "\" rel=\"" << xml_escape(edition.release()) << "\" epoch=\"" << edition.epoch() << "\" />";
114 string toXML( const Arch &arch )
117 out << xml_tag_enclose(xml_escape(arch.asString()), "arch");
122 string toXML( const Capability &cap )
124 #warning FIX WRITING AND READING CAPABILITY (incl old format)
126 //CapFactory factory;
127 //out << "<capability kind=\"" << cap.refers() << "\" >" << xml_escape(factory.encode(cap)) << "</capability>" << endl;
128 out << "<capability>" << cap << "</capability>" << endl; // wrong !
134 string toXML( const Capabilities &caps )
137 Capabilities::const_iterator it = caps.begin();
138 for ( ; it != caps.end(); ++it)
146 string toXML( const Dependencies &dep )
149 if ( dep[Dep::PROVIDES].size() > 0 )
150 out << " " << xml_tag_enclose(toXML(dep[Dep::PROVIDES]), "provides") << endl;
151 if ( dep[Dep::PREREQUIRES].size() > 0 )
152 out << " " << xml_tag_enclose(toXML(dep[Dep::PREREQUIRES]), "prerequires") << endl;
153 if ( dep[Dep::CONFLICTS].size() > 0 )
154 out << " " << xml_tag_enclose(toXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
155 if ( dep[Dep::OBSOLETES].size() > 0 )
156 out << " " << xml_tag_enclose(toXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
157 // why the YUM tag is freshen without s????
158 if ( dep[Dep::FRESHENS].size() > 0 )
159 out << " " << xml_tag_enclose(toXML(dep[Dep::FRESHENS]), "freshens") << endl;
160 if ( dep[Dep::REQUIRES].size() > 0 )
161 out << " " << xml_tag_enclose(toXML(dep[Dep::REQUIRES]), "requires") << endl;
162 if ( dep[Dep::RECOMMENDS].size() > 0 )
163 out << " " << xml_tag_enclose(toXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
164 if ( dep[Dep::ENHANCES].size() > 0 )
165 out << " " << xml_tag_enclose(toXML(dep[Dep::ENHANCES]), "enhances") << endl;
166 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
167 out << " " << xml_tag_enclose(toXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
168 if ( dep[Dep::SUGGESTS].size() > 0 )
169 out << " " << xml_tag_enclose(toXML(dep[Dep::SUGGESTS]), "suggests") << endl;
175 string toXML( const Resolvable::constPtr &obj )
179 out << " <name>" << xml_escape(obj->name()) << "</name>" << endl;
180 // is this shared? uh
181 out << " " << toXML(obj->edition()) << endl;
182 out << " " << toXML(obj->arch()) << endl;
183 out << " " << toXML(obj->deps()) << endl;
188 string toXML( const ResObject::constPtr &obj )
191 #warning FIX WRITING AND READING TRANSLATED TEXTS
192 // access implementation
193 //detail::ResImplTraits<ResObject::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
194 //out << translatedTextToXML(pipp->summary(), "summary");
195 //out << translatedTextToXML(pipp->description(), "description");
197 //out << translatedTextToXML(pipp->insnotify(), "install-notify");
198 //out << translatedTextToXML(pipp->delnotify(), "delete-notify");
199 //out << translatedTextToXML(pipp->licenseToConfirm(), "license-to-confirm");
200 out << " <vendor>" << xml_escape(obj->vendor()) << "</vendor>" << endl;
201 out << " <size>" << static_cast<ByteCount::SizeType>(obj->size()) << "</size>" << endl;
202 out << " <archive-size>" << static_cast<ByteCount::SizeType>(obj->downloadSize()) << "</archive-size>" << endl;
203 out << " <install-only>" << ( obj->installOnly() ? "true" : "false" ) << "</install-only>" << endl;
204 out << " <build-time>" << obj->buildtime().asSeconds() << "</build-time>" << endl;
205 // we assume we serialize on storeObject, set install time to NOW
206 out << " <install-time>" << Date::now().asSeconds() << "</install-time>" << endl;
212 string toXML( const Package::constPtr &obj )
215 out << "<package>" << endl;
216 // reuse Resolvable information serialize function
217 out << toXML(static_cast<Resolvable::constPtr>(obj));
218 out << toXML(static_cast<ResObject::constPtr>(obj));
219 out << "</package>" << endl;
224 string toXML( const Script::constPtr &obj )
227 out << "<script>" << endl;
228 // reuse Resolvable information serialize function
229 out << toXML(static_cast<Resolvable::constPtr>(obj));
230 out << toXML(static_cast<ResObject::constPtr>(obj));
232 repo::RepoMediaAccess access;
233 repo::ScriptProvider prov( access );
235 out << " <do>" << endl;
236 out << " <![CDATA[" << endl;
237 copyFileToStream( prov.provideDoScript( obj ), out );
238 out << " ]]>" << endl;
239 out << " </do>" << endl;
241 if ( obj->undoAvailable() )
243 out << " <undo>" << endl;
244 out << " <![CDATA[" << endl;
245 copyFileToStream( prov.provideUndoScript( obj ), out );
246 out << " ]]>" << endl;
247 out << " </undo>" << endl;
250 out << "</script>" << endl;
255 string toXML( const Message::constPtr &obj )
258 out << "<message>" << endl;
259 // reuse Resolvable information serialize function
260 out << toXML(static_cast<Resolvable::constPtr>(obj));
261 out << toXML(static_cast<ResObject::constPtr>(obj));
262 out << " <text>" << xml_escape(obj->text().text()) << "</text>" << endl;
263 out << "</message>" << endl;
268 string toXML( const Language::constPtr &obj )
271 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
272 out << "<language version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
273 out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
274 out << toXML(static_cast<ResObject::constPtr>(obj));
275 out << "</language>" << endl;
281 string toXML( const Selection::constPtr &obj )
284 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
285 out << "<pattern version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
287 out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
288 out << toXML(static_cast<ResObject::constPtr>(obj));
290 //out << " <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << endl;
291 out << " <uservisible>" << (obj->visible() ? "true" : "false" ) << "</uservisible>" << endl;
292 out << " <category>" << xml_escape(obj->category()) << "</category>" << endl;
293 out << " <icon></icon>" << endl;
294 out << "</pattern>" << endl;
299 string toXML( const Atom::constPtr &obj )
302 out << "<atom>" << endl;
303 out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
304 out << toXML(static_cast<ResObject::constPtr>(obj));
305 out << "</atom>" << endl;
310 string toXML( const Pattern::constPtr &obj )
313 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
314 out << "<pattern version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
316 out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
317 out << toXML(static_cast<ResObject::constPtr>(obj));
319 out << " <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << endl;
320 out << " <uservisible>" << (obj->userVisible() ? "true" : "false" ) << "</uservisible>" << endl;
321 out << " <category>" << xml_escape(obj->category()) << "</category>" << endl;
322 out << " <icon>" << xml_escape(obj->icon().asString()) << "</icon>" << endl;
323 out << " <script>" << xml_escape(obj->script().asString()) << "</script>" << endl;
324 out << "</pattern>" << endl;
329 string toXML( const Product::constPtr &obj )
332 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
333 out << "<product version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\" type=\"" << xml_escape(obj->type()) << "\">" << endl;
334 out << toXML(static_cast<Resolvable::constPtr>(obj)) << endl;
335 #warning "FIXME description and displayname of products"
337 out << toXML(static_cast<ResObject::constPtr>(obj));
339 #warning FIX WRITING AND READING TRANSLATED TEXTS
340 // access implementation
341 // detail::ResImplTraits<Product::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
342 // out << translatedTextToXML(pipp->shortName(), "shortname");
344 out << " <distribution-name>" << xml_escape(obj->distributionName()) << "</distribution-name>" << endl;
345 out << " <distribution-edition>" << xml_escape(obj->distributionEdition().asString()) << "</distribution-edition>" << endl;
346 out << " <source>" << xml_escape(obj->repository().info().alias()) << "</source>" << endl;
347 out << " <release-notes-url>" << xml_escape(obj->releaseNotesUrl().asString()) << "</release-notes-url>" << endl;
349 out << " <update-urls>" << endl;
350 list<Url> updateUrls = obj->updateUrls();
351 for ( list<Url>::const_iterator it = updateUrls.begin(); it != updateUrls.end(); ++it)
353 out << " <update-url>" << xml_escape(it->asString()) << "</update-url>" << endl;
355 out << " </update-urls>" << endl;
357 out << " <extra-urls>" << endl;
358 list<Url> extraUrls = obj->extraUrls();
359 for ( list<Url>::const_iterator it = extraUrls.begin(); it != extraUrls.end(); ++it)
361 out << " <extra-url>" << xml_escape(it->asString()) << "</extra-url>" << endl;
363 out << " </extra-urls>" << endl;
365 out << " <optional-urls>" << endl;
366 list<Url> optionalUrls = obj->optionalUrls();
367 for ( list<Url>::const_iterator it = optionalUrls.begin(); it != optionalUrls.end(); ++it)
369 out << " <optional-url>" << xml_escape(it->asString()) << "</optional-url>" << endl;
371 out << " </optional-urls>" << endl;
373 out << " <product-flags>" << endl;
374 list<string> flags = obj->flags();
375 for ( list<string>::const_iterator it = flags.begin(); it != flags.end(); ++it)
377 out << " <product-flag>" << xml_escape(*it) << "</product-flag>" << endl;
379 out << " </product-flags>" << endl;
381 out << "</product>" << endl;
387 string castedToXML( const Resolvable::constPtr &resolvable )
390 if ( isKind<Package>(resolvable) )
391 out << toXML(asKind<const Package>(resolvable)) << endl;
392 if ( isKind<Patch>(resolvable) )
393 out << toXML(asKind<const Patch>(resolvable)) << endl;
394 if ( isKind<Message>(resolvable) )
395 out << toXML(asKind<const Message>(resolvable)) << endl;
396 if ( isKind<Script>(resolvable) )
397 out << toXML(asKind<const Script>(resolvable)) << endl;
398 if ( isKind<Atom>(resolvable) )
399 out << toXML(asKind<const Atom>(resolvable)) << endl;
400 if ( isKind<Product>(resolvable) )
401 out << toXML(asKind<const Product>(resolvable)) << endl;
402 if ( isKind<Pattern>(resolvable) )
403 out << toXML(asKind<const Pattern>(resolvable)) << endl;
404 if ( isKind<Selection>(resolvable) )
405 out << toXML(asKind<const Selection>(resolvable)) << endl;
406 if ( isKind<Language>(resolvable) )
407 out << toXML(asKind<const Language>(resolvable)) << endl;
411 string resolvableTypeToString( const Resolvable::constPtr &resolvable, bool plural )
413 return resolvableKindToString(resolvable->kind(), plural);
416 string resolvableKindToString( const Resolvable::Kind &kind, bool plural)
418 string k = kind.asString();
419 if (k.substr(k.size() - 2, 2) == "ch")
420 return k + (plural?"es":"");
422 return k + (plural?"s":"");
426 string toXML( const Patch::constPtr &obj )
429 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
430 out << "<patch version=\"" << SERIALIZER_VERSION << "\" xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << endl;
432 // reuse Resolvable information serialize function
433 out << toXML(static_cast<Resolvable::constPtr>(obj));
434 out << toXML(static_cast<ResObject::constPtr>(obj));
436 out << "<id>" << xml_escape(obj->id()) << "</id>" << endl;
437 out << "<timestamp>" << obj->timestamp().asSeconds() << "</timestamp>" << endl;
439 out << "<category>" << obj->category() << "</category>" << endl;
440 out << "<affects-package-manager>" << ( obj->affects_pkg_manager() ? "true" : "false" ) << "</affects-package-manager>" << endl;
441 out << "<reboot-needed>" << ( obj->reboot_needed() ? "true" : "false" ) << "</reboot-needed>" << endl;
443 Patch::AtomList at = obj->atoms();
444 out << " <atoms>" << endl;
445 for (Patch::AtomList::iterator it = at.begin(); it != at.end(); it++)
447 Resolvable::Ptr one_atom = *it;
448 out << castedToXML(one_atom) << endl;
450 out << " </atoms>" << endl;
451 out << "</patch>" << endl;
455 /////////////////////////////////////////////////////////////////
456 } // namespace storage
457 ///////////////////////////////////////////////////////////////////
458 /////////////////////////////////////////////////////////////////
460 ///////////////////////////////////////////////////////////////////