mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			869 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			869 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
/* xmlj_transform.c -
 | 
						|
   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
#include "gnu_xml_libxmlj_transform_GnomeTransformerFactory.h"
 | 
						|
#include "gnu_xml_libxmlj_transform_GnomeTransformer.h"
 | 
						|
 | 
						|
#include "xmlj_dom.h"
 | 
						|
#include "xmlj_io.h"
 | 
						|
#include "xmlj_error.h"
 | 
						|
#include "xmlj_node.h"
 | 
						|
#include "xmlj_sax.h"
 | 
						|
#include "xmlj_util.h"
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include <libxml/xmlmemory.h>
 | 
						|
#include <libxml/debugXML.h>
 | 
						|
#include <libxml/xmlIO.h>
 | 
						|
#include <libxml/xinclude.h>
 | 
						|
#include <libxml/parser.h>
 | 
						|
#include <libxml/catalog.h>
 | 
						|
#include <libxslt/keys.h>
 | 
						|
#include <libxslt/xslt.h>
 | 
						|
#include <libxslt/xsltInternals.h>
 | 
						|
#include <libxslt/transform.h>
 | 
						|
#include <libxslt/xsltutils.h>
 | 
						|
#include <libxslt/functions.h>
 | 
						|
#include <libxslt/extensions.h>
 | 
						|
#include <libxslt/documents.h>
 | 
						|
 | 
						|
/* Local function prototypes */
 | 
						|
 | 
						|
void
 | 
						|
xmljDocumentFunction (xmlXPathParserContextPtr ctxt, int nargs);
 | 
						|
 | 
						|
xsltStylesheetPtr
 | 
						|
xmljGetStylesheetID (JNIEnv * env, jobject transformer);
 | 
						|
 | 
						|
jobject
 | 
						|
xmljGetTransformerProperties (JNIEnv *env, jobject transformer);
 | 
						|
 | 
						|
const xmlChar *
 | 
						|
xmljBooleanToString (int value);
 | 
						|
 | 
						|
void
 | 
						|
xmljSetOutputProperties (JNIEnv *env, jobject transformer,
 | 
						|
                         xsltStylesheetPtr stylesheet);
 | 
						|
 | 
						|
jobjectArray
 | 
						|
xmljGetParameterArray (JNIEnv *env, jobject transformer);
 | 
						|
 | 
						|
const char **
 | 
						|
xmljGetParameters (JNIEnv *env, jobjectArray pa);
 | 
						|
 | 
						|
void
 | 
						|
xmljFreeParameters (JNIEnv *env, jobjectArray pa, const char **parameters);
 | 
						|
 | 
						|
xmlDocPtr
 | 
						|
xmljTransform (JNIEnv *env, jobject transformer, xmlDocPtr source);
 | 
						|
 | 
						|
void
 | 
						|
xmljTransformToSAX (JNIEnv *env, jobject transformer, xmlDocPtr source,
 | 
						|
                    jobject callback);
 | 
						|
 | 
						|
xmlDocPtr
 | 
						|
xmljDocLoader (const xmlChar *uri, xmlDictPtr dict, int options,
 | 
						|
               void *ctxt, xsltLoadType type);
 | 
						|
 | 
						|
/* HACK: store stylesheet URL as context for resolving URIs in xmljDocLoader */
 | 
						|
static jstring stylesheetURL = NULL;
 | 
						|
 | 
						|
/*
 | 
						|
 * --------------------------------------------------------------------------
 | 
						|
 * 
 | 
						|
 * Native implementation for class
 | 
						|
 * gnu.xml.libxmlj.transform.GnomeTransformer follows.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
xmljSetProperty (JNIEnv * env, jobject outputProperties,
 | 
						|
		 jmethodID setPropertyMethodID, const char *name,
 | 
						|
		 const xmlChar * value)
 | 
						|
{
 | 
						|
  if (NULL != value)
 | 
						|
    {
 | 
						|
      jstring nameString = (*env)->NewStringUTF (env, name);
 | 
						|
      jstring valueString = (*env)->NewStringUTF (env, (const char *) value);
 | 
						|
 | 
						|
      jobject prevValue = (*env)->CallObjectMethod (env, outputProperties,
 | 
						|
						    setPropertyMethodID,
 | 
						|
						    nameString, valueString);
 | 
						|
      if (NULL != prevValue)
 | 
						|
	{
 | 
						|
	  (*env)->DeleteLocalRef (env, prevValue);
 | 
						|
	}
 | 
						|
 | 
						|
      (*env)->DeleteLocalRef (env, nameString);
 | 
						|
      (*env)->DeleteLocalRef (env, valueString);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
typedef struct CdataSectionScannerInfo_
 | 
						|
{
 | 
						|
  JNIEnv *env;
 | 
						|
  jobject stringBuffer;
 | 
						|
  jmethodID appendMethodID;
 | 
						|
  int isFirst;
 | 
						|
} CdataSectionScannerInfo;
 | 
						|
 | 
						|
static void
 | 
						|
cdataSectionScanner (void *payload, void *data, xmlChar * name)
 | 
						|
{
 | 
						|
  CdataSectionScannerInfo *info = (CdataSectionScannerInfo *) data;
 | 
						|
  JNIEnv *env = info->env;
 | 
						|
  jstring nameString = (*env)->NewStringUTF (env, (const char *) name);
 | 
						|
  jstring blankString = (*env)->NewStringUTF (env, " ");
 | 
						|
  jobject stringBuffer;
 | 
						|
  if (!info->isFirst)
 | 
						|
    {
 | 
						|
      stringBuffer
 | 
						|
	= (*env)->CallObjectMethod (env,
 | 
						|
				    info->stringBuffer,
 | 
						|
				    info->appendMethodID, blankString);
 | 
						|
      (*env)->DeleteLocalRef (env, stringBuffer);
 | 
						|
    }
 | 
						|
  info->isFirst = 0;
 | 
						|
  stringBuffer
 | 
						|
    = (*env)->CallObjectMethod (env,
 | 
						|
				info->stringBuffer,
 | 
						|
				info->appendMethodID, nameString);
 | 
						|
  (*env)->DeleteLocalRef (env, stringBuffer);
 | 
						|
  (*env)->DeleteLocalRef (env, blankString);
 | 
						|
  (*env)->DeleteLocalRef (env, nameString);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljDocumentFunction (xmlXPathParserContextPtr ctxt, int nargs)
 | 
						|
{
 | 
						|
  xmlXPathObjectPtr obj, obj2 = NULL;
 | 
						|
 | 
						|
  if ((nargs < 1) || (nargs > 2))
 | 
						|
    {
 | 
						|
      xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL,
 | 
						|
			  "document() : invalid number of args %d\n", nargs);
 | 
						|
      ctxt->error = XPATH_INVALID_ARITY;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  if (ctxt->value == NULL)
 | 
						|
    {
 | 
						|
      xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL,
 | 
						|
			  "document() : invalid arg value\n");
 | 
						|
      ctxt->error = XPATH_INVALID_TYPE;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
  if (nargs == 2)
 | 
						|
    {
 | 
						|
      if (ctxt->value->type != XPATH_NODESET)
 | 
						|
	{
 | 
						|
	  xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL,
 | 
						|
			      "document() : invalid arg expecting a nodeset\n");
 | 
						|
	  ctxt->error = XPATH_INVALID_TYPE;
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
 | 
						|
      obj2 = valuePop (ctxt);
 | 
						|
    }
 | 
						|
 | 
						|
  if (ctxt->value->type == XPATH_NODESET)
 | 
						|
    {
 | 
						|
      int i;
 | 
						|
      xmlXPathObjectPtr newobj, ret;
 | 
						|
 | 
						|
      obj = valuePop (ctxt);
 | 
						|
      ret = xmlXPathNewNodeSet (NULL);
 | 
						|
 | 
						|
      if (obj->nodesetval)
 | 
						|
	{
 | 
						|
	  for (i = 0; i < obj->nodesetval->nodeNr; i++)
 | 
						|
	    {
 | 
						|
	      valuePush (ctxt,
 | 
						|
			 xmlXPathNewNodeSet (obj->nodesetval->nodeTab[i]));
 | 
						|
	      xmlXPathStringFunction (ctxt, 1);
 | 
						|
	      if (nargs == 2)
 | 
						|
		{
 | 
						|
		  valuePush (ctxt, xmlXPathObjectCopy (obj2));
 | 
						|
		}
 | 
						|
	      else
 | 
						|
		{
 | 
						|
		  valuePush (ctxt,
 | 
						|
			     xmlXPathNewNodeSet (obj->nodesetval->
 | 
						|
						 nodeTab[i]));
 | 
						|
		}
 | 
						|
	      xsltDocumentFunction (ctxt, 2);
 | 
						|
	      newobj = valuePop (ctxt);
 | 
						|
	      ret->nodesetval = xmlXPathNodeSetMerge (ret->nodesetval,
 | 
						|
						      newobj->nodesetval);
 | 
						|
	      xmlXPathFreeObject (newobj);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
      xmlXPathFreeObject (obj);
 | 
						|
      if (obj2 != NULL)
 | 
						|
        {
 | 
						|
          xmlXPathFreeObject (obj2);
 | 
						|
        }
 | 
						|
      valuePush (ctxt, ret);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  /*
 | 
						|
   * Make sure it's converted to a string
 | 
						|
   */
 | 
						|
  xmlXPathStringFunction (ctxt, 1);
 | 
						|
  if (ctxt->value->type != XPATH_STRING)
 | 
						|
    {
 | 
						|
      xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL,
 | 
						|
			  "document() : invalid arg expecting a string\n");
 | 
						|
      ctxt->error = XPATH_INVALID_TYPE;
 | 
						|
      if (obj2 != NULL)
 | 
						|
	xmlXPathFreeObject (obj2);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  obj = valuePop (ctxt);
 | 
						|
  if (obj->stringval == NULL)
 | 
						|
    {
 | 
						|
      valuePush (ctxt, xmlXPathNewNodeSet (NULL));
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
 | 
						|
      xsltTransformContextPtr tctxt;
 | 
						|
 | 
						|
      tctxt = xsltXPathGetTransformContext (ctxt);
 | 
						|
 | 
						|
      {
 | 
						|
        SAXParseContext *saxContext =
 | 
						|
          (SAXParseContext *) tctxt->style->_private;
 | 
						|
 | 
						|
        xmlDocPtr tree = xmljResolveURIAndOpen (saxContext,
 | 
						|
                                                (const char*)obj->stringval, 
 | 
						|
                                                NULL);
 | 
						|
 | 
						|
        xsltNewDocument (tctxt, tree);	/* FIXME - free at a later point */
 | 
						|
 | 
						|
        valuePush (ctxt, xmlXPathNewNodeSet ((xmlNodePtr) tree));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  xmlXPathFreeObject (obj);
 | 
						|
  if (obj2 != NULL) {
 | 
						|
    xmlXPathFreeObject (obj2);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Returns the stylesheet pointer for the given GnomeTransformer.
 | 
						|
 */
 | 
						|
xsltStylesheetPtr
 | 
						|
xmljGetStylesheetID (JNIEnv * env, jobject transformer)
 | 
						|
{
 | 
						|
  jclass cls;
 | 
						|
  jfieldID field;
 | 
						|
  jobject id;
 | 
						|
  xsltStylesheetPtr stylesheet;
 | 
						|
 | 
						|
  if (transformer == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env, "javax/xml/transform/TransformerException",
 | 
						|
                          "Transformer is null");
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  cls = (*env)->GetObjectClass (env, transformer);
 | 
						|
  if (cls == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  field = (*env)->GetFieldID (env, cls, "stylesheet", "Ljava/lang/Object;");
 | 
						|
  if (field == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  id = (*env)->GetObjectField (env, transformer, field);
 | 
						|
  stylesheet = (xsltStylesheetPtr) xmljAsPointer (env, id);
 | 
						|
  if (stylesheet == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env, "javax/xml/transform/TransformerException",
 | 
						|
                          "Stylesheet is null");
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  return stylesheet;
 | 
						|
}
 | 
						|
 | 
						|
jobject
 | 
						|
xmljGetTransformerProperties (JNIEnv *env, jobject transformer)
 | 
						|
{
 | 
						|
  jclass cls;
 | 
						|
  jfieldID field;
 | 
						|
  
 | 
						|
  cls = (*env)->GetObjectClass (env, transformer);
 | 
						|
  if (cls == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  field = (*env)->GetFieldID (env, cls, "outputProperties",
 | 
						|
                              "Ljava/util/Properties;");
 | 
						|
  if (field == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  return (*env)->GetObjectField (env, transformer, field);
 | 
						|
}
 | 
						|
 | 
						|
const xmlChar *
 | 
						|
xmljBooleanToString (int value)
 | 
						|
{
 | 
						|
  return value ? BAD_CAST "yes" : BAD_CAST "no";
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Sets the output properties for the given transformer,
 | 
						|
 * based on its stylesheet.
 | 
						|
 */
 | 
						|
void
 | 
						|
xmljSetOutputProperties (JNIEnv *env, jobject transformer,
 | 
						|
                         xsltStylesheetPtr stylesheet)
 | 
						|
{
 | 
						|
  jobject outputProperties;
 | 
						|
  jclass propertiesClass;
 | 
						|
  jmethodID setPropertyMethod;
 | 
						|
 | 
						|
  outputProperties = xmljGetTransformerProperties (env, transformer);
 | 
						|
  if (outputProperties == NULL)
 | 
						|
    {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  propertiesClass = (*env)->FindClass (env, "java/util/Properties");
 | 
						|
  if (propertiesClass == NULL)
 | 
						|
    {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  setPropertyMethod =
 | 
						|
    (*env)->GetMethodID (env, propertiesClass, "setProperty",
 | 
						|
                         "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
 | 
						|
  if (setPropertyMethod == NULL)
 | 
						|
    {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "encoding", stylesheet->encoding);
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "media-type", stylesheet->mediaType);
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "doctype-public", stylesheet->doctypePublic);
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "doctype-system", stylesheet->doctypeSystem);
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "indent", xmljBooleanToString (stylesheet->indent));
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "method", stylesheet->method);
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "standalone", xmljBooleanToString (stylesheet->standalone));
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "version", stylesheet->version);
 | 
						|
  
 | 
						|
  xmljSetProperty (env, outputProperties, setPropertyMethod,
 | 
						|
                   "omit-xml-declaration",
 | 
						|
                   xmljBooleanToString (stylesheet->omitXmlDeclaration));
 | 
						|
  
 | 
						|
    {
 | 
						|
      CdataSectionScannerInfo info;
 | 
						|
      jclass stringBufferClass
 | 
						|
        =
 | 
						|
        (*env)->FindClass (env,
 | 
						|
                           "java/lang/StringBuffer");
 | 
						|
      jmethodID stringBufferConstructorID =
 | 
						|
        (*env)->GetMethodID (env, stringBufferClass,
 | 
						|
                             "<init>", "()V");
 | 
						|
      jmethodID toStringMethodID =
 | 
						|
        (*env)->GetMethodID (env, stringBufferClass,
 | 
						|
                             "toString",
 | 
						|
                             "()Ljava/lang/String;");
 | 
						|
      info.env = env;
 | 
						|
      info.isFirst = 1;
 | 
						|
      info.stringBuffer
 | 
						|
        = (*env)->AllocObject (env, stringBufferClass);
 | 
						|
      (*env)->CallVoidMethod (env, info.stringBuffer,
 | 
						|
                              stringBufferConstructorID);
 | 
						|
      info.appendMethodID =
 | 
						|
        (*env)->GetMethodID (env, stringBufferClass,
 | 
						|
                             "append",
 | 
						|
                             "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
 | 
						|
      
 | 
						|
      xmlHashScan (stylesheet->cdataSection,
 | 
						|
                   cdataSectionScanner, &info);
 | 
						|
      
 | 
						|
        {
 | 
						|
          jstring result = (jstring)
 | 
						|
            (*env)->CallObjectMethod (env,
 | 
						|
                                      info.stringBuffer,
 | 
						|
                                      toStringMethodID);
 | 
						|
          
 | 
						|
          jstring nameString =
 | 
						|
            (*env)->NewStringUTF (env,
 | 
						|
                                  "cdata-section-elements");
 | 
						|
          
 | 
						|
          jobject prevValue
 | 
						|
            =
 | 
						|
            (*env)->CallObjectMethod (env,
 | 
						|
                                      outputProperties,
 | 
						|
                                      setPropertyMethod,
 | 
						|
                                      nameString, result);
 | 
						|
          if (NULL != prevValue)
 | 
						|
            {
 | 
						|
              (*env)->DeleteLocalRef (env, prevValue);
 | 
						|
            }
 | 
						|
          (*env)->DeleteLocalRef (env, nameString);
 | 
						|
        }
 | 
						|
      
 | 
						|
      (*env)->DeleteLocalRef (env, info.stringBuffer);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Returns the parameter array for the given GnomeTransformer.
 | 
						|
 */
 | 
						|
jobjectArray
 | 
						|
xmljGetParameterArray (JNIEnv *env, jobject transformer)
 | 
						|
{
 | 
						|
  jclass cls;
 | 
						|
  jmethodID method;
 | 
						|
 | 
						|
  cls = (*env)->GetObjectClass (env, transformer);
 | 
						|
  if (cls == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  method = (*env)->GetMethodID (env, cls, "getParameterArray",
 | 
						|
                                "()[Ljava/lang/String;");
 | 
						|
  if (method == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  return (jobjectArray) (*env)->CallObjectMethod (env, transformer, method);
 | 
						|
}
 | 
						|
 | 
						|
/* Convert parameter array to xmlChar ** */
 | 
						|
const char **
 | 
						|
xmljGetParameters (JNIEnv *env, jobjectArray pa)
 | 
						|
{
 | 
						|
  int i, len;
 | 
						|
  const char **parameters;
 | 
						|
 | 
						|
  len = (*env)->GetArrayLength (env, pa);
 | 
						|
  parameters = (const char **) malloc ((len + 2) * sizeof (const char *));
 | 
						|
  if (parameters == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  
 | 
						|
  for (i = 0; i < len; i++)
 | 
						|
    {
 | 
						|
      jstring string = (jstring) (*env)->GetObjectArrayElement (env, pa, i);
 | 
						|
      
 | 
						|
      if (string != NULL)
 | 
						|
        {
 | 
						|
          parameters[i] = (*env)->GetStringUTFChars (env, string, NULL);
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          parameters[i] = NULL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
  
 | 
						|
  parameters[len] = 0;
 | 
						|
  parameters[len + 1] = 0;
 | 
						|
  return parameters;
 | 
						|
}
 | 
						|
  
 | 
						|
/* Release parameter strings */
 | 
						|
void
 | 
						|
xmljFreeParameters (JNIEnv *env, jobjectArray pa, const char **parameters)
 | 
						|
{ 
 | 
						|
  int i, len;
 | 
						|
  
 | 
						|
  len = (*env)->GetArrayLength (env, pa);
 | 
						|
  for (i = 0; i < len; i++)
 | 
						|
    {
 | 
						|
      jstring string = (jstring) (*env)->GetObjectArrayElement (env, pa, i);
 | 
						|
      if (string != NULL)
 | 
						|
        {
 | 
						|
          (*env)->ReleaseStringUTFChars (env, string, parameters[i]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
  
 | 
						|
  free (parameters);
 | 
						|
}
 | 
						|
 | 
						|
xmlDocPtr
 | 
						|
xmljTransform (JNIEnv *env, jobject transformer, xmlDocPtr source)
 | 
						|
{
 | 
						|
  xsltStylesheetPtr stylesheet;
 | 
						|
  xmlDocPtr result;
 | 
						|
  jobjectArray pa;
 | 
						|
  const char **parameters;
 | 
						|
 | 
						|
  stylesheet = xmljGetStylesheetID (env, transformer);
 | 
						|
  pa = xmljGetParameterArray (env, transformer);
 | 
						|
  parameters = xmljGetParameters (env, pa);
 | 
						|
  if (parameters == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env, "javax/xml/transform/TransformerException",
 | 
						|
                          "Couldn't allocate memory for parameters");
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  result = xsltApplyStylesheet (stylesheet, source, parameters);
 | 
						|
  xmljFreeParameters (env, pa, parameters);
 | 
						|
  if (result == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env, "javax/xml/transform/TransformerException",
 | 
						|
                          "XSLT transformation failed");
 | 
						|
    }
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljTransformToSAX (JNIEnv *env, jobject transformer, xmlDocPtr source,
 | 
						|
                    jobject callback)
 | 
						|
{
 | 
						|
  xsltStylesheetPtr stylesheet;
 | 
						|
  int ret;
 | 
						|
  jobjectArray pa;
 | 
						|
  const char **parameters;
 | 
						|
  xmlSAXHandlerPtr sax;
 | 
						|
 | 
						|
  stylesheet = xmljGetStylesheetID (env, transformer);
 | 
						|
  pa = xmljGetParameterArray (env, transformer);
 | 
						|
  parameters = xmljGetParameters (env, pa);
 | 
						|
  if (parameters == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env, "javax/xml/transform/TransformerException",
 | 
						|
                          "Couldn't allocate memory for parameters");
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  sax = NULL; /* TODO link up sax and callback */
 | 
						|
  ret = xsltRunStylesheet (stylesheet, source, parameters, NULL, sax, NULL);
 | 
						|
  xmljFreeParameters (env, pa, parameters);
 | 
						|
  if (ret == -1)
 | 
						|
    {
 | 
						|
      xmljThrowException (env, "javax/xml/transform/TransformerException",
 | 
						|
                          "XSLT transformation failed");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
xmlDocPtr
 | 
						|
xmljDocLoader (const xmlChar *uri, xmlDictPtr dict, int options,
 | 
						|
               void *ctxt, xsltLoadType type)
 | 
						|
{
 | 
						|
  JNIEnv *env;
 | 
						|
  jclass xmljClass;
 | 
						|
  jclass inputStreamClass;
 | 
						|
  jmethodID getInputStream;
 | 
						|
  jmethodID getDetectBuffer;
 | 
						|
  jstring systemId;
 | 
						|
  jobject inputStream;
 | 
						|
  jbyteArray detectBuffer;
 | 
						|
 | 
						|
  fflush(stdout);
 | 
						|
  env = xmljGetJNIEnv ();
 | 
						|
  if (!env)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  xmljClass = (*env)->FindClass (env, "gnu/xml/libxmlj/util/XMLJ");
 | 
						|
  if (!xmljClass)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  getInputStream =
 | 
						|
    (*env)->GetStaticMethodID (env, xmljClass, "xmljGetInputStream",
 | 
						|
                               "(Ljava/lang/String;Ljava/lang/String;)Lgnu/xml/libxmlj/util/NamedInputStream;");
 | 
						|
  if (!getInputStream)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  systemId = xmljNewString (env, uri);
 | 
						|
  inputStream = (*env)->CallStaticObjectMethod (env, xmljClass, getInputStream,
 | 
						|
                                                stylesheetURL, systemId);
 | 
						|
  if (!inputStream)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  inputStreamClass = (*env)->GetObjectClass (env, inputStream);
 | 
						|
  if (!inputStreamClass)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  getDetectBuffer = (*env)->GetMethodID (env, inputStreamClass,
 | 
						|
                                         "getDetectBuffer", "()[B");
 | 
						|
  if (!getDetectBuffer)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  detectBuffer = (*env)->CallObjectMethod (env, inputStream, getDetectBuffer);
 | 
						|
  if (!detectBuffer)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  return xmljParseDocument (env, NULL, inputStream, detectBuffer,
 | 
						|
                            NULL, systemId, stylesheetURL,
 | 
						|
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 2);
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.newStylesheet */
 | 
						|
JNIEXPORT jobject JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_newStylesheet (JNIEnv *env,
 | 
						|
                                                               jobject self)
 | 
						|
{
 | 
						|
  xsltStylesheetPtr stylesheet;
 | 
						|
  jobject ret;
 | 
						|
 | 
						|
  stylesheetURL = NULL;
 | 
						|
  xsltSetLoaderFunc (xmljDocLoader);
 | 
						|
  stylesheet = xsltNewStylesheet ();
 | 
						|
  xmljSetOutputProperties (env, self, stylesheet);
 | 
						|
  ret = xmljAsField (env, stylesheet);
 | 
						|
  if (ret == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env,
 | 
						|
                          "javax/xml/transform/TransformerConfigurationException",
 | 
						|
                          "Can't create Java object for stylesheet");
 | 
						|
    }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.newStylesheetFromStream */
 | 
						|
JNIEXPORT jobject JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_newStylesheetFromStream
 | 
						|
(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer,
 | 
						|
 jstring publicId, jstring systemId, jstring base,
 | 
						|
 jboolean entityResolver, jboolean errorHandler)
 | 
						|
{
 | 
						|
  xmlDocPtr doc;
 | 
						|
  xsltStylesheetPtr stylesheet;
 | 
						|
  jobject ret;
 | 
						|
 | 
						|
  doc = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId,
 | 
						|
                           base, 0, 0, 0, 0, 0, 
 | 
						|
                           entityResolver, errorHandler, 0, 0, 2);
 | 
						|
  if (doc == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  stylesheetURL = systemId;
 | 
						|
  xsltSetLoaderFunc (xmljDocLoader);
 | 
						|
  stylesheet = xsltParseStylesheetDoc (doc);
 | 
						|
  if (stylesheet == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env,
 | 
						|
                          "javax/xml/transform/TransformerConfigurationException",
 | 
						|
                          "Error parsing XSLT stylesheet");
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  xmljSetOutputProperties (env, self, stylesheet);
 | 
						|
  ret =  xmljAsField (env, stylesheet);
 | 
						|
  if (ret == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env,
 | 
						|
                          "javax/xml/transform/TransformerConfigurationException",
 | 
						|
                          "Can't create Java object for stylesheet");
 | 
						|
    }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.newStylesheetFromDoc */
 | 
						|
JNIEXPORT jobject JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_newStylesheetFromDoc
 | 
						|
(JNIEnv *env, jobject self, jobject in)
 | 
						|
{
 | 
						|
  xmlDocPtr doc;
 | 
						|
  xsltStylesheetPtr stylesheet;
 | 
						|
  jobject ret;
 | 
						|
 | 
						|
  doc = (xmlDocPtr) xmljGetNodeID (env, in);
 | 
						|
  if (doc == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  stylesheetURL = xmljNewString (env, doc->URL);
 | 
						|
  xsltSetLoaderFunc (xmljDocLoader);
 | 
						|
  stylesheet = xsltParseStylesheetDoc (doc);
 | 
						|
  if (stylesheet == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env,
 | 
						|
                          "javax/xml/transform/TransformerConfigurationException",
 | 
						|
                          "Error parsing XSLT stylesheet");
 | 
						|
    }
 | 
						|
  xmljSetOutputProperties (env, self, stylesheet);
 | 
						|
  ret =  xmljAsField (env, stylesheet);
 | 
						|
  if (ret == NULL)
 | 
						|
    {
 | 
						|
      xmljThrowException (env,
 | 
						|
                          "javax/xml/transform/TransformerConfigurationException",
 | 
						|
                          "Can't create Java object for stylesheet");
 | 
						|
    }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.transformStreamToStream */
 | 
						|
JNIEXPORT void JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformStreamToStream
 | 
						|
(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer,
 | 
						|
 jstring publicId, jstring systemId, jstring base,
 | 
						|
 jboolean entityResolver, jboolean errorHandler, jobject out)
 | 
						|
{
 | 
						|
  xmlDocPtr source;
 | 
						|
  xmlDocPtr result;
 | 
						|
 | 
						|
  source = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId,
 | 
						|
                              base, 0, 0, 0, 0, 0, 
 | 
						|
                              entityResolver, errorHandler, 0, 0, 2);
 | 
						|
  result = xmljTransform (env, self, source);
 | 
						|
  xmljSaveFileToJavaOutputStream (env, out, result,
 | 
						|
                                  (const char*) result->encoding);
 | 
						|
  xmlFreeDoc (result);
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.transformStreamToDoc */
 | 
						|
JNIEXPORT jobject JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformStreamToDoc
 | 
						|
(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer,
 | 
						|
 jstring publicId, jstring systemId, jstring base,
 | 
						|
 jboolean entityResolver, jboolean errorHandler)
 | 
						|
{
 | 
						|
  xmlDocPtr source;
 | 
						|
  xmlDocPtr result;
 | 
						|
 | 
						|
  source = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId,
 | 
						|
                              base, 0, 0, 0, 0, 0, 
 | 
						|
                              entityResolver, errorHandler, 0, 0, 2);
 | 
						|
  result = xmljTransform (env, self, source);
 | 
						|
  return xmljGetNodeInstance (env, (xmlNodePtr) result);
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.transformStreamToSAX */
 | 
						|
JNIEXPORT void JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformStreamToSAX
 | 
						|
(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer,
 | 
						|
 jstring publicId, jstring systemId, jstring base,
 | 
						|
 jboolean entityResolver, jboolean errorHandler, jobject callback)
 | 
						|
{
 | 
						|
  xmlDocPtr source;
 | 
						|
 | 
						|
  source = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId,
 | 
						|
                              base, 0, 0, 0, 0, 0, 
 | 
						|
                              entityResolver, errorHandler, 0, 0, 2);
 | 
						|
  xmljTransformToSAX (env, self, source, callback);
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.transformDocToStream */
 | 
						|
JNIEXPORT void JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformDocToStream
 | 
						|
(JNIEnv *env, jobject self, jobject doc, jobject out)
 | 
						|
{
 | 
						|
  xmlDocPtr source;
 | 
						|
  xmlDocPtr result;
 | 
						|
 | 
						|
  source = (xmlDocPtr) xmljGetNodeID (env, doc);
 | 
						|
  result = xmljTransform (env, self, source);
 | 
						|
  xmljSaveFileToJavaOutputStream (env, out, result,
 | 
						|
                                  (const char*) result->encoding);
 | 
						|
  xmlFreeDoc (result);
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.transformDocToDoc */
 | 
						|
JNIEXPORT jobject JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformDocToDoc
 | 
						|
(JNIEnv *env, jobject self, jobject doc)
 | 
						|
{
 | 
						|
  xmlDocPtr source;
 | 
						|
  xmlDocPtr result;
 | 
						|
 | 
						|
  source = (xmlDocPtr) xmljGetNodeID (env, doc);
 | 
						|
  result = xmljTransform (env, self, source);
 | 
						|
  return xmljGetNodeInstance (env, (xmlNodePtr) result);
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.transformDocToSAX */
 | 
						|
JNIEXPORT void JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformDocToSAX
 | 
						|
(JNIEnv *env, jobject self, jobject doc, jobject callback)
 | 
						|
{
 | 
						|
  xmlDocPtr source;
 | 
						|
 | 
						|
  source = (xmlDocPtr) xmljGetNodeID (env, doc);
 | 
						|
  xmljTransformToSAX (env, self, source, callback);
 | 
						|
}
 | 
						|
 | 
						|
/* GnomeTransformer.free */
 | 
						|
JNIEXPORT void JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformer_free (JNIEnv *env,
 | 
						|
                                                      jobject self)
 | 
						|
{
 | 
						|
  xsltStylesheetPtr stylesheet;
 | 
						|
 | 
						|
  stylesheet = xmljGetStylesheetID (env, self);
 | 
						|
  xsltFreeStylesheet (stylesheet);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * --------------------------------------------------------------------------
 | 
						|
 * Native implementation for class
 | 
						|
 * gnu.xml.libxmlj.transform.GnomeTransformerFactory follows.
 | 
						|
 */
 | 
						|
 | 
						|
/* GnomeTransformerFactory.freeLibxsltGlobal */
 | 
						|
JNIEXPORT void JNICALL
 | 
						|
Java_gnu_xml_libxmlj_transform_GnomeTransformerFactory_freeLibxsltGlobal (
 | 
						|
  JNIEnv *env __attribute__((__unused__)),
 | 
						|
  jclass clazz __attribute__((__unused__)))
 | 
						|
{
 | 
						|
  xsltCleanupGlobals ();
 | 
						|
  xmlCleanupParser ();
 | 
						|
}
 | 
						|
 |