Revision control
++ // Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
++ // Copyright (C) 2016 Intel Corporation.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
++
++ #include <QCommandLineParser>
++ #include <QCoreApplication>
++ #include <QDir>
++ #include <QFile>
++ #include <QJsonDocument>
++ #include <QJsonObject>
++ #include <QLibrary>
++ #include <QPluginLoader>
++ #include <QStringList>
++
++ #include <iostream>
++
++ enum PrintOption {
++ PrintIID = 0x01,
++ PrintClassName = 0x02,
++ PrintQtInfo = 0x04,
++ PrintUserData = 0x08
++ };
++ Q_DECLARE_FLAGS(PrintOptions, PrintOption)
++ Q_DECLARE_OPERATORS_FOR_FLAGS(PrintOptions)
++
++ int main(int argc, char** argv)
++ {
++ QCoreApplication app(argc, argv);
++ QCoreApplication::setApplicationName(QStringLiteral("qplugininfo"));
++ QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR));
++
++ QCommandLineParser parser;
++ parser.setApplicationDescription(QStringLiteral("Qt plugin meta-data dumper"));
++ QCommandLineOption jsonFormatOption(QStringList() << "f" << "json-format",
++ QStringLiteral("Print JSON data as: indented, compact"), QStringLiteral("format"));
++ QCommandLineOption fullJsonOption("full-json",
++ QStringLiteral("Print the plugin metadata in JSON format"));
++ QCommandLineOption printOption(QStringList() << "p" << QStringLiteral("print"),
++ QStringLiteral("Print detail (iid, classname, qtinfo, userdata)"), QStringLiteral("detail"));
++ jsonFormatOption.setDefaultValue(QStringLiteral("indented"));
++ printOption.setDefaultValues(QStringList() << QStringLiteral("iid") << QStringLiteral("qtinfo") << QStringLiteral("userdata"));
++
++ parser.addOption(fullJsonOption);
++ parser.addOption(jsonFormatOption);
++ parser.addOption(printOption);
++ parser.addHelpOption();
++ parser.addVersionOption();
++ parser.addPositionalArgument(QStringLiteral("plugin"), QStringLiteral("Plug-in of which to read the meta data."), QStringLiteral("<plugin>"));
++ parser.process(app);
++
++ if (parser.positionalArguments().isEmpty())
++ parser.showHelp(1);
++
++ bool fullJson = parser.isSet(fullJsonOption);
++ QJsonDocument::JsonFormat jsonFormat = parser.value(jsonFormatOption) == "indented" ? QJsonDocument::Indented : QJsonDocument::Compact;
++ QStringList printOptionList = parser.values(printOption);
++ PrintOptions print;
++ if (printOptionList.contains("iid"))
++ print |= PrintIID;
++ if (printOptionList.contains("classname"))
++ print |= PrintClassName;
++ if (printOptionList.contains("qtinfo"))
++ print |= PrintQtInfo;
++ if (printOptionList.contains("userdata"))
++ print |= PrintUserData;
++
++ int retval = 0;
++ const QStringList positionalArguments = parser.positionalArguments();
++ for (const QString &plugin : positionalArguments) {
++ QByteArray pluginNativeName = QFile::encodeName(QDir::toNativeSeparators(plugin));
++ if (!QFile::exists(plugin)) {
++ std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No such file or directory." << std::endl;
++ retval = 1;
++ continue;
++ }
++ if (!QLibrary::isLibrary(plugin)) {
++ std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": Not a plug-in." << std::endl;
++ retval = 1;
++ continue;
++ }
++
++ QPluginLoader loader(plugin);
++ QJsonObject metaData = loader.metaData();
++ if (metaData.isEmpty()) {
++ std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No plug-in meta-data found: "
++ << qPrintable(loader.errorString()) << std::endl;
++ retval = 1;
++ continue;
++ }
++
++ QString iid = metaData.value("IID").toString();
++ QString className = metaData.value("className").toString();
++ QJsonValue debug = metaData.value("debug");
++ int version = metaData.value("version").toInt();
++ QJsonValue userData = metaData.value("MetaData");
++
++ if ((version >> 16) != (QT_VERSION >> 16)) {
++ std::cerr << "qtplugininfo: " << pluginNativeName.constData()
++ << ": Qt version mismatch - got major version " << (version >> 16)
++ << ", expected " << (QT_VERSION >> 16) << std::endl;
++ retval = 1;
++ continue;
++ }
++ if (iid.isEmpty() || className.isEmpty() || debug.isNull()) {
++ std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, missing required fields:";
++ if (iid.isEmpty())
++ std::cerr << " iid";
++ if (className.isEmpty())
++ std::cerr << " className";
++ if (debug.isNull())
++ std::cerr << " debug";
++ std::cerr << std::endl;
++ retval = 1;
++ continue;
++ }
++
++ if (parser.positionalArguments().size() != 1)
++ std::cout << pluginNativeName.constData() << ": ";
++ if (fullJson) {
++ std::cout << QJsonDocument(metaData).toJson(jsonFormat).constData();
++ if (jsonFormat == QJsonDocument::Compact)
++ std::cout << std::endl;
++ } else {
++ if (print & PrintIID)
++ std::cout << "IID \"" << qPrintable(iid) << "\" ";
++ if (print & PrintClassName)
++ std::cout << "class " << qPrintable(className) << ' ';
++ if (print & PrintQtInfo)
++ std::cout << "Qt " << (version >> 16) << '.' << ((version >> 8) & 0xFF) << '.' << (version & 0xFF)
++ << (debug.toBool() ? " (debug)" : " (release)");
++ std::cout << std::endl;
++ if (print & PrintUserData) {
++ if (userData.isObject())
++ std::cout << "User Data: " << QJsonDocument(userData.toObject()).toJson().constData();
++ else if (!userData.isNull()) {
++ std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, user data is not a JSON object" << std::endl;
++ retval = 1;
++ }
++ }
++ }
++ }
++
++ return retval;
++ }