xml/xmldomandxpath/src/xmlenginedom/xmlengxpathconfiguration.cpp
changeset 0 e35f40988205
--- /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 <xml/dom/xmlengxpathconfiguration.h>
+#include "xmlengxpathevaluationcontext_impl.h"
+#include "libxml2_globals_private.h"
+#include <xml/dom/xmlengxpatherrors.h>
+#include <xml/utils/xmlengmem.h>
+#include <xml/utils/xmlengxestrings.h>
+
+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<MXmlEngXPathExtensionFunction*>(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<TXmlEngExtensionFunctionDescriptor>& 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<TXmlEngExtensionFunctionDescriptor>& 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<TXmlEngExtensionFunctionDescriptor>& aFuncVector, TUint aSize )
+    {
+    for (TUint i = 0; i < aSize; i++)
+        {
+        RemoveExtensionFunction(aFuncVector[i]);
+        }      
+    }