fixing bug #101602 for extension modules init and shutdown callbacks,
authorDaniel Veillard <veillard@src.gnome.org>
Mon, 13 Jan 2003 22:28:34 +0000 (22:28 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Mon, 13 Jan 2003 22:28:34 +0000 (22:28 +0000)
* libxslt/extensions.c libxslt/transform.c: fixing bug #101602
  for extension modules init and shutdown callbacks, check that
  they are now called when needed.
* python/libxsl.py python/libxslt-python-api.xml python/libxslt.c:
  started adding the extension module support at the Python level.
  Still a strange bug to hunt down left.
Daniel

ChangeLog
libxslt/extensions.c
libxslt/transform.c
python/libxsl.py
python/libxslt-python-api.xml
python/libxslt.c
python/libxsltclass.txt

index 74db91c..00b4842 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Mon Jan 13 23:25:59 CET 2003 Daniel Veillard <daniel@veillard.com>
+
+       * libxslt/extensions.c libxslt/transform.c: fixing bug #101602
+         for extension modules init and shutdown callbacks, check that
+         they are now called when needed.
+       * python/libxsl.py python/libxslt-python-api.xml python/libxslt.c:
+         started adding the extension module support at the Python level.
+         Still a strange bug to hunt down left.
+
 Sun Jan 12 23:56:18 CET 2003 Daniel Veillard <daniel@veillard.com>
 
        * libxslt/attributes.c libxslt/xsltInternals.h libxslt/imports.c
index b597e57..11b27d2 100644 (file)
@@ -306,6 +306,10 @@ xsltRegisterExtPrefix(xsltStylesheetPtr style,
     if ((style == NULL) || (prefix == NULL) | (URI == NULL))
        return(-1);
 
+#ifdef WITH_XSLT_DEBUG_EXTENSIONS
+    xsltGenericDebug(xsltGenericDebugContext,
+        "Registering extension prefix %s : %s\n", prefix, URI);
+#endif
     def = (xsltExtDefPtr) style->nsDefs;
     while (def != NULL) {
        if (xmlStrEqual(prefix, def->prefix))
@@ -317,6 +321,21 @@ xsltRegisterExtPrefix(xsltStylesheetPtr style,
        return(-1);
     ret->next = (xsltExtDefPtr) style->nsDefs;
     style->nsDefs = ret;
+
+    /*
+     * check wether there is an extension module with a stylesheet
+     * initialization function.
+     */
+    if (xsltExtensionsHash != NULL) {
+       xsltExtModulePtr module;
+
+       module = xmlHashLookup(xsltExtensionsHash, URI);
+       if (module != NULL) {
+           xsltExtDataPtr data;
+
+           data = xsltStyleGetExtData(style, URI);
+       }
+    }
     return(0);
 }
 
@@ -438,17 +457,19 @@ xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI) {
 #endif
            return(NULL);
        } else {
-           if (module->styleInitFunc == NULL)
-               return(NULL);
-
+           if (module->styleInitFunc == NULL) {
 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
-           xsltGenericDebug(xsltGenericDebugContext,
-                            "Initializing module: %s\n", URI);
+               xsltGenericDebug(xsltGenericDebugContext,
+                            "Registering style module: %s\n", URI);
 #endif
-
-           extData = module->styleInitFunc(style, URI);
-           if (extData == NULL)
-               return(NULL);
+               extData = NULL;
+           } else {
+#ifdef WITH_XSLT_DEBUG_EXTENSIONS
+               xsltGenericDebug(xsltGenericDebugContext,
+                                "Initializing module: %s\n", URI);
+#endif
+               extData = module->styleInitFunc(style, URI);
+           }
 
            data = xsltNewExtData(module, extData);
            if (data == NULL)
@@ -576,7 +597,6 @@ xsltInitCtxtExt (xsltExtDataPtr styleData, xsltInitExtCtxt *ctxt,
        xsltGenericDebug(xsltGenericDebugContext,
                         "xsltInitCtxtExt: no extData\n");
 #endif
-       return;
     }
     ctxtData = xsltNewExtData(module, extData);
     if (ctxtData == NULL) {
index 7d4aa98..813eba6 100644 (file)
@@ -401,7 +401,6 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
        cur->extrasMax = 0;
     }
 
-
     XSLT_REGISTER_VARIABLE_LOOKUP(cur);
     XSLT_REGISTER_FUNCTION_LOOKUP(cur);
     cur->xpathCtxt->nsHash = style->nsHash;
@@ -420,6 +419,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
     cur->xinclude = xsltDoXIncludeDefault;
     cur->outputFile = NULL;
     cur->sec = xsltGetDefaultSecurityPrefs();
+
     return(cur);
 }
 
@@ -433,6 +433,13 @@ void
 xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
     if (ctxt == NULL)
        return;
+
+    /*
+     * Shutdown the extension modules associated to the stylesheet
+     * used if needed.
+     */
+    xsltShutdownCtxtExts(ctxt);
+
     if (ctxt->xpathCtxt != NULL) {
        ctxt->xpathCtxt->nsHash = NULL;
        xmlXPathFreeContext(ctxt->xpathCtxt);
index ef88cad..8fd263e 100644 (file)
@@ -49,6 +49,37 @@ else:
         import libxsltmod
         import libxml2
 
+class extensionModule:
+    def _styleInit(self, style, URI):
+        return self.styleInit(stylesheet(_obj=style), URI)
+
+    def _styleShutdown(self, style, URI, data):
+        return self.styleShutdown(stylesheet(_obj=style), URI, data)
+
+    def _ctxtInit(self, ctxt, URI):
+        return self.ctxtInit(transformCtxt(_obj=ctxt), URI)
+
+    def _ctxtShutdown(self, ctxt, URI, data):
+        return self.ctxtShutdown(transformCtxt(_obj=ctxt), URI, data)
+
+    def styleInit(self, style, URI):
+        """Callback function when used in a newly compiled stylesheet,
+          the return value is passed in subsequent calls"""
+       pass
+
+    def styleShutdown(self, style, URI, data):
+        """Callback function when a stylesheet using it is destroyed"""
+       pass
+
+    def ctxtInit(self, ctxt, URI):
+        """Callback function when used in a new transformation process,
+          the return value is passed in subsequent calls"""
+       pass
+
+    def ctxtShutdown(self, ctxt, URI, data):
+        """Callback function when a transformation using it finishes"""
+       pass
+
 #
 # Everything below this point is automatically generated
 #
index 7fa4b09..ecdc526 100644 (file)
       <arg name='URI' type='xmlChar *' info='the namespace or NULL'/>
       <arg name='f' type='pythonObject' info='the python function'/>
     </function>
+    <function name='xsltRegisterExtensionClass' file='python'>
+      <info>Register a Python written extension class to the XSLT engine</info>
+      <return type='int' info="0 in case of success, -1 in case of error"/>
+      <arg name='URI' type='xmlChar *' info='the namespace or NULL'/>
+      <arg name='c' type='pythonObject' info='the python class instance'/>
+    </function>
     <function name='xsltCleanup' file='python'>
       <info>Cleanup all libxslt and libxml2 memory allocated</info>
       <return type='void'/>
index 1e51791..aeda2e4 100644 (file)
 #endif
 
 /* #define DEBUG */
-/* #define DEBUG_XPATH */
+#define DEBUG_XPATH */
 /* #define DEBUG_ERROR */
 /* #define DEBUG_MEMORY */
+#define DEBUG_EXTENSIONS */
 
 void initlibxsltmod(void);
 
@@ -131,7 +132,7 @@ libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED,
     xmlChar *ns_uri;
     PyObject *pyobj_f;
 
-    if (!PyArg_ParseTuple(args, (char *)"szO:registerXPathFunction",
+    if (!PyArg_ParseTuple(args, (char *)"szO:registerExtModuleFunction",
                          &name, &ns_uri, &pyobj_f))
         return(NULL);
 
@@ -411,6 +412,195 @@ libxslt_xsltRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self,
 
 /************************************************************************
  *                                                                     *
+ *                     Extension classes                               *
+ *                                                                     *
+ ************************************************************************/
+
+static xmlHashTablePtr libxslt_extModuleClasses = NULL;
+
+static void *
+libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style,
+                                   const xmlChar * URI) {
+    PyObject *result;
+    PyObject *class = NULL;
+
+#ifdef DEBUG_EXTENSIONS
+    printf("libxslt_xsltPythonExtModuleStyleInit(%p, %s) called\n",
+          style, URI);
+#endif
+
+    if ((style == NULL) || (URI == NULL))
+       return(NULL);
+
+    /*
+     * Find the function, it should be there it was there at lookup
+     */
+    class = xmlHashLookup(libxslt_extModuleClasses, URI);
+    if (class == NULL) {
+       fprintf(stderr, "libxslt_xsltPythonExtModuleStyleInit: internal error %s not found !\n", URI);
+       return(NULL);
+    }
+
+    if (PyObject_HasAttrString(class, (char *) "_styleInit")) {
+       result = PyObject_CallMethod(class, (char *) "_styleInit",
+                    (char *) "Os", libxslt_xsltStylesheetPtrWrap(style), URI);
+    }
+    return((void *)result);
+}
+static void
+libxslt_xsltPythonExtModuleStyleShutdown(xsltStylesheetPtr style,
+                                       const xmlChar * URI, void *data) {
+    PyObject *class = NULL;
+    PyObject *result;
+
+#ifdef DEBUG_EXTENSIONS
+    printf("libxslt_xsltPythonExtModuleStyleShutdown(%p, %s, %p) called\n",
+          style, URI, data);
+#endif
+
+    if ((style == NULL) || (URI == NULL))
+       return;
+
+    /*
+     * Find the function, it should be there it was there at lookup
+     */
+    class = xmlHashLookup(libxslt_extModuleClasses, URI);
+    if (class == NULL) {
+       fprintf(stderr, "libxslt_xsltPythonExtModuleStyleShutdown: internal error %s not found !\n", URI);
+       return(NULL);
+    }
+
+    if (PyObject_HasAttrString(class, (char *) "_styleShutdown")) {
+       result = PyObject_CallMethod(class, (char *) "_styleShutdown",
+                    (char *) "OsO", libxslt_xsltStylesheetPtrWrap(style),
+                    URI, (PyObject *) data);
+       Py_XDECREF(result);
+       Py_XDECREF((PyObject *)data);
+    }
+}
+
+static void *
+libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt,
+                                   const xmlChar * URI) {
+    PyObject *result;
+    PyObject *class = NULL;
+
+#ifdef DEBUG_EXTENSIONS
+    printf("libxslt_xsltPythonExtModuleCtxtInit(%p, %s) called\n",
+          ctxt, URI);
+#endif
+
+    if ((ctxt == NULL) || (URI == NULL))
+       return(NULL);
+
+    /*
+     * Find the function, it should be there it was there at lookup
+     */
+    class = xmlHashLookup(libxslt_extModuleClasses, URI);
+    if (class == NULL) {
+       fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtInit: internal error %s not found !\n", URI);
+       return(NULL);
+    }
+
+    if (PyObject_HasAttrString(class, (char *) "_ctxtInit")) {
+       result = PyObject_CallMethod(class, (char *) "_ctxtInit",
+                    (char *) "Os", libxslt_xsltTransformContextPtrWrap(ctxt),
+                    URI);
+    }
+    return((void *)result);
+}
+static void
+libxslt_xsltPythonExtModuleCtxtShutdown(xsltTransformContextPtr ctxt,
+                                       const xmlChar * URI, void *data) {
+    PyObject *class = NULL;
+    PyObject *result;
+
+#ifdef DEBUG_EXTENSIONS
+    printf("libxslt_xsltPythonExtModuleCtxtShutdown(%p, %s, %p) called\n",
+          ctxt, URI, data);
+#endif
+
+    if ((ctxt == NULL) || (URI == NULL))
+       return;
+
+    /*
+     * Find the function, it should be there it was there at lookup
+     */
+    class = xmlHashLookup(libxslt_extModuleClasses, URI);
+    if (class == NULL) {
+       fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtShutdown: internal error %s not found !\n", URI);
+       return(NULL);
+    }
+
+    if (PyObject_HasAttrString(class, (char *) "_ctxtShutdown")) {
+       result = PyObject_CallMethod(class, (char *) "_ctxtShutdown",
+                    (char *) "OsO", libxslt_xsltTransformContextPtrWrap(ctxt),
+                    URI, (PyObject *) data);
+       Py_XDECREF(result);
+       Py_XDECREF((PyObject *)data);
+    }
+}
+
+PyObject *
+libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED,
+                                  PyObject *args) {
+    PyObject *py_retval;
+    int ret = 0;
+    xmlChar *name;
+    xmlChar *ns_uri;
+    PyObject *pyobj_c;
+
+    if (!PyArg_ParseTuple(args, (char *)"zO:registerExtensionClass",
+                         &ns_uri, &pyobj_c))
+        return(NULL);
+
+    if ((ns_uri == NULL) || (pyobj_c == NULL)) {
+       py_retval = libxml_intWrap(-1);
+       return(py_retval);
+    }
+
+#ifdef DEBUG_EXTENSIONS
+    printf("libxslt_xsltRegisterExtensionClass(%s) called\n", ns_uri);
+#endif
+
+    if (libxslt_extModuleClasses == NULL)
+       libxslt_extModuleClasses = xmlHashCreate(10);
+    if (libxslt_extModuleClasses == NULL) {
+       py_retval = libxml_intWrap(-1);
+       return(py_retval);
+    }
+    ret = xmlHashAddEntry(libxslt_extModuleClasses, ns_uri, pyobj_c);
+    if (ret != 0) {
+       py_retval = libxml_intWrap(-1);
+       return(py_retval);
+    }
+    Py_XINCREF(pyobj_c);
+
+    ret = xsltRegisterExtModuleFull(ns_uri, 
+       (xsltExtInitFunction) libxslt_xsltPythonExtModuleCtxtInit,
+       (xsltExtShutdownFunction) libxslt_xsltPythonExtModuleCtxtShutdown,
+       (xsltStyleExtInitFunction) libxslt_xsltPythonExtModuleStyleInit,
+       (xsltStyleExtShutdownFunction) libxslt_xsltPythonExtModuleStyleShutdown);
+    py_retval = libxml_intWrap((int) ret);
+    if (ret < 0) {
+       Py_XDECREF(pyobj_c);
+    }
+    return(py_retval);
+}
+
+static void
+deallocateClasse(void *payload, xmlChar *name ATTRIBUTE_UNUSED) {
+    PyObject *class = (PyObject *) payload;
+
+#ifdef DEBUG_EXTENSIONS
+    printf("deallocateClasse(%s) called\n", name);
+#endif
+
+    Py_XDECREF(class);
+}
+
+/************************************************************************
+ *                                                                     *
  *                     Integrated cleanup                              *
  *                                                                     *
  ************************************************************************/
@@ -422,6 +612,9 @@ libxslt_xsltCleanup(PyObject *self ATTRIBUTE_UNUSED,
     if (libxslt_extModuleFunctions != NULL) {
        xmlHashFree(libxslt_extModuleFunctions, deallocateCallback);
     }
+    if (libxslt_extModuleClasses != NULL) {
+       xmlHashFree(libxslt_extModuleClasses, deallocateClasse);
+    }
     xsltCleanupGlobals();
     xmlCleanupParser();
     Py_INCREF(Py_None);
index ef2bc6c..1a0dd42 100644 (file)
@@ -20,6 +20,7 @@ registerAllExtras()
 cleanup()
 registerErrorHandler()
 registerExtModuleFunction()
+registerExtensionClass()
 
 # functions from module transform
 setXIncludeDefault()