|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include <stdio.h> |
|
43 |
|
44 #include <QtCore> |
|
45 #include <QTextStream> |
|
46 #include <qservicemanager.h> |
|
47 #include <QString> |
|
48 |
|
49 QT_USE_NAMESPACE |
|
50 |
|
51 QTM_USE_NAMESPACE |
|
52 |
|
53 class CommandProcessor : public QObject |
|
54 { |
|
55 Q_OBJECT |
|
56 |
|
57 public: |
|
58 CommandProcessor(QObject *parent = 0); |
|
59 ~CommandProcessor(); |
|
60 |
|
61 void execute(const QStringList &options, const QString &cmd, const QStringList &args); |
|
62 void showUsage(); |
|
63 static void showUsage(QTextStream *stream); |
|
64 |
|
65 public slots: |
|
66 void browse(const QStringList &args); |
|
67 void search(const QStringList &args); |
|
68 void add(const QStringList &args); |
|
69 void remove(const QStringList &args); |
|
70 |
|
71 private: |
|
72 bool setOptions(const QStringList &options); |
|
73 void showAllEntries(); |
|
74 void showInterfaceInfo(const QServiceFilter &filter); |
|
75 void showServiceInfo(const QString &service); |
|
76 |
|
77 QServiceManager *serviceManager; |
|
78 QTextStream *stdoutStream; |
|
79 }; |
|
80 |
|
81 CommandProcessor::CommandProcessor(QObject *parent) |
|
82 : QObject(parent), |
|
83 serviceManager(0), |
|
84 stdoutStream(new QTextStream(stdout)) |
|
85 { |
|
86 } |
|
87 |
|
88 CommandProcessor::~CommandProcessor() |
|
89 { |
|
90 delete stdoutStream; |
|
91 } |
|
92 |
|
93 void CommandProcessor::execute(const QStringList &options, const QString &cmd, const QStringList &args) |
|
94 { |
|
95 if (cmd.isEmpty()) { |
|
96 *stdoutStream << "Error: no command given\n\n"; |
|
97 showUsage(); |
|
98 return; |
|
99 } |
|
100 |
|
101 if (!setOptions(options)) |
|
102 return; |
|
103 |
|
104 int methodIndex = metaObject()->indexOfMethod(cmd.toAscii() + "(QStringList)"); |
|
105 if (methodIndex < 0) { |
|
106 *stdoutStream << "Bad command: " << cmd << "\n\n"; |
|
107 showUsage(); |
|
108 return; |
|
109 } |
|
110 |
|
111 if (!metaObject()->method(methodIndex).invoke(this, Q_ARG(QStringList, args))) |
|
112 *stdoutStream << "Cannot invoke method for command:" << cmd << '\n'; |
|
113 } |
|
114 |
|
115 void CommandProcessor::showUsage() |
|
116 { |
|
117 showUsage(stdoutStream); |
|
118 } |
|
119 |
|
120 void CommandProcessor::showUsage(QTextStream *stream) |
|
121 { |
|
122 *stream << "Usage: servicefw [options] <command> [command parameters]\n\n" |
|
123 "Commands:\n" |
|
124 "\tbrowse List all registered services\n" |
|
125 "\tsearch Search for a service or interface\n" |
|
126 "\tadd Register a service\n" |
|
127 "\tremove Unregister a service\n" |
|
128 "\n" |
|
129 "Options:\n" |
|
130 "\t--system Use the system-wide services database instead of the\n" |
|
131 "\t user-specific database\n" |
|
132 "\n"; |
|
133 } |
|
134 |
|
135 void CommandProcessor::browse(const QStringList &args) |
|
136 { |
|
137 Q_UNUSED(args); |
|
138 showAllEntries(); |
|
139 } |
|
140 |
|
141 void CommandProcessor::search(const QStringList &args) |
|
142 { |
|
143 if (args.isEmpty()) { |
|
144 *stdoutStream << "Usage:\n\tsearch <service|interface [version]>\n\n" |
|
145 "Examples:\n" |
|
146 "\tsearch SomeService\n" |
|
147 "\tsearch com.nokia.SomeInterface\n" |
|
148 "\tsearch com.nokia.SomeInterface 3.5\n" |
|
149 "\tsearch com.nokia.SomeInterface 3.5+\n"; |
|
150 return; |
|
151 } |
|
152 |
|
153 const QString &name = args[0]; |
|
154 if (name.contains('.')) { |
|
155 QServiceFilter filter; |
|
156 if (args.count() > 1) { |
|
157 const QString &version = args[1]; |
|
158 bool minimumMatch = version.endsWith('+'); |
|
159 filter.setInterface(name, |
|
160 minimumMatch ? (version.mid(0, version.length()-1)) : version, |
|
161 minimumMatch ? QServiceFilter::MinimumVersionMatch : QServiceFilter::ExactVersionMatch); |
|
162 if (filter.interfaceName().isEmpty()) { // setInterface() failed |
|
163 *stdoutStream << "Error: invalid interface version: " << version << '\n'; |
|
164 return; |
|
165 } |
|
166 } else { |
|
167 filter.setInterface(name); |
|
168 } |
|
169 showInterfaceInfo(filter); |
|
170 } else { |
|
171 showServiceInfo(name); |
|
172 } |
|
173 } |
|
174 |
|
175 static const char * const errorTable[] = { |
|
176 "No error", //0 |
|
177 "Storage read error", |
|
178 "Invalid service location", |
|
179 "Invalid service xml", |
|
180 "Invalid service interface descriptor", |
|
181 "Service already exists", |
|
182 "Interface implementation already exists", |
|
183 "Loading of plug-in failed", |
|
184 "Service or interface not found", |
|
185 "Insufficient capabilities to access service", |
|
186 "Unknown error" |
|
187 }; |
|
188 |
|
189 void CommandProcessor::add(const QStringList &args) |
|
190 { |
|
191 if (args.isEmpty()) { |
|
192 *stdoutStream << "Usage:\n\tadd <service-xml-file>\n"; |
|
193 return; |
|
194 } |
|
195 |
|
196 const QString &xmlPath = args[0]; |
|
197 if (!QFile::exists(xmlPath)) { |
|
198 *stdoutStream << "Error: cannot find file " << xmlPath << '\n'; |
|
199 return; |
|
200 } |
|
201 |
|
202 if (serviceManager->addService(xmlPath)) { |
|
203 *stdoutStream << "Registered service at " << xmlPath << '\n'; |
|
204 } else { |
|
205 int error = serviceManager->error(); |
|
206 if (error > 11) //map anything larger than 11 to 11 |
|
207 error = 11; |
|
208 *stdoutStream << "Error: cannot register service at " << xmlPath |
|
209 << " (" << errorTable[error] << ")" << '\n'; |
|
210 } |
|
211 } |
|
212 |
|
213 void CommandProcessor::remove(const QStringList &args) |
|
214 { |
|
215 if (args.isEmpty()) { |
|
216 *stdoutStream << "Usage:\n\tremove <service-name>\n"; |
|
217 return; |
|
218 } |
|
219 |
|
220 const QString &service = args[0]; |
|
221 if (serviceManager->removeService(service)) |
|
222 *stdoutStream << "Unregistered service " << service << '\n'; |
|
223 else |
|
224 *stdoutStream << "Error: cannot unregister service " << service << '\n'; |
|
225 } |
|
226 |
|
227 bool CommandProcessor::setOptions(const QStringList &options) |
|
228 { |
|
229 if (serviceManager) |
|
230 delete serviceManager; |
|
231 |
|
232 QStringList opts = options; |
|
233 QMutableListIterator<QString> i(opts); |
|
234 while (i.hasNext()) { |
|
235 if (i.next() == "--system") { |
|
236 serviceManager = new QServiceManager(QService::SystemScope, this); |
|
237 i.remove(); |
|
238 } |
|
239 } |
|
240 |
|
241 if (!opts.isEmpty()) { |
|
242 *stdoutStream << "Bad options: " << opts.join(" ") << "\n\n"; |
|
243 showUsage(); |
|
244 return false; |
|
245 } |
|
246 |
|
247 // other initialization, if not triggered by an option |
|
248 if (!serviceManager) |
|
249 serviceManager = new QServiceManager(this); |
|
250 |
|
251 return true; |
|
252 } |
|
253 |
|
254 void CommandProcessor::showAllEntries() |
|
255 { |
|
256 QStringList services = serviceManager->findServices(); |
|
257 if (services.isEmpty()) |
|
258 *stdoutStream << "No services found.\n"; |
|
259 else if (services.count() == 1) |
|
260 *stdoutStream << "Found 1 service.\n\n"; |
|
261 else |
|
262 *stdoutStream << "Found " << services.count() << " services.\n\n"; |
|
263 foreach (const QString &service, services) |
|
264 showServiceInfo(service); |
|
265 } |
|
266 |
|
267 void CommandProcessor::showInterfaceInfo(const QServiceFilter &filter) |
|
268 { |
|
269 QString interface = filter.interfaceName(); |
|
270 if (filter.majorVersion() >= 0 && filter.minorVersion() >= 0) { |
|
271 interface += QString(" %1.%2").arg(filter.majorVersion()).arg(filter.minorVersion()); |
|
272 if (filter.versionMatchRule() == QServiceFilter::MinimumVersionMatch) |
|
273 interface += '+'; |
|
274 } |
|
275 |
|
276 QList<QServiceInterfaceDescriptor> descriptors = serviceManager->findInterfaces(filter); |
|
277 if (descriptors.isEmpty()) { |
|
278 *stdoutStream << "Interface " << interface << " not found.\n"; |
|
279 return; |
|
280 } |
|
281 |
|
282 *stdoutStream << interface << " is implemented by:\n"; |
|
283 foreach (const QServiceInterfaceDescriptor &desc, descriptors) |
|
284 *stdoutStream << '\t' << desc.serviceName() << '\n'; |
|
285 } |
|
286 |
|
287 void CommandProcessor::showServiceInfo(const QString &service) |
|
288 { |
|
289 QList<QServiceInterfaceDescriptor> descriptors = serviceManager->findInterfaces(service); |
|
290 if (descriptors.isEmpty()) { |
|
291 *stdoutStream << "Service " << service << " not found.\n"; |
|
292 return; |
|
293 } |
|
294 |
|
295 QString description = descriptors[0].attribute( |
|
296 QServiceInterfaceDescriptor::ServiceDescription).toString(); |
|
297 QStringList capabilities = descriptors[0].attribute( |
|
298 QServiceInterfaceDescriptor::Capabilities).toStringList(); |
|
299 |
|
300 *stdoutStream << service << ":\n"; |
|
301 if (!description.isEmpty()) |
|
302 *stdoutStream << '\t' << description << '\n'; |
|
303 *stdoutStream << "\tLibrary: " << descriptors[0].attribute( |
|
304 QServiceInterfaceDescriptor::Location).toString() << '\n' |
|
305 << "\tCapabilities: " << (capabilities.isEmpty() ? "" : capabilities.join(", ")) << '\n' |
|
306 << "\tImplements:\n"; |
|
307 |
|
308 foreach (const QServiceInterfaceDescriptor &desc, descriptors) { |
|
309 *stdoutStream << "\t\t" << desc.interfaceName() << ' ' |
|
310 << desc.majorVersion() << '.' << desc.minorVersion() << '\n'; |
|
311 } |
|
312 } |
|
313 |
|
314 int main(int argc, char *argv[]) |
|
315 { |
|
316 QCoreApplication app(argc, argv); |
|
317 QStringList args = QCoreApplication::arguments(); |
|
318 |
|
319 if (args.count() == 1 || args.value(1) == "--help" || args.value(1) == "-h") { |
|
320 QTextStream stream(stdout); |
|
321 CommandProcessor::showUsage(&stream); |
|
322 return 0; |
|
323 } |
|
324 |
|
325 QStringList options; |
|
326 for (int i=1; i<args.count(); i++) { |
|
327 if (args[i].startsWith("--")) |
|
328 options += args[i]; |
|
329 } |
|
330 |
|
331 CommandProcessor processor; |
|
332 processor.execute(options, args.value(options.count() + 1), args.mid(options.count() + 2)); |
|
333 return 0; |
|
334 } |
|
335 |
|
336 #include "servicefw.moc" |