--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filemanager/GFLM/src/CGflmFileRecognizer.cpp Mon Jan 18 20:09:41 2010 +0200
@@ -0,0 +1,436 @@
+/*
+* Copyright (c) 2002-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: Recogniser wrapper
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "CGflmFileRecognizer.h"
+#include "CGflmDriveResolver.h"
+#include "CGflmDriveItem.h"
+#include "GflmUtils.h"
+#include "GFLMConsts.h"
+#include <e32svr.h>
+#include <barsread.h>
+#include <GflmFileExtensionMimeTypes.rsg>
+#include <data_caging_path_literals.hrh>
+
+
+// CONSTANTS
+_LIT( KFileExtensionResourceFile, "gflmfileextensionmimetypes.rsc" );
+const TInt KMimeTypeGranularity = 10;
+const TUint KPerCentToDrop = 30;
+const TUint KHundredPerCent = 100;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CGflmFileRecognizer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CGflmFileRecognizer(
+ CGflmDriveResolver* aDriveResolver,
+ RFs& aFs ) :
+ iCache( _FOFF( CPathTypePair, iLink ) ),
+ iDriveResolver( aDriveResolver ),
+ iFs( aFs )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::ConstructL( TInt aMemoryConsumption )
+ {
+ User::LeaveIfError( iApaSession.Connect() );
+ iMimeTypes = new( ELeave ) CDesCArraySeg( KMimeTypeGranularity );
+ iCacheMaxMemoryUsage = aMemoryConsumption;
+
+ // Get resource drive from dll location
+ TFileName dllFileName;
+ Dll::FileName( dllFileName );
+ TParsePtrC dllParse( dllFileName );
+
+ TFileName resFileName;
+ resFileName.Copy( dllParse.Drive() );
+ resFileName.Append( KDC_RESOURCE_FILES_DIR );
+ GflmUtils::EnsureFinalBackslash( resFileName );
+ resFileName.Append( KFileExtensionResourceFile );
+
+ RResourceFile resFile;
+ resFile.OpenL( iFs, resFileName );
+ CleanupClosePushL( resFile );
+ resFile.ConfirmSignatureL();
+
+ ConstructExtMimePairsL( resFile, R_EXT_MIME_PAIRS, iExtMimePairs );
+ ConstructExtMimePairsL(
+ resFile, R_REMOTE_EXT_MIME_PAIRS, iRemoteExtMimePairs );
+
+ CleanupStack::PopAndDestroy( &resFile );
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::ConstructExtMimePairsL
+//
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::ConstructExtMimePairsL(
+ RResourceFile& aResFile,
+ TInt aResId,
+ RPointerArray< CExtMimePair >& aPairs )
+ {
+ // read the pairs
+ HBufC8* resData = aResFile.AllocReadLC( aResId );
+ TResourceReader reader;
+ reader.SetBuffer( resData );
+ TInt count( reader.ReadInt16() );
+ aPairs.ReserveL( count );
+ for ( TInt i( 0 ); i < count; i++ )
+ {
+ TPtrC ext( reader.ReadTPtrC() );
+ TPtrC mime( reader.ReadTPtrC() );
+ CExtMimePair* pair = new (ELeave) CExtMimePair();
+ CleanupStack::PushL( pair );
+ pair->iExt = ext.AllocL();
+ pair->iMime = mime.AllocL();
+ aPairs.AppendL( pair );
+ CleanupStack::Pop( pair );
+ }
+ CleanupStack::PopAndDestroy( resData );
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::FindMimeFromExt
+//
+// -----------------------------------------------------------------------------
+//
+TPtrC CGflmFileRecognizer::FindMimeFromExt(
+ const TDesC& aExt,
+ RPointerArray< CExtMimePair >& aPairs )
+ {
+ TInt count( aPairs.Count() );
+
+ for( TInt i( 0 ); i < count; i++)
+ {
+ CExtMimePair* pair = aPairs[ i ];
+ if( !aExt.CompareF( *pair->iExt ) )
+ {
+ return TPtrC( *pair->iMime );
+ }
+ }
+ return TPtrC( KNullDesC );
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer* CGflmFileRecognizer::NewL(
+ RFs& aFs,
+ TInt aMemoryConsumption,
+ CGflmDriveResolver* aDriveResolver )
+ {
+ CGflmFileRecognizer* self =
+ new( ELeave ) CGflmFileRecognizer( aDriveResolver, aFs );
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aMemoryConsumption );
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::~CGflmFileRecognizer
+//
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::~CGflmFileRecognizer()
+ {
+ iApaSession.Close();
+
+ FlushCache();
+
+ delete iMimeTypes;
+
+ iExtMimePairs.ResetAndDestroy();
+ iExtMimePairs.Close();
+
+ iRemoteExtMimePairs.ResetAndDestroy();
+ iRemoteExtMimePairs.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::RecognizeL( const TDesC& aFilename )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC CGflmFileRecognizer::RecognizeL( const TDesC& aFilename )
+ {
+ TPtrC mimeType;
+ TRAPD( err, mimeType.Set( DoRecognizeL( aFilename ) ) );
+ if ( err == KErrNoMemory )
+ {
+ FlushCache();
+ return DoRecognizeL( aFilename );
+ }
+ User::LeaveIfError( err );
+ return mimeType;
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename )
+ {
+ // Search the cache for a hit
+ TInt cropPoint( aFilename.LocateReverse( KGFLMDot()[ 0 ] ) );
+ TBool isRemoteDrive( EFalse );
+
+ if ( iDriveResolver && iDriveResolver->IsRemoteDrive( aFilename ) )
+ {
+ isRemoteDrive = ETrue;
+ }
+
+ if( cropPoint != KErrNotFound )
+ {
+ TPtrC ext( aFilename.Mid( cropPoint ) );
+ TPtrC mime( FindMimeFromExt( ext, iExtMimePairs ) );
+ if ( mime.Length() )
+ {
+ return mime;
+ }
+
+ // Use remote drive specific extension mime pairs and skip
+ // content recognition because it is so slow for remote drives.
+ // Mime types are resolved from extension by remote storage framework
+ // anyway.
+ if ( isRemoteDrive)
+ {
+ return FindMimeFromExt( ext, iRemoteExtMimePairs );
+ }
+ }
+ else if ( isRemoteDrive)
+ {
+ // Skip content recognition for remote drives because it is so slow
+ return TPtrC( KNullDesC );
+ }
+
+ TDblQueIter< CPathTypePair > pairIt( iCache );
+ pairIt.SetToFirst();
+ CPathTypePair* pair = NULL;
+ while ( ( pair = pairIt++ ) != NULL )
+ {
+ TPtrC ptr( *( pair->iFilename ) );
+ if( ptr.Length() == aFilename.Length() &&
+ !aFilename.CompareF( ptr ) )
+ {
+ // Cache hit
+ // Move item to the first position if not already.
+ // When clearing cache, oldest items can be dropped easily.
+ pair->iLink.Deque();
+ iCache.AddFirst( *pair );
+
+ if ( pair->iTypeIndex != KErrNotFound )
+ {
+ return iMimeTypes->MdcaPoint( pair->iTypeIndex );
+ }
+ return TPtrC( KNullDesC );
+ }
+ }
+
+ // Cache miss
+ TUid uid( KNullUid );
+ TDataType datatype;
+
+ TIMESTAMP( "GFLM AppForDocument started: " )
+
+ // Acquire the mime-type of the file
+ TInt err( iApaSession.AppForDocument( aFilename, uid, datatype ) );
+
+ TIMESTAMP( "GFLM AppForDocument ended: " )
+
+ if ( err != KErrNone )
+ {
+ // If recognition returns error, handle as unrecognized file
+ ERROR_LOG1(
+ "CGflmFileRecognizer::DoRecognizeL-AppForDocument=%d",
+ err )
+ return TPtrC( KNullDesC );
+ }
+
+ CPathTypePair* newPair = CPathTypePair::NewLC( aFilename );
+ TPtrC mimeType( datatype.Des() );
+
+ INFO_LOG2( "GFLM AppForDocument:file=%S,mime=%S", &aFilename, &mimeType )
+
+ // Run through the mime-type list to find the correct index
+ if ( mimeType.Length() )
+ {
+ TBool isMimeFound( EFalse );
+ TInt mimeCount( iMimeTypes->MdcaCount() );
+ for ( TInt j( 0 ); j < mimeCount; j++ )
+ {
+ if( !mimeType.CompareF( iMimeTypes->MdcaPoint( j ) ) )
+ {
+ newPair->iTypeIndex = j;
+ isMimeFound = ETrue;
+ break;
+ }
+ }
+ // Add mime type to list if not already added
+ if ( !isMimeFound )
+ {
+ iMimeTypes->AppendL( mimeType );
+ newPair->iTypeIndex = mimeCount;
+ }
+ }
+
+ // Cleanup cache and add new pair
+ CleanupStack::Pop( newPair );
+ CleanupCache();
+ iCacheMemoryUsage += newPair->Size();
+ iCache.AddFirst( *newPair );
+
+ if ( newPair->iTypeIndex != KErrNotFound )
+ {
+ return iMimeTypes->MdcaPoint( newPair->iTypeIndex );
+ }
+ return TPtrC( KNullDesC );
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::FlushCache( )
+//
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::FlushCache()
+ {
+ TDblQueIter< CPathTypePair > pairIt( iCache );
+ pairIt.SetToFirst();
+ CPathTypePair* pair = NULL;
+ while ( ( pair = pairIt++ ) != NULL )
+ {
+ pair->iLink.Deque();
+ delete pair;
+ }
+ iCacheMemoryUsage = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CleanupCache( )
+//
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::CleanupCache( )
+ {
+ if( iCacheMemoryUsage > iCacheMaxMemoryUsage )
+ {
+ TInt dropThreshold = ( TInt ) ( ( ( ( TUint ) iCacheMaxMemoryUsage ) *
+ KPerCentToDrop ) / KHundredPerCent );
+ TInt droppedSize( 0 );
+
+ TDblQueIter< CPathTypePair > pairIt( iCache );
+ pairIt.SetToLast();
+ CPathTypePair* pair = NULL;
+ while ( ( pair = pairIt-- ) != NULL )
+ {
+ droppedSize += pair->Size();
+ pair->iLink.Deque();
+ delete pair;
+ if ( droppedSize >= dropThreshold )
+ {
+ break;
+ }
+ }
+ iCacheMemoryUsage -= droppedSize;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::NewLC()
+//
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CPathTypePair*
+ CGflmFileRecognizer::CPathTypePair::NewLC( const TDesC& aFilename )
+ {
+ CPathTypePair* self = new ( ELeave ) CPathTypePair();
+ CleanupStack::PushL( self );
+ self->ConstructL( aFilename );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::ConstructL()
+//
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::CPathTypePair::ConstructL( const TDesC& aFilename )
+ {
+ iFilename = aFilename.AllocL();
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::CPathTypePair()
+//
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CPathTypePair::CPathTypePair() :
+ iTypeIndex( KErrNotFound )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::~CPathTypePair()
+//
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CPathTypePair::~CPathTypePair()
+ {
+ delete iFilename;
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::Size()
+//
+// -----------------------------------------------------------------------------
+//
+TInt CGflmFileRecognizer::CPathTypePair::Size() const
+ {
+ return ( sizeof( TInt ) + iFilename->Size() + sizeof( TDblQueLink ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CExtMimePair::~CExtMimePair()
+//
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CExtMimePair::~CExtMimePair()
+ {
+ delete iExt;
+ delete iMime;
+ }
+
+// End of File