From e29ef32ec02e01d51065962e0b0f88c70121b3de Mon Sep 17 00:00:00 2001 From: kh1 Date: Tue, 26 Mar 2013 13:10:09 +0100 Subject: Add strict and relaxed parsing to Settings class. * StrictParseMode -> creating binaries and repositories * RelaxedParseMode -> running the installer/updater itself Introduced parse modes to be able to use old settings (existing ones on user systems) with new binaries. Add and adjust autotest. Change-Id: I3f7c7357325661a1197400d8d8dc2a5ca8bed184 Reviewed-by: Karsten Heimrich --- src/libs/installer/packagemanagercoredata.cpp | 2 +- src/libs/installer/settings.cpp | 99 +++++++++++++++++---------- src/libs/installer/settings.h | 8 ++- src/libs/installer/updatesettings.cpp | 2 +- 4 files changed, 70 insertions(+), 41 deletions(-) (limited to 'src/libs') diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp index 660a72922..7dbdf4e1a 100644 --- a/src/libs/installer/packagemanagercoredata.cpp +++ b/src/libs/installer/packagemanagercoredata.cpp @@ -73,7 +73,7 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash &va try { m_settings = Settings::fromFileAndPrefix(QLatin1String(":/metadata/installer-config/config.xml"), - QLatin1String(":/metadata/installer-config/")); + QLatin1String(":/metadata/installer-config/"), Settings::RelaxedParseMode); } catch (const Error &e) { // TODO: try better error handling qCritical("Could not parse Config: %s", qPrintable(e.message())); diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp index 79eee652f..0a2abaa9a 100644 --- a/src/libs/installer/settings.cpp +++ b/src/libs/installer/settings.cpp @@ -79,38 +79,57 @@ static QSet variantListToSet(const QVariantList &list) return set; } -static QSet readRepositories(QXmlStreamReader &reader, bool isDefault) +static void raiseError(QXmlStreamReader &reader, const QString &error, Settings::ParseMode parseMode) +{ + if (parseMode == Settings::StrictParseMode) { + reader.raiseError(error); + } else { + QFile *xmlFile = qobject_cast(reader.device()); + if (xmlFile) { + qWarning() << QString::fromLatin1("Ignoring following settings reader error in %1, line %2, " + "column %3: %4").arg(xmlFile->fileName()).arg(reader.lineNumber()).arg(reader.columnNumber()) + .arg(reader.errorString()); + } else { + qWarning("Ignoring following settings reader error: %s", qPrintable(error)); + } + } +} + +static QSet readRepositories(QXmlStreamReader &reader, bool isDefault, Settings::ParseMode parseMode) { QSet set; while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("Repository")) { Repository repo(QString(), isDefault); while (reader.readNextStartElement()) { - if (reader.name() == QLatin1String("Url")) + if (reader.name() == QLatin1String("Url")) { repo.setUrl(reader.readElementText()); - else if (reader.name() == QLatin1String("Username")) + } else if (reader.name() == QLatin1String("Username")) { repo.setUsername(reader.readElementText()); - else if (reader.name() == QLatin1String("Password")) + } else if (reader.name() == QLatin1String("Password")) { repo.setPassword(reader.readElementText()); - else if (reader.name() == QLatin1String("Enabled")) + } else if (reader.name() == QLatin1String("Enabled")) { repo.setEnabled(bool(reader.readElementText().toInt())); - else - reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg( - reader.name().toString())); + } else { + raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name() + .toString()), parseMode); + } - if (!reader.attributes().isEmpty()) - reader.raiseError(QString::fromLatin1("Unexpected attribute for element '%1'.").arg( - reader.name().toString())); + if (!reader.attributes().isEmpty()) { + raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.") + .arg(reader.name().toString()), parseMode); + } } set.insert(repo); } else { - reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg( - reader.name().toString())); + raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name().toString()), + parseMode); } - if (!reader.attributes().isEmpty()) - reader.raiseError(QString::fromLatin1("Unexpected attribute for element '%1'.").arg( - reader.name().toString())); + if (!reader.attributes().isEmpty()) { + raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.").arg(reader + .name().toString()), parseMode); + } } return set; } @@ -123,33 +142,33 @@ static QVariantHash readTitles(QXmlStreamReader &reader) return hash; } -static QHash readPages(QXmlStreamReader &reader) +static QHash readPages(QXmlStreamReader &reader, Settings::ParseMode parseMode) { QHash hash; while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("Page")) { QVariantHash pageElements; const QString pageName = reader.attributes().value(QLatin1String("name")).toString(); - if (pageName.isEmpty()) - reader.raiseError(QLatin1String("Expected non-empty attribute 'name' for element 'Page'.")); - + if (pageName.isEmpty()) { + raiseError(reader, QLatin1String("Expected non-empty attribute 'name' for element 'Page'."), + parseMode); + } while (reader.readNextStartElement()) { const QString name = reader.name().toString(); - if (name == QLatin1String("Title") || name == QLatin1String("SubTitle")) { + if (name == QLatin1String("Title") || name == QLatin1String("SubTitle")) pageElements.insert(name, readTitles(reader)); - } else { + else pageElements.insert(name, reader.readElementText(QXmlStreamReader::SkipChildElements)); - } } hash.insert(pageName, pageElements); } else { - reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg(reader.name().toString())); + raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name().toString()), + parseMode); } } return hash; } - // -- Settings::Private class Settings::Private : public QSharedData @@ -195,7 +214,7 @@ Settings& Settings::operator=(const Settings &other) } /* static */ -Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix) +Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix, ParseMode parseMode) { QFile file(path); QFile overrideConfig(QLatin1String(":/overrideconfig.xml")); @@ -208,9 +227,10 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix) QXmlStreamReader reader(&file); if (reader.readNextStartElement()) { - if (reader.name() != QLatin1String("Installer")) - reader.raiseError(QString::fromLatin1("Unexpected element '%1' as root element.").arg( - reader.name().toString())); + if (reader.name() != QLatin1String("Installer")) { + raiseError(reader, QString::fromLatin1("Unexpected element '%1' as root element.").arg(reader + .name().toString()), parseMode); + } } QStringList elementList; elementList << scName << scVersion << scTitle << scPublisher << scProductUrl @@ -230,34 +250,37 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix) s.d->m_data.insert(scPrefix, prefix); while (reader.readNextStartElement()) { const QString name = reader.name().toString(); - if (!elementList.contains(name)) - reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg(name)); + raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(name), parseMode); - if (!reader.attributes().isEmpty()) - reader.raiseError(QString::fromLatin1("Unexpected attribute for element '%1'.").arg(name)); + if (!reader.attributes().isEmpty()) { + raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.").arg(name), + parseMode); + } if (blackList.contains(name)) { if (name == scRemoteRepositories) - s.addDefaultRepositories(readRepositories(reader, true)); + s.addDefaultRepositories(readRepositories(reader, true, parseMode)); if (name == scPages) { qWarning() << "Deprecated element 'Pages'."; - QHash pages = readPages(reader); + QHash pages = readPages(reader, parseMode); const QStringList &keys = pages.keys(); foreach (const QString &key, keys) s.d->m_data.insert(key, pages.value(key)); } } else { - if (s.d->m_data.contains(name)) + if (s.d->m_data.contains(name)) { + // instead of raising parse mode based error, raise a real error reader.raiseError(QString::fromLatin1("Element '%1' has been defined before.").arg(name)); + } s.d->m_data.insert(name, reader.readElementText(QXmlStreamReader::SkipChildElements)); } } if (reader.error() != QXmlStreamReader::NoError) { - throw Error(QString::fromLatin1("Error in %1, line %2, column %3: %4") - .arg(path).arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); + throw Error(QString::fromLatin1("Error in %1, line %2, column %3: %4").arg(path).arg(reader + .lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); } if (s.d->m_data.value(scName).isNull()) diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h index 8ffbfc004..fcea7cb55 100644 --- a/src/libs/installer/settings.h +++ b/src/libs/installer/settings.h @@ -74,13 +74,19 @@ public: UserDefinedProxy }; + enum ParseMode { + StrictParseMode, + RelaxedParseMode + }; + explicit Settings(); ~Settings(); Settings(const Settings &other); Settings &operator=(const Settings &other); - static Settings fromFileAndPrefix(const QString &path, const QString &prefix); + static Settings fromFileAndPrefix(const QString &path, const QString &prefix, + ParseMode parseMode = StrictParseMode); QString logo() const; QString title() const; diff --git a/src/libs/installer/updatesettings.cpp b/src/libs/installer/updatesettings.cpp index da6ab9319..2e876839f 100644 --- a/src/libs/installer/updatesettings.cpp +++ b/src/libs/installer/updatesettings.cpp @@ -153,7 +153,7 @@ QSet UpdateSettings::repositories() const try { if(result.isEmpty()) { result = Settings::fromFileAndPrefix(QLatin1String(":/metadata/installer-config/config.xml"), - QLatin1String(":/metadata/installer-config/")).userRepositories(); + QLatin1String(":/metadata/installer-config/"), Settings::RelaxedParseMode).userRepositories(); } } catch (const Error &error) { qDebug("Could not parse config: %s", qPrintable(error.message())); -- cgit v1.2.3