memspy/Engine/Source/Helpers/MemSpyEngineHelperECom.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:57:15 +0200
changeset 0 a03f92240627
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2009 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:
*
*/

#include <memspy/engine/memspyenginehelperecom.h>

// System includes
#include <charconv.h>

// User includes
#include <memspy/engine/memspyengine.h>
#include <memspy/engine/memspyengineutils.h>
#include <memspy/engine/memspyenginehelperfilesystem.h>

// Literal constants
_LIT8( KMemSpyEComXmlFileMimeType, "text/xml" );
_LIT8( KMemSpyXmlSpec_MasterSection, "memspy_ecom_sections" );
_LIT8( KMemSpyXmlSpec_ChildSectionCategory, "category" );
_LIT8( KMemSpyXmlSpec_ChildSectionCategory_Attribute_Name, "name" );
_LIT8( KMemSpyXmlSpec_ChildSectionInterface, "interface" );
_LIT8( KMemSpyXmlSpec_ChildSectionInterface_Name, "name" );
_LIT8( KMemSpyXmlSpec_ChildSectionInterface_Uid, "uid" );
_LIT8( KMemSpyXmlSpec_HexPrefix, "0x" );





CMemSpyEngineHelperECom::CMemSpyEngineHelperECom( CMemSpyEngine& aEngine )
:   iEngine( aEngine )
    {
    }

    
CMemSpyEngineHelperECom::~CMemSpyEngineHelperECom()
    {
    iCategories.ResetAndDestroy();
    iCategories.Close();
    //
    delete iParser;
    delete iConverter;
    //
    iEComSession.Close();
    REComSession::FinalClose();
    }


void CMemSpyEngineHelperECom::ConstructL()
    {
    TRAPD( err, ConstructInternalL() );
    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructL() - error: %d", err );
    err = err;
    }


void CMemSpyEngineHelperECom::ConstructInternalL()
    {
    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructInternalL() - START" );
    iEComSession = REComSession::OpenL();

    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructInternalL() - creating parser..." );
	iParser = CParser::NewL( KMemSpyEComXmlFileMimeType, *this );

    // We only convert from UTF-8 to UTF-16
    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructInternalL() - creating charconv object..." );
    iConverter = CCnvCharacterSetConverter::NewL();
    if  ( iConverter->PrepareToConvertToOrFromL( KCharacterSetIdentifierUtf8, iEngine.FsSession() ) == CCnvCharacterSetConverter::ENotAvailable )
	    {
		User::Leave(KErrNotFound);
		}

    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructInternalL() - reading xml..." );
    ConstructFromFileL();
    
    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructInternalL() - END" );
    }


void CMemSpyEngineHelperECom::ConstructFromFileL()
    {
    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructFromFileL() - START" );

    // Locate the source file
    TRAPD( err, 
        HBufC* fileName = FindEComXmlFileNameLC();
        ParseL( *fileName );
        CleanupStack::PopAndDestroy( fileName );
        );
    err = err;

    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructFromFileL() - parse error: %d", err );

    delete iConverter;
    iConverter = NULL;

    // Build captions
    const TInt categoryCount = iCategories.Count();
    for( TInt i=0; i<categoryCount; i++ )
        {
        //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructFromFileL() - building caption: %d", i );

        CMemSpyEngineEComCategory* cat = iCategories[ i ];
        cat->BuildCaptionL();
        }

    //RDebug::Printf( "CMemSpyEngineHelperECom::ConstructFromFileL() - END" );
    }


CMemSpyEngineHelperECom* CMemSpyEngineHelperECom::NewL( CMemSpyEngine& aEngine )
    {
    CMemSpyEngineHelperECom* self = new(ELeave) CMemSpyEngineHelperECom( aEngine );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }


REComSession& CMemSpyEngineHelperECom::EComSession()
    {
    return iEComSession;
    }


EXPORT_C CMemSpyEngineEComCategory& CMemSpyEngineHelperECom::At( TInt aIndex )
    {
    return *iCategories[ aIndex ];
    }


EXPORT_C TInt CMemSpyEngineHelperECom::IndexOf( const CMemSpyEngineEComCategory& aEntry )
    {
    const TInt index = iCategories.Find( &aEntry );
    return index;
    }


EXPORT_C TInt CMemSpyEngineHelperECom::MdcaCount() const
    {
    return iCategories.Count();
    }


EXPORT_C TPtrC CMemSpyEngineHelperECom::MdcaPoint( TInt aIndex ) const
    {
    CMemSpyEngineEComCategory* category = iCategories[ aIndex ];
    return category->Caption();
    }


HBufC* CMemSpyEngineHelperECom::FindEComXmlFileNameLC()
    {
    RFs& fsSession = iEngine.FsSession();
    //
    TFileName* fileName = new(ELeave) TFileName();
    CleanupStack::PushL( fileName );
    //
    fsSession.PrivatePath( *fileName );
    //
    TFindFile findFile( fsSession );
    User::LeaveIfError( findFile.FindByPath( KMemSpyEComInterfaceIdFileName, fileName ) );
    //
    HBufC* ret = findFile.File().AllocL();
    CleanupStack::PopAndDestroy( fileName );
    CleanupStack::PushL( ret );
    return ret;
    }


void CMemSpyEngineHelperECom::ConvertL( const TDesC8& aInput, TDes16& aOutput )
    {
    const TInt error = iConverter->ConvertToUnicode( aOutput, aInput, iCharconvConverterState );
    User::LeaveIfError( error );
    }


void CMemSpyEngineHelperECom::ParseL( const TDesC& aFileName )
    {
	Xml::ParseL( *iParser, iEngine.FsSession(), aFileName );
    //
    const TInt error = iParserErrorCode;
    //RDebug::Printf( "CMemSpyEngineHelperECom::ParseL() - iParserErrorCode: %d", iParserErrorCode );
    iParserErrorCode = KErrNone;
    //
	User::LeaveIfError( error );
    }


void CMemSpyEngineHelperECom::OnChildSectionCategoryL( const RAttributeArray& aAttributes )
    {
    TBuf<128> name;
    TBool gotName = EFalse;
    //
    const TInt count = aAttributes.Count();
	for( TInt i=0; i<count; i++ )
		{
		const TPtrC8 attrib( aAttributes[ i ].Attribute().LocalName().DesC() );
		const TPtrC8 value( aAttributes[ i ].Value().DesC() );
        //
		if  ( attrib.CompareF( KMemSpyXmlSpec_ChildSectionCategory_Attribute_Name ) == 0 )
			{
            if  ( gotName )
                {
                User::LeaveIfError( KErrCorrupt );
                }
            else
                {
                ConvertL( value, name );
                gotName = ETrue;
                }
			}
        }
    //
    if  ( gotName )
        {
        // Make a new category
        //RDebug::Print( _L("CMemSpyEngineHelperECom::OnChildSectionCategoryL() - creating category: %S"), &name );

        CMemSpyEngineEComCategory* category = CMemSpyEngineEComCategory::NewLC( *this, name );
        iCategories.AppendL( category );
        CleanupStack::Pop( category );

        //RDebug::Print( _L("CMemSpyEngineHelperECom::OnChildSectionCategoryL() - created category: %S"), &name );
        }
    else
        {
        User::Leave( KErrCorrupt );
        }
    }


void CMemSpyEngineHelperECom::OnChildSectionInterfaceL( const RAttributeArray& aAttributes )
    {
    TUid uid = KNullUid;
    TBuf<128> name;
    TBool gotName = EFalse;
    TBool gotUid = EFalse;
    //
    const TInt count = aAttributes.Count();
	for( TInt i=0; i<count; i++ )
		{
		const TPtrC8 attrib( aAttributes[ i ].Attribute().LocalName().DesC() );
		const TPtrC8 value( aAttributes[ i ].Value().DesC() );
        //
		if  ( attrib.CompareF( KMemSpyXmlSpec_ChildSectionInterface_Name ) == 0 )
			{
            if  ( gotName )
                {
                User::LeaveIfError( KErrCorrupt );
                }
            else
                {
                ConvertL( value, name );
                gotName = ETrue;
                }
			}
		else if ( attrib.CompareF( KMemSpyXmlSpec_ChildSectionInterface_Uid ) == 0 )
			{
            if  ( gotUid )
                {
                User::LeaveIfError( KErrCorrupt );
                }
            else
                {
                if  ( value.Length() >= 8 )
                    {
                    TRadix radix = EDecimal;
                    TPtrC8 pValue( value );
                    //
                    if  ( value.Length() == 10 && value.Left( 2 ) == KMemSpyXmlSpec_HexPrefix )
                        {
                        pValue.Set( value.Mid( 2 ) );
                        radix = EHex;
                        }
                    //
                    TUint32 uidVal = 0;
                    TLex8 lexer( pValue );
                    const TInt err = lexer.Val( uidVal, radix );
                    User::LeaveIfError( err );
                    uid.iUid = uidVal;
                    gotUid = ETrue;
                    }
                }
			}
        }
    //
    const TInt catCount = iCategories.Count();
    if  ( gotName && gotUid && catCount > 0 )
        {
        //RDebug::Print( _L("CMemSpyEngineHelperECom::OnChildSectionInterfaceL() - creating interface for %S [0x%08x]"), &name, uid.iUid );

        CMemSpyEngineEComCategory* category = iCategories[ catCount - 1 ];
        TRAPD( err, category->CreateInterfaceL( name, uid ) );
        err = err;
        //RDebug::Print( _L("CMemSpyEngineHelperECom::OnChildSectionInterfaceL() - error: %d, for %S [0x%08x]"), err, &name, uid.iUid );
        }
    else
        {
        User::Leave( KErrCorrupt );
        }
    }


void CMemSpyEngineHelperECom::OnStartDocumentL( const RDocumentParameters& /*aDocParam*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnEndDocumentL( TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnStartElementL( const RTagInfo& aElement, const RAttributeArray& aAttributes, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    //
	TInt err = KErrNone;
	const TPtrC8 name( aElement.LocalName().DesC() );
    //
    if  ( name.CompareF( KMemSpyXmlSpec_MasterSection ) == 0 )
		{
		iSeenMasterSection = ETrue;
		}
    else if ( iSeenMasterSection )
        {
        if  ( name.CompareF( KMemSpyXmlSpec_ChildSectionCategory ) == 0 )
            {
            OnChildSectionCategoryL( aAttributes );
            }
        else if ( name.CompareF( KMemSpyXmlSpec_ChildSectionInterface ) == 0 )
            {
            OnChildSectionInterfaceL( aAttributes );
            }
        }
    //
    User::LeaveIfError( err );
    }


void CMemSpyEngineHelperECom::OnEndElementL( const RTagInfo& /*aElement*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnContentL( const TDesC8& /*aBytes*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnStartPrefixMappingL( const RString& /*aPrefix*/, const RString& /*aUri*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnEndPrefixMappingL( const RString& /*aPrefix*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnSkippedEntityL( const RString& /*aName*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnProcessingInstructionL( const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyEngineHelperECom::OnError( TInt aErrorCode )
    {
    iParserErrorCode = aErrorCode;
    }


TAny* CMemSpyEngineHelperECom::GetExtendedInterface( const TInt32 /*aUid*/ )
    {
    return NULL;
    }





































CMemSpyEngineEComCategory::CMemSpyEngineEComCategory( CMemSpyEngineHelperECom& aHelper )
:   iHelper( aHelper )
    {
    }

    
CMemSpyEngineEComCategory::~CMemSpyEngineEComCategory()
    {
    delete iCaption;
    delete iName;
    iInterfaces.ResetAndDestroy();
    iInterfaces.Close();
    }


void CMemSpyEngineEComCategory::ConstructL( const TDesC& aName )
    {
    iName = aName.AllocL();
    iCaption = aName.AllocL(); // Replace later on
    }


CMemSpyEngineEComCategory* CMemSpyEngineEComCategory::NewLC( CMemSpyEngineHelperECom& aHelper, const TDesC& aName )
    {
    CMemSpyEngineEComCategory* self = new(ELeave) CMemSpyEngineEComCategory( aHelper );
    CleanupStack::PushL( self );
    self->ConstructL( aName );
    return self;
    }


EXPORT_C CMemSpyEngineEComInterface& CMemSpyEngineEComCategory::At( TInt aIndex )
    {
    return *iInterfaces[ aIndex ];
    }


EXPORT_C TInt CMemSpyEngineEComCategory::IndexOf( const CMemSpyEngineEComInterface& aEntry )
    {
    const TInt index = iInterfaces.Find( &aEntry );
    return index;
    }


EXPORT_C TInt CMemSpyEngineEComCategory::MdcaCount() const
    {
    return iInterfaces.Count();
    }


EXPORT_C TPtrC CMemSpyEngineEComCategory::MdcaPoint( TInt aIndex ) const
    {
    CMemSpyEngineEComInterface* iface = iInterfaces[ aIndex ];
    return iface->Caption();
    }


void CMemSpyEngineEComCategory::CreateInterfaceL( const TDesC& aName, TUid aUid )
    {
    CMemSpyEngineEComInterface* iface = CMemSpyEngineEComInterface::NewLC( *this, aName, aUid );
    iInterfaces.AppendL( iface );
    CleanupStack::Pop( iface );
    }


void CMemSpyEngineEComCategory::BuildCaptionL()
    {
    delete iCaption; 
    iCaption = NULL;

    _LIT( KCaptionFormat, "\t%S\t\t%d interface" );
    iCaption = HBufC::NewL( 256 );
    TPtr pCaption( iCaption->Des() );
    pCaption.Format( KCaptionFormat, iName, iInterfaces.Count() );
    if  ( iInterfaces.Count() > 1 )
        {
        pCaption.Append( 's' );
        }
    }












CMemSpyEngineEComInterface::CMemSpyEngineEComInterface( CMemSpyEngineEComCategory& aCategory, TUid aUid )
:   iUid( aUid ), iCategory( aCategory )
    {
    }

    
CMemSpyEngineEComInterface::~CMemSpyEngineEComInterface()
    {
    delete iCaption;
    delete iName;
    iImplementations.ResetAndDestroy();
    iImplementations.Close();
    }


void CMemSpyEngineEComInterface::ConstructL( const TDesC& aName )
    {
    iName = aName.AllocL();

    // Get implementation information for this interface...
    RImplInfoPtrArray infoArray;
    CleanupResetAndDestroyPushL( infoArray );
    REComSession::ListImplementationsL( iUid, infoArray );

    // Make implementation objects for each impl that exists.
    const TInt count = infoArray.Count();
    for( TInt i=count-1; i>=0; i-- )
        {
        CImplementationInformation* info = infoArray[ i ];

        // Get info
        CMemSpyEngineEComImplementation* impl = CMemSpyEngineEComImplementation::NewLC( *this, info );

        // Now owned by impl
        infoArray.Remove( i );

        // Add to container
        iImplementations.AppendL( impl );
        CleanupStack::Pop( impl );
        }

    // Tidy up
    CleanupStack::PopAndDestroy( &infoArray );

    // Build caption
    _LIT( KCaptionFormat, "\t%S\t\t[0x%08x] [%d impl]" );
    iCaption = HBufC::NewL( 256 );
    TPtr pCaption( iCaption->Des() );
    pCaption.Format( KCaptionFormat, iName, iUid.iUid, count );
    }


CMemSpyEngineEComInterface* CMemSpyEngineEComInterface::NewLC( CMemSpyEngineEComCategory& aCategory, const TDesC& aName, TUid aUid )
    {
    CMemSpyEngineEComInterface* self = new(ELeave) CMemSpyEngineEComInterface( aCategory, aUid );
    CleanupStack::PushL( self );
    self->ConstructL( aName );
    return self;
    }


EXPORT_C CMemSpyEngineEComImplementation& CMemSpyEngineEComInterface::At( TInt aIndex )
    {
    return *iImplementations[ aIndex ];
    }


EXPORT_C TInt CMemSpyEngineEComInterface::IndexOf( const CMemSpyEngineEComImplementation& aEntry )
    {
    const TInt index = iImplementations.Find( &aEntry );
    return index;
    }


EXPORT_C TInt CMemSpyEngineEComInterface::MdcaCount() const
    {
    return iImplementations.Count();
    }


EXPORT_C TPtrC CMemSpyEngineEComInterface::MdcaPoint( TInt aIndex ) const
    {
    CMemSpyEngineEComImplementation* impl = iImplementations[ aIndex ];
    return impl->Caption();
    }





















CMemSpyEngineEComImplementation::CMemSpyEngineEComImplementation( CMemSpyEngineEComInterface& aInterface )
:   iInterface( aInterface )
    {
    }

    
CMemSpyEngineEComImplementation::~CMemSpyEngineEComImplementation()
    {
    delete iCaption;
    delete iName;
    delete iInfoText;
    delete iInfo;
    }


void CMemSpyEngineEComImplementation::ConstructL( CImplementationInformation* aInfo )
    {
    iInfoText = new(ELeave) CDesCArrayFlat( 10 );
    TBuf< 256 > temp;

    // Make items.
    if  ( aInfo->DisplayName().Length() )
        {
        _LIT( KNameFormat, "0x%08x - %S" );
        temp.Format( KNameFormat, aInfo->ImplementationUid().iUid, &aInfo->DisplayName() );
        }
    else
        {
        _LIT( KNameFormat, "0x%08x" );
        temp.Format( KNameFormat, aInfo->ImplementationUid().iUid );
        }
    iName = temp.AllocL();

    _LIT( KItem1, "\tImpl. Uid\t\t0x%08x" );
    temp.Format( KItem1, aInfo->ImplementationUid().iUid );
    iInfoText->AppendL( temp );

    if  ( aInfo->DisplayName().Length() )
        {
        _LIT( KItem2, "\tDisplay Name\t\t%S" );
        temp.Format( KItem2, &aInfo->DisplayName() );
        }
    else
        {
        _LIT( KItem2, "\tDisplay Name\t\t[Undefined]" );
        temp.Copy( KItem2 );
        }
    iInfoText->AppendL( temp );

    _LIT( KItem3, "\tVersion\t\t%d" );
    temp.Format( KItem3, aInfo->Version() );
    iInfoText->AppendL( temp );

    HBufC* opaqueData = CopyAndCropLC( aInfo->OpaqueData() );
    if  ( opaqueData->Length() )
        {
        _LIT( KItem4, "\tOpaque Data\t\t%S" );
        temp.Format( KItem4, opaqueData );
        }
    else
        {
        _LIT( KItem4, "\tOpaque Data\t\t[Undefined]" );
        temp.Copy( KItem4 );
        }
    iInfoText->AppendL( temp );
    CleanupStack::PopAndDestroy( opaqueData );

    HBufC* dataType = CopyAndCropLC( aInfo->DataType() );
    if  ( opaqueData->Length() )
        {
        _LIT( KItem5, "\tData Type\t\t%S" );
        temp.Format( KItem5, dataType );
        }
    else
        {
        _LIT( KItem5, "\tData Type\t\t[Undefined]" );
        temp.Copy( KItem5 );
        }
    iInfoText->AppendL( temp );
    CleanupStack::PopAndDestroy( dataType );

    _LIT( KItem6, "\tDrive\t\t%S" );
    TBuf< 10 > drive;
    const TDriveNumber driveNumber = static_cast< TDriveNumber >( static_cast< TInt >( aInfo->Drive() ) );
    CMemSpyEngineHelperFileSystem::GetDriveNumberText( driveNumber, drive );
    temp.Format( KItem6, &drive );
    iInfoText->AppendL( temp );

    if  ( aInfo->Disabled() )
        {
        iInfoText->AppendL( _L("\tIs Disabled\t\tYes") );
        }
    else
        {
        iInfoText->AppendL( _L("\tIs Disabled\t\tNo") );
        }

    if  ( aInfo->RomOnly() )
        {
        iInfoText->AppendL( _L("\tROM-Only\t\tYes") );
        }
    else
        {
        iInfoText->AppendL( _L("\tROM-Only\t\tNo") );
        }
    
    if  ( aInfo->RomBased() )
        {
        iInfoText->AppendL( _L("\tROM-Based\t\tYes") );
        }
    else
        {
        iInfoText->AppendL( _L("\tROM-Based\t\tNo") );
        }
    
    // Make caption
    if  ( aInfo->DisplayName().Length() )
        {
        _LIT( KCaptionFormat, "\t0x%08x\t\t%S" );
        temp.Format( KCaptionFormat, aInfo->ImplementationUid().iUid, &aInfo->DisplayName() );
        }
    else
        {
        _LIT( KCaptionFormat, "\t0x%08x\t\t[Name Undefined]" );
        temp.Format( KCaptionFormat, aInfo->ImplementationUid().iUid );
        }
    iCaption = temp.AllocL();

    // Must do this last
    iInfo = aInfo;
    }


CMemSpyEngineEComImplementation* CMemSpyEngineEComImplementation::NewLC( CMemSpyEngineEComInterface& aInterface, CImplementationInformation* aInfo )
    {
    CMemSpyEngineEComImplementation* self = new(ELeave) CMemSpyEngineEComImplementation( aInterface );
    CleanupStack::PushL( self );
    self->ConstructL( aInfo );
    return self;
    }


HBufC* CMemSpyEngineEComImplementation::CopyAndCropLC( const TDesC8& aText )
    {
    const TInt KMaxEComDataLength = 200; // Any longer and we'll crop it...
    //
    HBufC* data = HBufC::NewLC( aText.Length() );
    data->Des().Copy( aText );
    //
    if  ( data->Length() > KMaxEComDataLength )
        {
        data->Des().SetLength( KMaxEComDataLength );
        }
    //
    return data;
    }


EXPORT_C TInt CMemSpyEngineEComImplementation::MdcaCount() const
    {
    return iInfoText->MdcaCount();
    }


EXPORT_C TPtrC CMemSpyEngineEComImplementation::MdcaPoint( TInt aIndex ) const
    {
    return iInfoText->MdcaPoint( aIndex );
    }