devicediagnosticsfw/diagframework/src/diagpluginloaderdependencyparser.cpp
changeset 0 b497e44ab2fc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devicediagnosticsfw/diagframework/src/diagpluginloaderdependencyparser.cpp	Thu Dec 17 09:07:52 2009 +0200
@@ -0,0 +1,596 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Parse dependency information from XML in ECOM plug-in
+                 resource files
+*
+*/
+
+
+// CLASS DECLARATION
+#include "diagpluginloaderdependencyparser.h"
+
+// SYSTEM INCLUDE FILES
+#include <xml/parser.h>         // CParser
+#include <badesca.h>
+#include <e32svr.h>
+#include <DiagFrameworkDebug.h> // LOGSTRING
+
+// USER INCLUDE FILES
+
+using namespace Xml;
+
+namespace DiagPluginPool
+    {
+// ============================================================================
+// LOCAL DATA
+// ============================================================================
+
+_LIT8( KParserMIMEType, "text/xml" );
+_LIT8( KRootXmlTag, "diagplugininfo" );
+_LIT8( KOrderNumberTag, "order" );
+_LIT8( KServiceProvidedTag, "serviceprovided" );
+_LIT8( KServicesRequiredTag, "servicesrequired" );
+_LIT8( KServiceTag, "service" );
+_LIT8( KNameAttrTag, "name" );
+_LIT8( KNumberAttrTag, "number" );
+
+// ============================================================================
+// MEMBER FUNCTIONS( CDepdendencyParser )
+// ============================================================================
+
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CDependencyParser* CDependencyParser::NewL()
+    {
+    CDependencyParser* self = CDependencyParser::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// NewLC
+// ---------------------------------------------------------------------------
+//
+CDependencyParser* CDependencyParser::NewLC()
+    {
+    CDependencyParser* self = new( ELeave )CDependencyParser;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    } 
+
+// ---------------------------------------------------------------------------
+// ~CDependencyParser
+// ---------------------------------------------------------------------------
+//
+CDependencyParser::~CDependencyParser()
+    {
+    delete iParser;
+    delete iServiceProvided;
+    if ( iServicesRequired )
+        {
+        iServicesRequired->Reset();
+        }
+    delete iServicesRequired;
+    }
+
+// ---------------------------------------------------------------------------
+// ParseL
+// ---------------------------------------------------------------------------
+//
+void CDependencyParser::ParseL( const TDesC8& aOpaqueData, const TDesC8& aDefaultData )
+    {
+    
+    ASSERT( aOpaqueData.Length() );    
+    ASSERT( aDefaultData.Length() );        
+    
+    // Start out by deleting and zeroing old elements
+    if ( iHasBeenRun )
+        {        
+        ResetL();
+        }        
+           
+    iHasBeenRun = ETrue;
+    
+    // Get Parent UID    
+    iParseStatus = ParseToUid( aDefaultData, iParentUid );       
+    
+    // Do not parse opaque data if UID is invalid because plug-in will not be loaded
+    // when data error is detected.        
+    if ( iParseStatus == KErrNone )    
+        {
+        // Parse buffer in one fell swoop            
+        iParser->ParseBeginL();    
+        iParser->ParseL( aOpaqueData );    
+        iParser->ParseEndL();            
+        }            
+    
+    // Check for error from parser
+    User::LeaveIfError( iParseStatus );
+    
+    // Check for error in format
+    if ( iBadXML )
+        {
+        User::Leave( KErrCorrupt );
+        }
+    }
+   
+// ---------------------------------------------------------------------------
+// GetOrderNumber
+// ---------------------------------------------------------------------------
+//    
+TInt CDependencyParser::GetOrderNumber() const
+    {
+    return iOrderNumber;
+    }
+    
+// ---------------------------------------------------------------------------
+// GetServiceProvided
+// ---------------------------------------------------------------------------
+//    
+HBufC* CDependencyParser::GetServiceProvided()
+    {
+    HBufC* ret = iServiceProvided;
+    iServiceProvided = NULL;
+    return ret;
+    }
+ 
+// ---------------------------------------------------------------------------
+// GetServicesRequired
+// ---------------------------------------------------------------------------
+//   
+CDesC16ArrayFlat* CDependencyParser::GetServicesRequired()
+    {
+    // Ownership is passed to caller
+    CDesC16ArrayFlat* ret = iServicesRequired;    
+    iServicesRequired = NULL;
+    return ret;
+    }
+    
+// ---------------------------------------------------------------------------
+// GetServicesRequired
+// ---------------------------------------------------------------------------
+//       
+const TUid& CDependencyParser::GetParentUid() const
+    {
+    return iParentUid;       
+    }
+
+// ---------------------------------------------------------------------------
+// From Xml::MContentHandler
+// OnStartElementL
+// ---------------------------------------------------------------------------
+//
+void CDependencyParser::OnStartElementL(
+    const RTagInfo& aElement,
+    const RAttributeArray& aAttributes,
+    TInt aErrorCode
+    )
+    {
+    const TDesC8& elementName8 = aElement.LocalName().DesC();
+    
+#ifdef _DEBUG   
+    HBufC* elementName16 = Convert8BitTo16BitBufferLC( elementName8 );
+    LOGSTRING3( "OnStartElementL %S %d\n", elementName16, aErrorCode )
+    CleanupStack::PopAndDestroy( elementName16 );    
+#endif
+    
+    /*
+    Parse XML tags in the following sample format:
+    
+    <diagplugininfo>
+       <order number="5"/>
+       <serviceprovided name="Browser"/>
+       <servicesrequired>"
+           <service name="SIM"/>
+           <service name="Graphics"/>
+       </servicesrequired>
+   </diagplugininfo>   
+    */        
+    
+    if ( !iInsideRootNode )
+        {
+        // Look for root node
+        if ( ! elementName8.Compare( KRootXmlTag ) )
+            {
+            iInsideRootNode = ETrue;
+            }
+        else
+            {
+            LOGSTRING( "Error: unexpected element looking for root node.\n" )
+            iBadXML = ETrue;
+            }
+        }
+    else // Look for "body" nodes
+        {
+        // Check order number
+        if ( ! elementName8.Compare( KOrderNumberTag ) )
+            {
+            LOGSTRING("Order number\n")
+            if ( ValidateXmlTag( aAttributes, iFoundOrderNumber ))
+                {
+                if ( ! ParseNumericAttribute( aAttributes[0], iOrderNumber ) )
+                    {
+                    LOGSTRING2( "Order Number: \'%d\'\n", iOrderNumber )
+                    }
+                else
+                    {                                       
+                    iBadXML = ETrue;
+                    }
+                }           
+            }
+        // Check service provided
+        else if ( ! elementName8.Compare( KServiceProvidedTag ) )
+            {
+            LOGSTRING("Service Provided\n")
+            
+            if ( ValidateXmlTag( aAttributes, iFoundServiceProvided ))
+                {
+                if ( ! ParseStringAttributeL( aAttributes[0], iServiceProvided ) )
+                                            
+                    {                    
+                    LOGSTRING2( "Service Provided \"%S\"\n", iServiceProvided )
+                    }
+                else
+                    {                    
+                    iBadXML = ETrue;
+                    }
+                }              
+            }
+
+        // Check services required block
+        else if ( ! elementName8.Compare( KServicesRequiredTag ) )
+            {
+            if ( ! iFoundServicesRequired )
+                {                
+                iParsingServicesRequired = ETrue;
+                iFoundServicesRequired = ETrue;
+                }
+            else
+                {                
+                LOGSTRING( "Error: unexpected services required tag found.\n" )
+                iBadXML = ETrue;
+                }
+            }
+        
+        // Check service tag
+        else if ( ! elementName8.Compare( KServiceTag ) )
+            {
+            LOGSTRING("Service\n")
+            
+            // OK to have multiple service tags so use dummy as "found" flag
+            TBool Dummy = EFalse;
+            
+            if ( ValidateXmlTag( aAttributes, Dummy ))
+                {
+                HBufC* newService = NULL;
+                
+                if ( ! ParseStringAttributeL( aAttributes[0],
+                                                newService ) )
+                    {
+                    LOGSTRING2( "Got service required \"%S\"\n", newService )
+                    CleanupStack::PushL( newService );
+                    iServicesRequired->AppendL( *newService );
+                    CleanupStack::PopAndDestroy( newService );                    
+                    }
+                else
+                    {
+                    iBadXML = ETrue;
+                    }
+                }            
+            }
+        // Unexpected tag            
+        else
+            {
+            LOGSTRING( "Error: unexpected XML tag found.\n" )
+            iBadXML = ETrue;
+            }
+        }        
+    }       
+
+// ---------------------------------------------------------------------------
+// From Xml::MContentHandler
+// OnEndElementL
+// ---------------------------------------------------------------------------
+//    
+void CDependencyParser::OnEndElementL( const Xml::RTagInfo& aElement, TInt aErrorCode )
+    {
+    const TDesC8& elementName8 = aElement.LocalName().DesC();
+    
+ #ifdef _DEBUG
+    HBufC* elementName16 = Convert8BitTo16BitBufferLC( elementName8 );
+    LOGSTRING3( "OnEndElementL %S %d\n", elementName16, aErrorCode )
+    CleanupStack::PopAndDestroy( elementName16 );
+ #endif
+    
+    // Check for end services required block
+    if ( ! elementName8.Compare( KServicesRequiredTag ) )
+        {
+        iParsingServicesRequired = EFalse;
+        }    
+        
+    // Check for end of root block
+    if ( ! elementName8.Compare( KRootXmlTag ) )        
+        {            
+        iInsideRootNode = EFalse;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From Xml::MContentHandler
+// OnContentL
+// ---------------------------------------------------------------------------
+//     
+void CDependencyParser::OnContentL( const TDesC8& /*aBytes*/, TInt aErrorCode )
+    {    
+    LOGSTRING2( "OnContentL %d\n", aErrorCode )
+    }    
+    
+// ---------------------------------------------------------------------------
+// From Xml::MContentHandler
+// OnError
+// ---------------------------------------------------------------------------
+//    
+void CDependencyParser::OnError( TInt aErrorCode )
+    {
+    LOGSTRING2( "OnError %d\n", aErrorCode )
+        
+    iParseStatus = aErrorCode;
+    }  
+    
+// ============================================================================
+// PRIVATE MEMBER FUNCTIONS( CDepdendencyParser )
+// ============================================================================    
+    
+// ---------------------------------------------------------------------------
+// Convert8BitTo16BitBufferLC
+// ---------------------------------------------------------------------------
+//  
+HBufC* CDependencyParser::Convert8BitTo16BitBufferLC( const TDesC8& Des ) const
+    {
+    HBufC* buf = HBufC::NewLC( Des.Length() );
+    buf->Des().Copy( Des );
+    return buf;
+    }
+
+// ---------------------------------------------------------------------------
+// ParseNumericAttribute
+// ---------------------------------------------------------------------------
+//  
+TBool CDependencyParser::ParseNumericAttribute( const RAttribute& aAttribute, 
+                                                TInt& aNumericAttribute )
+    {
+    TBool corrupt = EFalse;
+    const TDesC8& attrName = aAttribute.Attribute().LocalName().DesC();
+    const TDesC8& attrVal = aAttribute.Value().DesC();
+
+    // Attribute name should be "number"
+    if ( attrName.Compare( KNumberAttrTag ) )
+        {
+        LOGSTRING( "Error: expected number attribute.\n" )
+        corrupt = ETrue;
+        }
+    else
+        {
+        // Parse out order number
+        TLex8 lex( attrVal );
+        TInt rc=lex.Val( aNumericAttribute );
+        if ( rc != KErrNone )
+            {
+            LOGSTRING2( "Error: Could not parse attribute( rc=%d )", rc )
+            corrupt = ETrue;
+            }
+        }
+
+    return corrupt;
+    }
+
+// ---------------------------------------------------------------------------
+// ParseStringAttributeL
+// ---------------------------------------------------------------------------
+//
+TBool CDependencyParser::ParseStringAttributeL( const RAttribute& aAttribute, 
+                                                HBufC*& aStringAttribute )
+    {
+    TBool corrupt = EFalse;
+    const TDesC8& attrName = aAttribute.Attribute().LocalName().DesC();
+    const TDesC8& attrVal = aAttribute.Value().DesC();
+
+    // Attribute name should be "name"
+    if ( attrName.Compare( KNameAttrTag ) )
+        {
+        LOGSTRING( "Error: expected name attribute.\n" )
+        corrupt = ETrue;
+        }
+    else
+        {
+        aStringAttribute = Convert8BitTo16BitBufferLC( attrVal );
+        CleanupStack::Pop( aStringAttribute );
+        }
+
+    return corrupt;
+    }
+
+// ----------------------------------------------------------------------------
+// ParseToUid
+// ----------------------------------------------------------------------------
+//
+TInt CDependencyParser::ParseToUid( const TDesC8& aSource, TUid& aTarget )
+    {
+    // Remove required "0x" from the descriptor
+    _LIT8( KHexPrefix, "0x" );
+
+    TPtrC8 pSource( aSource );
+    const TInt prefixPosition = pSource.Find( KHexPrefix );
+    if ( prefixPosition == KErrNotFound )
+        {
+        return KErrCorrupt;            
+        }
+    else
+        {
+        pSource.Set( aSource.Mid( prefixPosition + KHexPrefix().Length() ) );
+        }            
+
+    // Parse to integer
+    TLex8 lex( pSource );
+    TUint integer = 0;
+
+    // Parse using TRadix::EHex as radix:
+    const TInt err = lex.Val( integer, EHex );
+    aTarget.iUid = integer;
+   
+    return err;
+    }
+    
+
+// ---------------------------------------------------------------------------
+// ValidateXmlTag
+// Validate Xml tag following a few standard rules that apply to
+// all XML tags in this format:
+// 1) Only one attribute is in each XML tag
+// 2) Only one of any given tag is allowed
+// ---------------------------------------------------------------------------
+//
+TBool CDependencyParser::ValidateXmlTag( const Xml::RAttributeArray& aAttributes,
+                                         TBool& aFoundTag )
+    {         
+    if ( aFoundTag )
+        {
+        LOGSTRING( "Error: multiple tags found.  Ignoring subsequent values.\n" )        
+        }
+    else 
+        {
+        aFoundTag = ETrue;
+        
+        if ( aAttributes.Count() == 1 )
+            {
+            return ETrue;
+            }
+        else if ( aAttributes.Count() > 1 )
+            {
+            LOGSTRING( "Error: Extra data after attribute tag.\n" )
+            iBadXML = ETrue;
+            }
+        else
+            {
+            LOGSTRING( "Error: No attributes found.\n" )
+            iBadXML = ETrue;
+            }
+        }                
+        
+    return EFalse;        
+    }    
+
+// ---------------------------------------------------------------------------
+// ResetL
+// ---------------------------------------------------------------------------
+//
+void CDependencyParser::ResetL()
+    {
+    delete iServiceProvided;
+    iServiceProvided = NULL;
+            
+    if ( iServicesRequired )
+        {
+        iServicesRequired->Reset();
+        }
+    delete iServicesRequired;
+    iServicesRequired = new( ELeave )CDesC16ArrayFlat( 1 );
+            
+    iOrderNumber = 0;
+    iParentUid = TUid::Uid(0);
+    
+    // Reset all flags
+    iParsingServicesRequired = EFalse;
+    iBadXML = EFalse;
+    iInsideRootNode = EFalse;
+    iFoundOrderNumber = EFalse;
+    iFoundServiceProvided = EFalse;
+    iFoundServicesRequired = EFalse;
+    iParseStatus = 0;
+    }
+        
+// ============================================================================
+// PRIVATE CONSTRUCTORS ( CDepdendencyParser )
+// ============================================================================           
+        
+// ---------------------------------------------------------------------------
+// CDependencyParser::CDependencyParser
+// ---------------------------------------------------------------------------
+//
+CDependencyParser::CDependencyParser()
+    {    //lint !e1927 variables not showing up in initializer list
+         // initialized in CBase constructor
+    }    //lint !e1744 member variables possibly not initialized
+    
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CDependencyParser::ConstructL()
+    {        
+    iParser = CParser::NewL( KParserMIMEType, *this );            
+    iServicesRequired = new( ELeave )CDesC16ArrayFlat( 1 );
+    }       
+    
+
+// ============================================================================
+// Unused pure virtual functions from Xml::MContentHandler
+// ============================================================================
+
+void CDependencyParser::OnStartDocumentL( const RDocumentParameters& /* aDocParam */, TInt /* aErrorCode */ )
+    {
+    }
+
+void CDependencyParser::OnEndDocumentL( TInt /* aErrorCode */ )
+    {
+    }
+
+void CDependencyParser::OnStartPrefixMappingL( const RString& /* aPrefix */, const RString& /* aUri */, TInt /* aErrorCode */ )
+    {
+    }
+
+void CDependencyParser::OnEndPrefixMappingL( const RString& /* aPrefix */, TInt /* aErrorCode */ )
+    {
+    }
+
+void CDependencyParser::OnIgnorableWhiteSpaceL( const TDesC8& /* aBytes */, TInt /* aErrorCode */ )
+    {
+    }
+
+void CDependencyParser::OnSkippedEntityL( const RString& /* aName */, TInt /* aErrorCode */ )
+    {
+    }
+
+void CDependencyParser::OnProcessingInstructionL( const TDesC8& /* aTarget */, const TDesC8& /* aData */, TInt /* aErrorCode */ )
+    {
+    }
+
+void CDependencyParser::OnExtensionL( const RString& /* aData */, TInt /* aToken */, TInt /* aErrorCode */ )
+    {
+    }
+
+TAny* CDependencyParser::GetExtendedInterface( const TInt32 /* aUid */ )
+    {
+    return 0;
+    }
+    
+    } // namespace DiagPluginPool
+
+// End of File
+