--- /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)
+ {
+ }
+