diff -r 000000000000 -r e35f40988205 xml/xmldomandxpath/src/xmlenginedom/xmlengxpathconfiguration.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/xmldomandxpath/src/xmlenginedom/xmlengxpathconfiguration.cpp Thu Dec 17 09:29:21 2009 +0200 @@ -0,0 +1,300 @@ +// Copyright (c) 2006-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: +// XPath configuraion functions +// + +#include "xmlengdomdefs.h" +#include +#include "xmlengxpathevaluationcontext_impl.h" +#include "libxml2_globals_private.h" +#include +#include +#include + +const TInt KHashTableSize = 32; + +// ----------------------------------------------------------------------------------------------------- +// Common callback for all extension functions +// +// Prototyped by: +// typedef void (*xmlXPathFunction) (xmlXPathParserContextPtr ctxt, int nargs); +// +// Non-natively implemented XPath extension function cannot be registered in libxml2 XPath module +// directly without using libxml2 XPath API.Thus, native implementation is impossible +// when libxml2's APIs are hidden. +// +// That is why this callback is used: it is a front-end for function calls. +// Function pointers are registered in a separate storage (xmlXPathIntermediaryExtensionFunctionsHash) +// and are dynamically discovered during function call by function name and namespace uri. +// ----------------------------------------------------------------------------------------------------- +// +void XmlEngineXpathCommonExtensionCallback(xmlXPathParserContextPtr ctxt, int nargs) + { + // Select function to call + const xmlChar* KFunc = ctxt->context->function; + const xmlChar* KFuncNs = ctxt->context->functionURI; + + void* funcPtr = xmlHashLookup2( + xmlXPathIntermediaryExtensionFunctionsHash, + KFunc, + KFuncNs); + if (!funcPtr) + { + XP_ERROR(XPATH_UNKNOWN_FUNC_ERROR); + } + MXmlEngXPathExtensionFunction* extFunc = reinterpret_cast(funcPtr); + // Check arity + TInt maxArity = extFunc->MaxArity(); + if (nargs < ((TInt)extFunc->MinArity()) || + (maxArity >= 0 && nargs > maxArity)) + { + XP_ERROR(XPATH_INVALID_ARITY); + } + // Wrap arguments + TXmlEngXPathEvaluationContextImpl context(ctxt, nargs); + if (!context.Initialize()) + { + SET_OOM_FLAG; + XP_ERROR(XPATH_MEMORY_ERROR); + } + // Call function + MXmlEngXPathExtensionFunction::TXmlEngEvaluationStatus status = extFunc->Evaluate(&context); + RXmlEngXPathResult res = context.Result(); + if (status != MXmlEngXPathExtensionFunction::ESucceeded) + { + xmlXPathFreeObject(INTERNAL_XPATHOBJPTR(res)); + XP_ERROR(XPATH_XE_EXTENSION_FUNC_ERROR); + } + // Remove arguments from the evaluation stack + + for (TInt i = 0; i < nargs; i++) + { + xmlXPathFreeObject(valuePop(ctxt)); + } + + // Push the result to the stack + valuePush(ctxt, INTERNAL_XPATHOBJPTR(res)); // Note: no need to check OOM flag -- later... + + } + +// ----------------------------------------------------------------------------------------------------- +// Default constructor +// ----------------------------------------------------------------------------------------------------- +// +EXPORT_C TXmlEngExtensionFunctionDescriptor::TXmlEngExtensionFunctionDescriptor() + { + iFunc = NULL; + iName = NULL; + iNamespaceUri = NULL; + iReserved = 0; + } + +// ----------------------------------------------------------------------------------------------------- +// Switches On or Off support of XForms extensions by XML Engine: +// - instance() function +// +// @param aEnable ETrue/EFalse to Enable/Disable additional functions +// +// @note +// Currently, XForms extensions are always ON and this method does nothing. +// ----------------------------------------------------------------------------------------------------- +// +EXPORT_C void XmlEngXPathConfiguration::Unused_Func1(TBool /*aEnable*/) + { + } + +// ----------------------------------------------------------------------------------------------------- +// Disables support of any previously registered extension functions +// and switches to support of only XPath Function Library. +// ----------------------------------------------------------------------------------------------------- +// +EXPORT_C void XmlEngXPathConfiguration::ResetExtensionFunctionsL() + { + // Set the hash tables free: + // xmlXPathIntermediaryExtensionFunctionsHash and + // xmlXPathDefaultFunctionsHash + // + + xmlHashTablePtr& fExtHash = xmlXPathIntermediaryExtensionFunctionsHash; + xmlHashFree(fExtHash, NULL); + fExtHash = NULL; + // + xmlHashTablePtr& fHash = xmlXPathDefaultFunctionsHash; + xmlHashFree(fHash, NULL); + fHash = NULL; + + // Fill the hash table with standard functions + // + // This reinitializes hash tables of XPath functions + xmlXPathContextPtr ctxt = xmlXPathNewContext(NULL); + OOM_IF_NULL(ctxt); + xmlXPathFreeContext(ctxt); + } + +EXPORT_C TBool XmlEngXPathConfiguration::IsFunctionSupportedL( + const TDesC8& aFunc, + const TDesC8& aNsUri ) + { + if(!xmlXPathDefaultFunctionsHash) + { + return FALSE; + } + // If the function hashes are not initialized -- we should do it! + + + + + + + + xmlChar* func = xmlCharFromDesC8L(aFunc); + CleanupStack::PushL(func); + xmlChar* ns = NULL; + if(aNsUri.Length()) + ns = xmlCharFromDesC8L(aNsUri); + void* test = xmlHashLookup2( + xmlXPathDefaultFunctionsHash, + func, + ns); + TBool res = (NULL != test); + delete ns; + CleanupStack::PopAndDestroy(func); + return res; + } + +EXPORT_C void XmlEngXPathConfiguration::AddExtensionFunctionL(const TXmlEngExtensionFunctionDescriptor& aFuncDes ) + { + xmlHashTablePtr fHash = xmlXPathIntermediaryExtensionFunctionsHash; + // store new function to XPath Extensions storage + if (!fHash) + { + + + xmlXPathIntermediaryExtensionFunctionsHash = fHash = xmlHashCreate(KHashTableSize); + OOM_IF_NULL(fHash); + } + + + + // Note: it is not critical, since redefinitions of core XPath function won't be found + TInt res = xmlHashUpdateEntry2( + fHash, + (const xmlChar*)aFuncDes.iName, + (const xmlChar*)aFuncDes.iNamespaceUri, + aFuncDes.iFunc, + NULL); + if (res == -1) + { + TEST_OOM_FLAG; + User::Leave(KXmlEngErrXPathResult); + } + // Note: for now it is fixed that once defined, an extension is available in all + // evaluations of XPath in this thread. + xmlXPathDefineExtensionFunctionsGlobally = 1; + // register common callback in XPath engine with new function's name + if (!xmlXPathDefaultFunctionsHash) + { + // It was not initialized yet + // This is temporal solution to force initialization + xmlXPathContextPtr tmpCtxt = xmlXPathNewContext(NULL); + OOM_IF_NULL(tmpCtxt); + xmlXPathFreeContext(tmpCtxt); + + } + + if ( !xmlXPathDefaultFunctionsHash ) + { + User::Leave(KXmlEngErrWrongUseOfAPI); + } + res = xmlHashUpdateEntry2( + xmlXPathDefaultFunctionsHash, + (const xmlChar*)aFuncDes.iName, + (const xmlChar*)aFuncDes.iNamespaceUri, + (void*)XmlEngineXpathCommonExtensionCallback, + NULL); + + if (res == -1) + { + TEST_OOM_FLAG; + User::Leave(KXmlEngErrXPathResult); + } + // Now, XmlEngineXpathCommonExtensionCallback is called for registered function. + // XmlEngineXpathCommonExtensionCallback performs lookup in + // xmlXPathIntermediaryExtensionFunctionsHash for a function pointer by function name + // wraps XPath evaluation context (arguments) and calls Evaluate() method of + // registered function + } + +EXPORT_C void XmlEngXPathConfiguration::AddExtensionFunctionVectorL (const RArray& aFuncVector, TUint aSize) + { + for (TUint i = 0; i < aSize; i++) + { + AddExtensionFunctionL(aFuncVector[i]); + } + } + +EXPORT_C void XmlEngXPathConfiguration::AddNativeExtensionFunctionL(const TXmlEngExtensionFunctionDescriptor& aNativeFuncDes ) + { + if (!xmlXPathDefaultFunctionsHash) + { + // It was not initialized yet + // This is temporal solution to force initialization + xmlXPathContextPtr tmpCtxt = xmlXPathNewContext(NULL); + OOM_IF_NULL(tmpCtxt); + xmlXPathFreeContext(tmpCtxt); + } + + if ( !xmlXPathDefaultFunctionsHash ) + { + User::Leave(KXmlEngErrWrongUseOfAPI); + } + + TInt res = xmlHashUpdateEntry2( + xmlXPathDefaultFunctionsHash, + (const xmlChar*)aNativeFuncDes.iName, + (const xmlChar*)aNativeFuncDes.iNamespaceUri, + aNativeFuncDes.iFunc, + NULL); + + if (res == -1) + { + TEST_OOM_FLAG; + User::Leave(KXmlEngErrXPathResult); + } + } + +EXPORT_C void XmlEngXPathConfiguration::AddNativeExtensionFunctionVectorL(const RArray& aNativeFuncVector, TUint aSize) + { + for (TUint i = 0; i < aSize; i++) + { + AddNativeExtensionFunctionL(aNativeFuncVector[i]); + } + } + +EXPORT_C void XmlEngXPathConfiguration::RemoveExtensionFunction(const TXmlEngExtensionFunctionDescriptor& aFuncDes ) + { + xmlHashRemoveEntry2( + xmlXPathDefaultFunctionsHash, + (const xmlChar*)aFuncDes.iName, + (const xmlChar*)aFuncDes.iNamespaceUri, + NULL /* deallocator function */); + } + +EXPORT_C void XmlEngXPathConfiguration::RemoveExtensionFunctionVector(const RArray& aFuncVector, TUint aSize ) + { + for (TUint i = 0; i < aSize; i++) + { + RemoveExtensionFunction(aFuncVector[i]); + } + }