1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com> |
4 | ** Copyright (C) 2016 Intel Corporation. |
5 | ** Contact: https://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the tools applications of the Qt Toolkit |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at https://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include <QCommandLineParser> |
31 | #include <QCoreApplication> |
32 | #include <QDir> |
33 | #include <QFile> |
34 | #include <QJsonDocument> |
35 | #include <QJsonObject> |
36 | #include <QLibrary> |
37 | #include <QPluginLoader> |
38 | #include <QStringList> |
39 | |
40 | #include <iostream> |
41 | |
42 | enum PrintOption { |
43 | PrintIID = 0x01, |
44 | PrintClassName = 0x02, |
45 | PrintQtInfo = 0x04, |
46 | PrintUserData = 0x08 |
47 | }; |
48 | Q_DECLARE_FLAGS(PrintOptions, PrintOption) |
49 | Q_DECLARE_OPERATORS_FOR_FLAGS(PrintOptions) |
50 | |
51 | int main(int argc, char** argv) |
52 | { |
53 | QCoreApplication app(argc, argv); |
54 | QCoreApplication::setApplicationName(QStringLiteral("qplugininfo" )); |
55 | QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR)); |
56 | |
57 | QCommandLineParser parser; |
58 | parser.setApplicationDescription(QStringLiteral("Qt5 plugin meta-data dumper" )); |
59 | QCommandLineOption jsonFormatOption(QStringList() << "f" << "json-format" , |
60 | QStringLiteral("Print JSON data as: indented, compact" ), QStringLiteral("format" )); |
61 | QCommandLineOption fullJsonOption("full-json" , |
62 | QStringLiteral("Print the plugin metadata in JSON format" )); |
63 | QCommandLineOption printOption(QStringList() << "p" << QStringLiteral("print" ), |
64 | QStringLiteral("Print detail (iid, classname, qtinfo, userdata)" ), QStringLiteral("detail" )); |
65 | jsonFormatOption.setDefaultValue(QStringLiteral("indented" )); |
66 | printOption.setDefaultValues(QStringList() << QStringLiteral("iid" ) << QStringLiteral("qtinfo" ) << QStringLiteral("userdata" )); |
67 | |
68 | parser.addOption(commandLineOption: fullJsonOption); |
69 | parser.addOption(commandLineOption: jsonFormatOption); |
70 | parser.addOption(commandLineOption: printOption); |
71 | parser.addHelpOption(); |
72 | parser.addVersionOption(); |
73 | parser.addPositionalArgument(QStringLiteral("plugin" ), QStringLiteral("Plug-in of which to read the meta data." ), QStringLiteral("<plugin>" )); |
74 | parser.process(app); |
75 | |
76 | if (parser.positionalArguments().isEmpty()) |
77 | parser.showHelp(exitCode: 1); |
78 | |
79 | bool fullJson = parser.isSet(option: fullJsonOption); |
80 | QJsonDocument::JsonFormat jsonFormat = parser.value(option: jsonFormatOption) == "indented" ? QJsonDocument::Indented : QJsonDocument::Compact; |
81 | QStringList printOptionList = parser.values(option: printOption); |
82 | PrintOptions print; |
83 | if (printOptionList.contains(str: "iid" )) |
84 | print |= PrintIID; |
85 | if (printOptionList.contains(str: "classname" )) |
86 | print |= PrintClassName; |
87 | if (printOptionList.contains(str: "qtinfo" )) |
88 | print |= PrintQtInfo; |
89 | if (printOptionList.contains(str: "userdata" )) |
90 | print |= PrintUserData; |
91 | |
92 | int retval = 0; |
93 | const QStringList positionalArguments = parser.positionalArguments(); |
94 | for (const QString &plugin : positionalArguments) { |
95 | QByteArray pluginNativeName = QFile::encodeName(fileName: QDir::toNativeSeparators(pathName: plugin)); |
96 | if (!QFile::exists(fileName: plugin)) { |
97 | std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No such file or directory." << std::endl; |
98 | retval = 1; |
99 | continue; |
100 | } |
101 | if (!QLibrary::isLibrary(fileName: plugin)) { |
102 | std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": Not a plug-in." << std::endl; |
103 | retval = 1; |
104 | continue; |
105 | } |
106 | |
107 | QPluginLoader loader(plugin); |
108 | QJsonObject metaData = loader.metaData(); |
109 | if (metaData.isEmpty()) { |
110 | std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No plug-in meta-data found: " |
111 | << qPrintable(loader.errorString()) << std::endl; |
112 | retval = 1; |
113 | continue; |
114 | } |
115 | |
116 | QString iid = metaData.value(key: "IID" ).toString(); |
117 | QString className = metaData.value(key: "className" ).toString(); |
118 | QJsonValue debug = metaData.value(key: "debug" ); |
119 | int version = metaData.value(key: "version" ).toInt(); |
120 | QJsonValue userData = metaData.value(key: "MetaData" ); |
121 | |
122 | if ((version >> 16) != (QT_VERSION >> 16)) { |
123 | std::cerr << "qtplugininfo: " << pluginNativeName.constData() |
124 | << ": Qt version mismatch - got major version " << (version >> 16) |
125 | << ", expected " << (QT_VERSION >> 16) << std::endl; |
126 | retval = 1; |
127 | continue; |
128 | } |
129 | if (iid.isEmpty() || className.isEmpty() || debug.isNull()) { |
130 | std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, missing required fields:" ; |
131 | if (iid.isEmpty()) |
132 | std::cerr << " iid" ; |
133 | if (className.isEmpty()) |
134 | std::cerr << " className" ; |
135 | if (debug.isNull()) |
136 | std::cerr << " debug" ; |
137 | std::cerr << std::endl; |
138 | retval = 1; |
139 | continue; |
140 | } |
141 | |
142 | if (parser.positionalArguments().size() != 1) |
143 | std::cout << pluginNativeName.constData() << ": " ; |
144 | if (fullJson) { |
145 | std::cout << QJsonDocument(metaData).toJson(format: jsonFormat).constData(); |
146 | if (jsonFormat == QJsonDocument::Compact) |
147 | std::cout << std::endl; |
148 | } else { |
149 | if (print & PrintIID) |
150 | std::cout << "IID \"" << qPrintable(iid) << "\" " ; |
151 | if (print & PrintClassName) |
152 | std::cout << "class " << qPrintable(className) << ' '; |
153 | if (print & PrintQtInfo) |
154 | std::cout << "Qt " << (version >> 16) << '.' << ((version >> 8) & 0xFF) << '.' << (version & 0xFF) |
155 | << (debug.toBool() ? " (debug)" : " (release)" ); |
156 | std::cout << std::endl; |
157 | if (print & PrintUserData) { |
158 | if (userData.isObject()) |
159 | std::cout << "User Data: " << QJsonDocument(userData.toObject()).toJson().constData(); |
160 | else if (!userData.isNull()) { |
161 | std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, user data is not a JSON object" << std::endl; |
162 | retval = 1; |
163 | } |
164 | } |
165 | } |
166 | } |
167 | |
168 | return retval; |
169 | } |
170 | |