qthighway/xqserviceutil/src/xqservicemetadata/old/xqservicemetadata.cpp
branchRCL_3
changeset 9 5d007b20cfd0
equal deleted inserted replaced
8:885c2596c964 9:5d007b20cfd0
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * This program is free software: you can redistribute it and/or modify
       
     6 * it under the terms of the GNU Lesser General Public License as published by
       
     7 * the Free Software Foundation, version 2.1 of the License.
       
     8 * 
       
     9 * This program is distributed in the hope that it will be useful,
       
    10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 * GNU Lesser General Public License for more details.
       
    13 *
       
    14 * You should have received a copy of the GNU Lesser General Public License
       
    15 * along with this program.  If not, 
       
    16 * see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
       
    17 *
       
    18 * Description:  Service metadata parser class implementation 
       
    19 *
       
    20 */
       
    21 
       
    22 #include "xqservicelog.h"
       
    23 
       
    24 #include <QFile>
       
    25 #include "xqservicemetadata_p.h"
       
    26 #include "xqsfwinterface_p.h"
       
    27  
       
    28 
       
    29 //XML tags and attributes
       
    30 //General
       
    31 #define NAME_TAG  "name"
       
    32 #define DESCRIPTION_TAG "description"
       
    33 
       
    34 //Service related
       
    35 #define SERVICE_TAG "service" 
       
    36 #define SERVICE_FILEPATH "filepath"
       
    37 
       
    38 //Interface related
       
    39 #define INTERFACE_TAG "interface"
       
    40 #define INTERFACE_VERSION "version" 
       
    41 #define INTERFACE_CAPABILITY "capabilities"
       
    42 
       
    43 
       
    44 QT_BEGIN_NAMESPACE
       
    45 
       
    46 static const char  PATH_SEPARATOR[] = "\\";
       
    47 
       
    48 /*!
       
    49     \class ServiceMetaData
       
    50 
       
    51     Utility class (used by service database) that offers support for 
       
    52     parsing metadata service xml registry file during service registration. \n
       
    53     
       
    54     It uses QXMLStreamReader class for parsing. Supproted Operations are:
       
    55         - Parse the service and interfaces defined in XML file
       
    56         - name, version, capabilitiesList, description and filePath of service can be retrieved
       
    57         - each interface can be retrieved
       
    58 */
       
    59 
       
    60 /*!
       
    61  *  Class constructor
       
    62  *
       
    63  * @param aXmlFilePath path to the xml file that describes the service. 
       
    64  */
       
    65 ServiceMetaData::ServiceMetaData(const QString &aXmlFilePath)
       
    66 {
       
    67     XQSERVICE_DEBUG_PRINT("ServiceMetaData::ServiceMetaData(1)");
       
    68     XQSERVICE_DEBUG_PRINT("aXmlFilePath: %s", qPrintable(aXmlFilePath));
       
    69     xmlDevice = new QFile(aXmlFilePath);
       
    70     ownsXmlDevice = true;
       
    71     latestError = 0;
       
    72 }
       
    73 
       
    74 /*!
       
    75  *  Class constructor
       
    76  *
       
    77  * @param device QIODevice that contains the XML data that describes the service.
       
    78  */
       
    79 ServiceMetaData::ServiceMetaData(QIODevice *device)
       
    80 {
       
    81     XQSERVICE_DEBUG_PRINT("ServiceMetaData::ServiceMetaData(2)");
       
    82     xmlDevice = device;
       
    83     ownsXmlDevice = false;
       
    84     latestError = 0;
       
    85 }
       
    86 
       
    87 /*!
       
    88  *  Class destructor
       
    89  * 
       
    90  */
       
    91 ServiceMetaData::~ServiceMetaData()
       
    92 {
       
    93     XQSERVICE_DEBUG_PRINT("ServiceMetaData::~ServiceMetaData");
       
    94     if (ownsXmlDevice)
       
    95         delete xmlDevice;
       
    96 }
       
    97 
       
    98 /*!
       
    99     Sets the device containing the XML data that describes the service to \a device.
       
   100  */
       
   101 void ServiceMetaData::setDevice(QIODevice *device)
       
   102 {
       
   103     XQSERVICE_DEBUG_PRINT("ServiceMetaData::setDevice");
       
   104     clearMetadata();
       
   105     xmlDevice = device;
       
   106     ownsXmlDevice = false;
       
   107 }
       
   108 
       
   109 /*!
       
   110     Returns the device containing the XML data that describes the service.
       
   111 */
       
   112 QIODevice *ServiceMetaData::device() const
       
   113 {
       
   114     XQSERVICE_DEBUG_PRINT("ServiceMetaData::device");
       
   115     return xmlDevice;
       
   116 }
       
   117 
       
   118 /*!
       
   119  *  Gets the service name
       
   120  *
       
   121  * @return service name or default value (empty string) if it is not available
       
   122  */
       
   123 QString ServiceMetaData::name()
       
   124 {
       
   125     XQSERVICE_DEBUG_PRINT("ServiceMetaData::name");
       
   126     XQSERVICE_DEBUG_PRINT("serviceName: %s", qPrintable(serviceName));
       
   127     return serviceName;
       
   128 }
       
   129  
       
   130 /*!
       
   131  *  Sets the path of service implementation file
       
   132  *
       
   133  * @param aFilePath path of service implementation file
       
   134  */
       
   135 void ServiceMetaData::setServiceFilePath(const QString &aFilePath)
       
   136 {
       
   137     XQSERVICE_DEBUG_PRINT("ServiceMetaData::setServiceFilePath");
       
   138     XQSERVICE_DEBUG_PRINT("aFilePath: %s", qPrintable(aFilePath));
       
   139     serviceFilePath = aFilePath;
       
   140 }
       
   141  
       
   142 /*!
       
   143  *  Gets the path of the service implementation file
       
   144  *
       
   145  * @return service implementation filepath
       
   146  */
       
   147 QString ServiceMetaData::filePath()
       
   148 {
       
   149     XQSERVICE_DEBUG_PRINT("ServiceMetaData::filePath");
       
   150     XQSERVICE_DEBUG_PRINT("serviceFilePath: %s", qPrintable(serviceFilePath));
       
   151     return serviceFilePath;
       
   152 }
       
   153  
       
   154 /*!
       
   155  *  Gets the service description
       
   156  *
       
   157  * @return service description or default value (empty string) if it is not available
       
   158  */
       
   159 QString ServiceMetaData::description()
       
   160 {
       
   161     XQSERVICE_DEBUG_PRINT("ServiceMetaData::description");
       
   162     XQSERVICE_DEBUG_PRINT("serviceDescription: %s", qPrintable(serviceDescription));
       
   163     return serviceDescription;
       
   164 }
       
   165  
       
   166 /*!
       
   167    Returns the number of interfaces provided by the service description
       
   168  */
       
   169 int ServiceMetaData::interfaceCount()
       
   170 {
       
   171     XQSERVICE_DEBUG_PRINT("ServiceMetaData::interfaceCount"); 
       
   172     XQSERVICE_DEBUG_PRINT("serviceInterfaces.count(): %d", serviceInterfaces.count());
       
   173     return serviceInterfaces.count();
       
   174 }
       
   175  
       
   176 /*!
       
   177    Returns the metadata of the interace at \a index; otherwise
       
   178    returns 0.
       
   179  */
       
   180 QList<SFWInterface> ServiceMetaData::getInterfaces()
       
   181 {
       
   182     XQSERVICE_DEBUG_PRINT("ServiceMetaData::getInterfaces");
       
   183     return serviceInterfaces;
       
   184 } 
       
   185 
       
   186 /*!
       
   187     Parses the file and extracts the service metadata \n
       
   188     Custom error codes: \n
       
   189     SFW_ERROR_UNABLE_TO_OPEN_FILE in case can not open the XML file \n
       
   190     SFW_ERROR_INVALID_XML_FILE in case service registry is not a valid XML file \n
       
   191     SFW_ERROR_NO_SERVICE in case XML file has no service tag\n
       
   192     @return true if the metadata was read properly, false if there is an error
       
   193  */
       
   194 bool ServiceMetaData::extractMetadata()
       
   195 {
       
   196     XQSERVICE_DEBUG_PRINT("ServiceMetaData::extractMetadata");
       
   197     latestError = 0;
       
   198     clearMetadata();                   
       
   199     QXmlStreamReader xmlReader;
       
   200     bool parseError = false;
       
   201     //Open xml file
       
   202     if (!xmlDevice->isOpen() && !xmlDevice->open(QIODevice::ReadOnly)) {
       
   203         XQSERVICE_DEBUG_PRINT("Couldn't open the file");
       
   204         latestError = ServiceMetaData::SFW_ERROR_UNABLE_TO_OPEN_FILE;
       
   205         parseError = true;
       
   206     } else {
       
   207         //Load xml content
       
   208         xmlReader.setDevice(xmlDevice);
       
   209         // Read XML doc 
       
   210         while (!xmlReader.atEnd() && !parseError) {
       
   211             xmlReader.readNext();
       
   212             //Found a <service> node, read service related metadata
       
   213             if (xmlReader.isStartElement() && xmlReader.name() == SERVICE_TAG) {
       
   214                 if (!processServiceElement(xmlReader)) {
       
   215                     XQSERVICE_DEBUG_PRINT("Couldn't process service element");
       
   216                     parseError = true;
       
   217                 }
       
   218             }
       
   219             else if (xmlReader.isStartElement() && xmlReader.name() != SERVICE_TAG) {
       
   220                 XQSERVICE_DEBUG_PRINT("No service");
       
   221                 latestError = ServiceMetaData::SFW_ERROR_NO_SERVICE;
       
   222                 parseError = true;
       
   223             }
       
   224             else if (xmlReader.tokenType() == QXmlStreamReader::Invalid) {
       
   225                 XQSERVICE_DEBUG_PRINT("Invalid XML");
       
   226                 latestError = ServiceMetaData::SFW_ERROR_INVALID_XML_FILE;
       
   227                 parseError = true;
       
   228             }
       
   229         }
       
   230         if (ownsXmlDevice)
       
   231             xmlDevice->close();
       
   232     }
       
   233     if (parseError) {
       
   234         clearMetadata();
       
   235     }
       
   236     XQSERVICE_DEBUG_PRINT("parseError: %d", parseError);
       
   237     return !parseError;
       
   238 }
       
   239  
       
   240 /*!
       
   241     Gets the latest parsing error \n
       
   242     @return parsing error(negative value) or 0 in case there is none
       
   243  */
       
   244 int ServiceMetaData::getLatestError()
       
   245 {
       
   246     XQSERVICE_DEBUG_PRINT("ServiceMetaData::getLatestError");
       
   247     XQSERVICE_DEBUG_PRINT("latestError: %d", latestError);
       
   248     return latestError;
       
   249 }
       
   250  
       
   251 /*!
       
   252     Gets the value of the attribute from the XML node \n
       
   253     @param aDomElement xml node
       
   254     @param aAttributeName attribute name
       
   255     @param aValue [out] attribute value
       
   256     @return true if the value was read, false otherwise
       
   257  */
       
   258 bool ServiceMetaData::getAttributeValue(const QXmlStreamReader &aXMLReader, const QString &aAttributeName, QString &aValue)
       
   259 {
       
   260     XQSERVICE_DEBUG_PRINT("ServiceMetaData::getAttributeValue");
       
   261     XQSERVICE_DEBUG_PRINT("aAttributeName: %s", qPrintable(aAttributeName));
       
   262     bool result = false;
       
   263     for (int i = 0; i < aXMLReader.attributes().count(); i++){
       
   264         QXmlStreamAttribute att = aXMLReader.attributes()[i];
       
   265         if (att.name() == aAttributeName) {
       
   266             if (att.value().isNull() || att.value().isEmpty()) {
       
   267                 result = false;
       
   268             } else {
       
   269                 result = true;
       
   270                 aValue = att.value().toString();
       
   271                 XQSERVICE_DEBUG_PRINT("aValue: %s", qPrintable(aValue));
       
   272             }
       
   273         }
       
   274     }
       
   275     // Capability attribute is allowed to be empty
       
   276     if (aAttributeName == INTERFACE_CAPABILITY) {
       
   277         result = true;
       
   278     }
       
   279     XQSERVICE_DEBUG_PRINT("result: %d", result);
       
   280     return result;
       
   281 }
       
   282   
       
   283 /*!
       
   284     Parses and extracts the service metadata from the current xml <service> node \n
       
   285     Custom error codes: \n
       
   286     SFW_ERROR_NO_SERVICE_NAME in case no service name in XML file \n
       
   287     SFW_ERROR_NO_INTERFACE_VERSION in case no interface version in XML file \n
       
   288     SFW_ERROR_PARSE_SERVICE in case can not parse service section in XML file \n
       
   289     SFW_ERROR_NO_SERVICE_FILEPATH in case no service file path in XML file \n
       
   290     SFW_ERROR_INVALID_XML_FILE in case XML file is not valid \n
       
   291     SFW_ERROR_NO_SERVICE_INTERFACE in case no interface defined for service in XML file \n
       
   292     @param aXMLReader xml stream reader 
       
   293     @return true if the metadata was read properly, false if there is an error
       
   294  */
       
   295 bool ServiceMetaData::processServiceElement(QXmlStreamReader &aXMLReader)
       
   296 {
       
   297     XQSERVICE_DEBUG_PRINT("ServiceMetaData::processServiceElement");
       
   298     Q_ASSERT(aXMLReader.isStartElement() && aXMLReader.name() == SERVICE_TAG);
       
   299     bool parseError = false;
       
   300 
       
   301     if (!getAttributeValue(aXMLReader, NAME_TAG, serviceName)) {
       
   302         XQSERVICE_DEBUG_PRINT("No service name");
       
   303         latestError = ServiceMetaData::SFW_ERROR_NO_SERVICE_NAME;
       
   304         parseError = true;
       
   305     }
       
   306 
       
   307     if (!parseError) {
       
   308         if (!getAttributeValue(aXMLReader, SERVICE_FILEPATH, serviceFilePath)) {
       
   309             XQSERVICE_DEBUG_PRINT("No service filepath");
       
   310             latestError = ServiceMetaData::SFW_ERROR_NO_SERVICE_FILEPATH;
       
   311             parseError = true;
       
   312         }
       
   313     }
       
   314 
       
   315     while (!parseError && !aXMLReader.atEnd()) {
       
   316         aXMLReader.readNext();  
       
   317         if (aXMLReader.name() == DESCRIPTION_TAG) {
       
   318             serviceDescription = aXMLReader.readElementText();
       
   319             XQSERVICE_DEBUG_PRINT("serviceDescription: %s", qPrintable(serviceDescription));
       
   320         //Found a <interface> node, read module related metadata  
       
   321         } else if (aXMLReader.isStartElement() && aXMLReader.name() == INTERFACE_TAG) {
       
   322             if (!processInterfaceElement(aXMLReader)){
       
   323                 XQSERVICE_DEBUG_PRINT("Couldn't process interface element");
       
   324                 parseError = true;
       
   325             }
       
   326         //Found </service>, leave the loop
       
   327         } else if (aXMLReader.isEndElement() && aXMLReader.name() == SERVICE_TAG) {
       
   328             XQSERVICE_DEBUG_PRINT("Service element handled");
       
   329             break;
       
   330         } else if (aXMLReader.isEndElement() || aXMLReader.isStartElement()) {
       
   331             XQSERVICE_DEBUG_PRINT("Service parse error");
       
   332             latestError = ServiceMetaData::SFW_ERROR_PARSE_SERVICE;
       
   333             parseError = true;            
       
   334         } else if (aXMLReader.tokenType() == QXmlStreamReader::Invalid) {
       
   335             XQSERVICE_DEBUG_PRINT("Invalid XML");
       
   336             latestError = ServiceMetaData::SFW_ERROR_INVALID_XML_FILE;
       
   337             parseError = true;
       
   338         }
       
   339     }
       
   340 
       
   341     if (serviceInterfaces.count() == 0 && latestError == 0) {
       
   342         XQSERVICE_DEBUG_PRINT("No service interface");
       
   343         latestError = ServiceMetaData::SFW_ERROR_NO_SERVICE_INTERFACE;
       
   344         parseError = true;
       
   345     }
       
   346     if (parseError) {
       
   347         clearMetadata();
       
   348     }
       
   349     XQSERVICE_DEBUG_PRINT("parseError: %d", parseError);
       
   350     return !parseError;
       
   351 }
       
   352 
       
   353 /*!
       
   354     Parses and extracts the interface metadata from the current xml <interface> node \n
       
   355     Custome error codes: \n
       
   356     SFW_ERROR_NO_INTERFACE_NAME in case no interface name in XML file \n
       
   357     SFW_ERROR_PARSE_INTERFACE in case error parsing interface section \n
       
   358     SFW_ERROR_INVALID_XML_FILE in case XML file is not valid \n
       
   359     @param aXMLReader xml stream reader 
       
   360     @return true if the metadata was read properly, false if there is an error
       
   361  */
       
   362 bool ServiceMetaData::processInterfaceElement(QXmlStreamReader &aXMLReader)
       
   363 {
       
   364     XQSERVICE_DEBUG_PRINT("ServiceMetaData::processInterfaceElement");
       
   365     Q_ASSERT(aXMLReader.isStartElement() && aXMLReader.name() == INTERFACE_TAG);
       
   366     bool parseError = false;
       
   367 
       
   368     //Read interface parameter
       
   369     QString tmp;
       
   370     SFWInterface aInterface("");
       
   371     if (getAttributeValue(aXMLReader, NAME_TAG, tmp)) {
       
   372         XQSERVICE_DEBUG_PRINT("Name attribute value");
       
   373         aInterface = SFWInterface(tmp);
       
   374         tmp.clear();
       
   375         if (getAttributeValue(aXMLReader, INTERFACE_VERSION, tmp)) {
       
   376             XQSERVICE_DEBUG_PRINT("Interface version value");
       
   377             bool success = checkVersion(tmp);
       
   378             if ( success ) {
       
   379                 aInterface.setVersion(tmp);
       
   380                 tmp.clear();
       
   381                 if (getAttributeValue(aXMLReader, INTERFACE_CAPABILITY, tmp)) {
       
   382                     XQSERVICE_DEBUG_PRINT("Interface capability value");
       
   383                     aInterface.setCapabilities(tmp.split(",", QString::SkipEmptyParts));
       
   384                 }
       
   385             } else {
       
   386                 XQSERVICE_DEBUG_PRINT("Invalid interface version");
       
   387                 latestError = ServiceMetaData::SFW_ERROR_INVALID_VERSION;
       
   388                 parseError = true;
       
   389             }
       
   390         }
       
   391         else{
       
   392             XQSERVICE_DEBUG_PRINT("No interface version");
       
   393             latestError = ServiceMetaData::SFW_ERROR_NO_INTERFACE_VERSION;
       
   394             parseError = true;
       
   395         }
       
   396     } else {
       
   397         XQSERVICE_DEBUG_PRINT("No interface name");
       
   398         latestError = ServiceMetaData::SFW_ERROR_NO_INTERFACE_NAME;
       
   399         parseError = true;
       
   400     }
       
   401 
       
   402     while (!parseError && !aXMLReader.atEnd()) {
       
   403         aXMLReader.readNext();
       
   404         //Read interface description
       
   405         if (aXMLReader.isStartElement() && aXMLReader.name() == DESCRIPTION_TAG) {
       
   406             XQSERVICE_DEBUG_PRINT("Interface description");
       
   407             aInterface.setDescription(aXMLReader.readElementText());
       
   408         //Found </interface>, leave the loop
       
   409         } else if (aXMLReader.isEndElement() && aXMLReader.name() == INTERFACE_TAG) {
       
   410             XQSERVICE_DEBUG_PRINT("Interface handled");
       
   411             break;  
       
   412         } else if (aXMLReader.isStartElement() || aXMLReader.isEndElement()) {
       
   413             XQSERVICE_DEBUG_PRINT("Interface parse error");
       
   414             latestError = ServiceMetaData::SFW_ERROR_PARSE_INTERFACE;
       
   415             parseError = true;
       
   416         } else if (aXMLReader.tokenType() == QXmlStreamReader::Invalid) {
       
   417             XQSERVICE_DEBUG_PRINT("Invalid XML");
       
   418             latestError = ServiceMetaData::SFW_ERROR_INVALID_XML_FILE;
       
   419             parseError = true;
       
   420         }
       
   421     }
       
   422 
       
   423     if (!parseError) {
       
   424         const QString ident = aInterface.name()+aInterface.version();
       
   425         XQSERVICE_DEBUG_PRINT("ident: %s", qPrintable(ident));
       
   426         if (duplicates.contains(ident.toLower())) {
       
   427             XQSERVICE_DEBUG_PRINT("Duplicate interface");
       
   428             latestError = ServiceMetaData::SFW_ERROR_DUPLICATED_INTERFACE;
       
   429             parseError = true;
       
   430         } else {
       
   431             duplicates.insert(ident.toLower());
       
   432             serviceInterfaces.append(aInterface);
       
   433         }
       
   434     }
       
   435     XQSERVICE_DEBUG_PRINT("parseError: %d", parseError);
       
   436     return !parseError;
       
   437 }
       
   438 
       
   439 bool ServiceMetaData::checkVersion(const QString &version)
       
   440 {
       
   441     XQSERVICE_DEBUG_PRINT("ServiceMetaData::checkVersion");
       
   442     //match x.y as version format
       
   443     QRegExp rx("^([1-9][0-9]*)\\.(0+|[1-9][0-9]*)$");
       
   444     int pos = rx.indexIn(version);
       
   445     QStringList list = rx.capturedTexts();
       
   446     bool success = false;
       
   447     if (pos == 0 && list.count() == 3
       
   448             && rx.matchedLength() == version.length() )
       
   449     {
       
   450         list[1].toInt(&success);
       
   451         if ( success ) {
       
   452             list[2].toInt(&success);
       
   453         }
       
   454     }
       
   455     XQSERVICE_DEBUG_PRINT("success: %d", success);
       
   456     return success;
       
   457 }
       
   458 
       
   459 /*!
       
   460  *  Clears the service metadata
       
   461  *
       
   462  */
       
   463 void ServiceMetaData::clearMetadata()
       
   464 {
       
   465     XQSERVICE_DEBUG_PRINT("ServiceMetaData::clearMetadata");
       
   466     serviceName.clear();
       
   467     serviceFilePath.clear();
       
   468     serviceDescription.clear();
       
   469     serviceInterfaces.clear();
       
   470     duplicates.clear();
       
   471 }
       
   472 
       
   473 QT_END_NAMESPACE