imaging/imagingfws/resolver/ImageConversionResolver.cpp
changeset 0 5752a19fdefe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imaging/imagingfws/resolver/ImageConversionResolver.cpp	Wed Aug 25 12:29:52 2010 +0300
@@ -0,0 +1,586 @@
+// Copyright (c) 1997-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 <ecom/ecom.h>
+#include <ecom/ecomerrorcodes.h>
+#include <ecom/implementationinformation.h>
+
+#include "ImageConversionResolver.h"
+#include "ImageConvResolvrUtils.h"
+
+_LIT(KIclResolverPanicCategory, "ImageConversionResolver");
+
+//Current version of plugin framework.
+//Plugin will be ignored if the version from opaque data doesn't
+//match the current framework version.
+//const TInt KPluginFrameworkVersion = 0; 
+
+GLDEF_C void Panic(TInt aReason)
+	{
+	User::Panic(KIclResolverPanicCategory, aReason);
+	}
+
+/** 
+ * Constructs and initialises a new instance of CImageConversionResolver.
+ *
+ * @param     "MPublicRegistry& aRegistry"
+ *            A reference to the registry on which it will operate
+ * @return    "CImageConversionResolver*"
+ *            A pointer to the newly constructed resolver
+ */
+CImageConversionResolver* CImageConversionResolver::NewL(MPublicRegistry& aRegistry)
+	{
+	return new(ELeave) CImageConversionResolver(aRegistry);
+	}
+
+/** 
+ *
+ * Default destructor
+ *
+ */
+CImageConversionResolver::~CImageConversionResolver()
+	{
+	}
+
+/** 
+ *
+ * Default constructor
+ *
+ * @param     "MPublicRegistry& aRegistry"
+ *            A reference to the registry on which it will operate
+ */
+CImageConversionResolver::CImageConversionResolver(MPublicRegistry& aRegistry)
+	: CResolver(aRegistry)
+	{
+	}
+
+/** 
+ *
+ * Request that the resolver identify the most appropriate interface
+ * implementation.
+ *
+ * @param     "TUid aInterfaceUid"
+ *            The Uid of the interface you want to match against
+ * @param     "const TEComResolverParams& aAdditionalParameters"
+ *            A passed in reference to the parameters on which to match
+ * @return    "TUid"
+ *            The implementation Uid of the single best match found
+ */
+TUid CImageConversionResolver::IdentifyImplementationL(TUid aInterfaceUid, const TEComResolverParams& aAdditionalParameters) const
+	{
+	RImplInfoArray& implementationsInfo = iRegistry.ListImplementationsL(aInterfaceUid);
+	TUid found = KNullUid;
+	if (implementationsInfo.Count())
+		found = ResolveL(implementationsInfo, aAdditionalParameters);
+
+	return found;
+	}
+
+/** 
+ *
+ * Called by IdentifyImplementationL to select an implementation from the
+ * supplied implementation uid, ignoring any implementations that have their 
+ * Disabled flag set or are not of the current framework version.
+ * The image type and sub type is verified to ensure the implementation is of
+ * expected type.
+ * 
+ * @param     "const RImplInfoArray& aImplementationsInfo"
+ *            The list of plugins you want to match against
+ * @param     "const TEComResolverParams& aAdditionalParameters"
+ *            A passed in reference to the parameters on which to match
+ * @return    "TUid"
+ *            The implementation Uid of plugin
+ */
+TUid CImageConversionResolver::ResolveL(const RImplInfoArray& aImplementationsInfo, const TEComResolverParams& aAdditionalParameters) const
+	{
+	// Retrieve the match data from the descriptor
+	CCustomMatchData* customMatch = CCustomMatchData::NewLC(aAdditionalParameters.DataType());
+
+	TResolverMatchType matchType = customMatch->MatchType();
+	TUint requiredExtensions = customMatch->ExtensionOptions();
+	TUint requiredOptions = customMatch->Options();
+	TUid baseType = customMatch->BaseType();
+	TUid subType = customMatch->SubType();
+	TUid implementationUid = customMatch->ImplementationType();
+
+	RUidDataArray requiredOptionsUids;
+	if (requiredOptions) 
+		{
+		CleanupClosePushL(requiredOptionsUids);
+		customMatch->GetOptionsUidsL(requiredOptionsUids);
+		}
+
+	// Select plugin on implementation uid
+	if((matchType != EMatchUids) || (implementationUid == KNullUid))
+		User::Leave(KErrArgument);
+
+	TUid bestMatch = KNullUid;
+	TInt version = 0;
+	TBool requiredOptionsFound = EFalse;
+
+	// Loop through the implementations searching for the implementation uid
+	const TInt count = aImplementationsInfo.Count();
+	for(TInt index = 0; index < count; index++)
+		{
+		const CImplementationInformation& impData = *aImplementationsInfo[index];
+		COpaqueDataParse* parse = NULL;
+		TRAPD(error, parse = COpaqueDataParse::NewL(impData.OpaqueData()));
+		if (error!=KErrNone)
+			{
+			if (error==KErrNotSupported)
+				{
+				// means that the resource entry was not valid
+				continue;
+				}
+			else
+				User::Leave(error);
+			}
+
+		CleanupStack::PushL(parse);
+		
+		// we can assume the version is valid as it is checked in 
+		// COpaqueDataParse::ConstructL() which leaves if not valid
+		ASSERT(parse->Version() <= KIclPluginFrameworkVersionMax);
+
+		if (!impData.Disabled())
+			{
+			if (implementationUid == impData.ImplementationUid())
+				{ // Got a match
+				// Moved here to optimize iteration through implementations
+				// Check if extension options are required.
+				if (requiredExtensions)
+					{
+					if (!parse->SupportsExtensionsL(requiredExtensions))
+						{
+						CleanupStack::PopAndDestroy(parse);
+						continue;
+						}
+					}
+
+				if ((baseType == parse->ImageTypeUid()) && (subType == parse->ImageSubTypeUid()))
+					{// ImageType and SubType match
+					if (requiredOptions) 
+						{
+						parse->EnsureBinaryPropertiesReadL();
+						if(parse->CheckOptionsUids(requiredOptionsUids))
+							{
+							if (!requiredOptionsFound) 
+								{
+								bestMatch = impData.ImplementationUid();
+								version = impData.Version();
+								requiredOptionsFound = ETrue;
+								CleanupStack::PopAndDestroy(parse);
+								continue;
+								}
+							}
+						else 
+							{
+							if (requiredOptionsFound)
+								{
+								CleanupStack::PopAndDestroy(parse);
+								continue;
+								}
+							}
+						}
+										
+					if (version < impData.Version())
+						{ // Higher version match
+						bestMatch = impData.ImplementationUid();
+						version = impData.Version();
+						}
+					}
+				}
+			}
+		CleanupStack::PopAndDestroy(parse);
+		}
+
+	if (requiredOptions) 
+		{
+		CleanupStack::PopAndDestroy();//requiredOptionsUids
+		}
+	CleanupStack::PopAndDestroy(customMatch);
+
+	return bestMatch;
+	}
+
+/* 
+ *
+ * List all the implementations which satisfy the specified interface, ignoring 
+ * any implementations that have their Disabled flag set or are not of the 
+ * current framework version.
+ *
+ * The list is sorted:
+ * 1) For EMatchString in desending order of number of bytes matched and version number.
+ * 2) For EMatchMIMEType in asending order of the MIME position that matched and
+ *    desending version number.
+ * 3) All others - desending version numbers.
+ *
+ * @param     "TUid aInterfaceUid"
+ *            The Uid of the interface you want to match against
+ * @param     "const TEComResolverParams& aAdditionalParameters"
+ *            A passed in reference to the parameters on which to match
+ * @return    "RImplInfoArray*"
+ *            The list of matches found
+ */
+ RImplInfoArray* CImageConversionResolver::ListAllL(TUid aInterfaceUid, const TEComResolverParams& aAdditionalParameters) const
+	{
+	// Retrieve the match data from the descriptor
+	CCustomMatchData* customMatch = CCustomMatchData::NewLC(aAdditionalParameters.DataType());
+
+	TResolverMatchType matchType = customMatch->MatchType();
+	TUint requiredExtensions = customMatch->ExtensionOptions();
+	TUint requiredOptions = customMatch->Options();
+	TUid baseType = customMatch->BaseType();
+	TUid subType = customMatch->SubType();
+	TUid implementationUid = customMatch->ImplementationType();
+	HBufC8* matchString = customMatch->MatchString().AllocLC();
+	HBufC* fileSuffix = customMatch->FileSuffix().AllocLC();
+	
+	RUidDataArray requiredUids;
+	CleanupClosePushL(requiredUids);
+	customMatch->GetMatchReqUidsL(requiredUids);
+	
+	RUidDataArray requiredOptionsUids;
+	CleanupClosePushL(requiredOptionsUids);
+	customMatch->GetOptionsUidsL(requiredOptionsUids);
+		
+	// Use the member var to create the array so that we get proper cleanup behaviour
+	RImplInfoArray& fullList = iRegistry.ListImplementationsL(aInterfaceUid);
+
+	RArray<TSortImplInfo> sortList;
+	CleanupClosePushL(sortList);
+
+	TInt matchLevel = 0;
+	TInt optionsMatchLevel = 0;
+
+	// Loop through the implementations matching on appropriate info
+	const TInt count = fullList.Count();
+	TInt index;
+
+	for(index = 0; index < count; index++)
+		{
+		const CImplementationInformation& impData = *(fullList[index]);
+		COpaqueDataParse* parse = NULL;
+		TRAPD(error, parse = COpaqueDataParse::NewL(impData.OpaqueData()));
+		if (error!=KErrNone)
+			{
+			if (error==KErrNotSupported)
+				{
+				// means that the resource entry was not valid
+				continue;
+				}
+			else
+				User::Leave(error);
+			}
+
+		CleanupStack::PushL(parse);
+		
+		// we can assume the version is valid as it is checked in 
+		// COpaqueDataParse::ConstructL() which leaves if not valid
+		ASSERT(parse->Version() <= KIclPluginFrameworkVersionMax);
+		
+		if (!impData.Disabled())
+			{
+			
+			TBool matchFound = EFalse;
+			switch(matchType)
+				{
+				case EListImageTypes:
+					{
+					if (baseType == KNullUid)
+						{ // Looking for base image types
+						if (parse->ImageSubTypeUid() == KNullUid)
+							matchFound = ETrue;
+						}
+					else
+						{ // Looking for sub-types of a particular base image type
+						if ((baseType == parse->ImageTypeUid()) && (parse->ImageSubTypeUid() != KNullUid))
+							matchFound = ETrue;
+						}
+					break;
+					}
+
+				case EListFileTypes:
+					{ // Looking for entries with file extensions and/or MIME types
+					if(!parse->OnlyUidsAvail() && !parse->IsSubCodec())
+						matchFound = ETrue;
+					break;
+					}
+
+				case EMatchMIMEType:
+					{
+					if(!parse->OnlyUidsAvail() && !parse->IsSubCodec())
+						{ //If codec has no MIME types ignore it
+						parse->EnsureMIMETypesReadL();
+						const TInt numMimeTypes = parse->MIMETypesCount();
+						for (TInt index2 = 0; index2 < numMimeTypes; index2++)
+							{
+							const TDesC8& mimeType = parse->MIMEType(index2);
+							if (COpaqueDataParse::CompareMIMETypes(*matchString, mimeType))
+								{
+								matchFound = ETrue;
+								matchLevel = index2;
+								break;
+								}
+							}
+						}
+
+					break;
+					}
+
+				case EMatchString:
+					{ // Match the match strings
+					if (CImageConversionResolverUtils::Match(*matchString, impData.DataType(), matchLevel))
+						matchFound = ETrue;
+					break;
+					}
+
+				case EMatchUids:
+					{ // match on UIDs
+					if (implementationUid != KNullUid)
+						{// We're matching on codec implementation uid
+						if (implementationUid == impData.ImplementationUid())
+							{
+							matchFound = ETrue;
+							}
+						else
+							{
+							matchFound = (implementationUid == parse->PluginClassUid());
+							}
+						}
+					else
+						{ // We're matching on image type (and sub-type)
+						if (parse->CompareUids(baseType, subType))
+							matchFound = ETrue;
+						}
+					break;
+					}
+
+				case EMatchFileSuffix:
+					{
+					if(!parse->OnlyUidsAvail() && parse->IsOpenAgainstSuffix())
+						{ //If codec has file extensions and allow matching on them
+						parse->EnsureExtnsReadL();
+						const TInt numExtns = parse->ExtnsCount();
+						for (TInt index2 = 0; index2 < numExtns; index2++)
+							{
+							const TDesC8& extn = parse->Extn(index2);
+							if (COpaqueDataParse::CompareFileSuffixL(*fileSuffix, extn))
+								{
+								matchFound = ETrue;
+								matchLevel = index2;
+								break;
+								}
+							}
+						}
+
+					break;
+					}
+					
+				case EMatchReqUids:
+					{
+					if(!parse->OnlyUidsAvail())
+						{
+						parse->EnsureBinaryPropertiesReadL();
+						if(parse->CheckRequiredUids(requiredUids))
+							{
+							matchFound = ETrue;
+							if(parse->IsDefaultCodec())
+								{
+								matchLevel = 1;
+								}
+							else
+								{
+								matchLevel = 0;
+								}
+							}
+						}					
+					break;
+					}
+
+				default:
+					{//unknown match type
+					Panic(KErrArgument);
+					}
+				}
+			
+			if (matchFound)
+				{
+				// Moved here to reduce timing required to list all codecs plugins.
+				// Check if certain extensions are required.
+				if (requiredExtensions)
+					{
+					if (!parse->SupportsExtensionsL(requiredExtensions))
+						{
+						CleanupStack::PopAndDestroy(parse);
+						continue;
+						}
+					}
+				
+				// Check if certain options are required
+				if(requiredOptions)
+					{
+					optionsMatchLevel = 0;
+					parse->EnsureBinaryPropertiesReadL();
+					if(parse->CheckOptionsUids(requiredOptionsUids))
+						{
+						optionsMatchLevel = 1;// one for having required options
+						if(parse->IsDefaultCodec())
+							{
+							optionsMatchLevel = 2; // two for being default codec and having required options
+							}
+						}
+					}
+				
+				TSortImplInfo sortInfo(fullList[index],matchLevel,optionsMatchLevel);
+				User::LeaveIfError(sortList.Append(sortInfo));
+				}
+			}
+		CleanupStack::PopAndDestroy(parse);
+		}
+
+	TLinearOrder<TSortImplInfo>* sortFunction = NULL;
+	if(matchType==EMatchMIMEType)
+		sortFunction = new (ELeave) TLinearOrder<TSortImplInfo>(SortAsending);
+	else
+		sortFunction = new (ELeave) TLinearOrder<TSortImplInfo>(SortDesending);
+
+	sortList.Sort(*sortFunction);
+	delete sortFunction;
+
+	RImplInfoArray* retList = new (ELeave) RImplInfoArray;
+	CleanupStack::PushL(retList);
+	// coverity[double_push]
+	CleanupClosePushL(*retList); // note the double PushL - will Close and delete on PopAndDestroy(2)
+
+	TInt noEntries = sortList.Count();
+	for(index = 0; index < noEntries; index++)
+		User::LeaveIfError(retList->Append(sortList[index].iImplInfo));
+		
+	if ((matchType == EMatchString) && (noEntries > 1))
+		{
+		// check that there is no ambiguity due to a short match string
+		TBool matchStringIsTooShort = EFalse;
+		for (TInt i = 0; i < noEntries; i++)
+			{
+			const CImplementationInformation& implementationInfo = *((*retList)[i]);
+			TInt implementationStringLength = implementationInfo.DataType().Length();
+			while ((implementationStringLength > 0) && (implementationInfo.DataType()[implementationStringLength - 1] == '?'))
+				{ // Clip extraneous '?' wildcards off the end of the plugin match string
+				implementationStringLength--;
+				}
+			if (matchString->Length() < implementationStringLength)
+				{
+				matchStringIsTooShort = ETrue;
+				break;
+				}
+			}
+
+			if (matchStringIsTooShort)
+				{
+				User::Leave(KErrUnderflow);
+				}
+			}
+
+
+
+	CleanupStack::Pop(2, retList); // retList x2
+
+	CleanupStack::PopAndDestroy(6, customMatch); // sortList, requiredOptionsUids, requiredUids, fileSuffix, matchString, customMatch
+
+	return retList;
+	}
+
+/**
+ * Function to sort an array of TSortImplInfo in asending order of the match level, options match level and
+ * then in desending order of version numbers.
+ *
+ * @param	"const TSortImplInfo& aImpInfo1"
+ *			First element.
+ * @param	"const TSortImplInfo& aImpInfo2"
+ *			Second element.
+ * @return	"TInt"
+ *			Indication of element swapping order.
+ */
+TInt CImageConversionResolver::SortAsending(const TSortImplInfo& aImpInfo1, const TSortImplInfo& aImpInfo2)
+	{
+	TInt result = aImpInfo1.iMatchLevel - aImpInfo2.iMatchLevel;
+
+	if(result == 0)
+		result = aImpInfo1.iOptionsMatchLevel - aImpInfo2.iOptionsMatchLevel;
+
+	if(result == 0)
+		result = aImpInfo2.iImplInfo->Version() - aImpInfo1.iImplInfo->Version();
+
+	return result;
+	}
+
+/**
+ * Function to sort an array of TSortImplInfo in desending order of the match level, options match level 
+ * and version numbers.
+ *
+ * @param	"const TSortImplInfo& aImpInfo1"
+ *			First element.
+ * @param	"const TSortImplInfo& aImpInfo2"
+ *			Second element.
+ * @return	"TInt"
+ *			Indication of element swapping order.
+ */
+TInt CImageConversionResolver::SortDesending(const TSortImplInfo& aImpInfo1, const TSortImplInfo& aImpInfo2)
+	{
+	TInt result = aImpInfo2.iMatchLevel - aImpInfo1.iMatchLevel;
+
+	if(result == 0)
+		result = aImpInfo2.iOptionsMatchLevel - aImpInfo1.iOptionsMatchLevel;
+	
+	if(result == 0)
+		result = aImpInfo2.iImplInfo->Version() - aImpInfo1.iImplInfo->Version();
+
+	return result;
+	}
+
+/**
+ * Construtor for the TSortImplInfo class
+ *
+ * @param	"CImplementationInformation *const aImplInfo"
+ *			A implementation information element to be sorted.
+ * @param	"TInt aMatchLevel"
+ *			The matching level of the entry
+ */
+TSortImplInfo::TSortImplInfo(CImplementationInformation *const aImplInfo, TInt aMatchLevel):
+	iImplInfo(aImplInfo),
+	iMatchLevel(aMatchLevel),
+	iOptionsMatchLevel(0)	
+	{
+	}
+
+/**
+ * Construtor for the TSortImplInfo class
+ *
+ * @param	"CImplementationInformation *const aImplInfo"
+ *			A implementation information element to be sorted.
+ * @param	"TInt aMatchLevel"
+ *			The matching level of the entry
+ * @param	"TInt aOptionsMatchLevel"
+ *			The options matching level of the entry
+ */
+TSortImplInfo::TSortImplInfo(CImplementationInformation *const aImplInfo, TInt aMatchLevel, TInt aOptionsMatchLevel):
+	iImplInfo(aImplInfo),
+	iMatchLevel(aMatchLevel),
+	iOptionsMatchLevel(aOptionsMatchLevel)
+	{
+	}
+