mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			814 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			814 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
/* xmlj_io.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 "xmlj_io.h"
 | 
						|
#include "xmlj_error.h"
 | 
						|
#include "xmlj_node.h"
 | 
						|
#include "xmlj_sax.h"
 | 
						|
#include "xmlj_util.h"
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdarg.h>
 | 
						|
 | 
						|
#include <libxml/xmlIO.h>
 | 
						|
#include <libxml/parserInternals.h>
 | 
						|
 | 
						|
#include <pthread.h>
 | 
						|
 | 
						|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 | 
						|
#define UNSIGN(a) (((a) < 0) ? ((a) + 0x100) : (a))
 | 
						|
 | 
						|
#define DETECT_BUFFER_SIZE 50
 | 
						|
 | 
						|
typedef struct _OutputStreamContext
 | 
						|
{
 | 
						|
 | 
						|
  JNIEnv *env;
 | 
						|
  jobject outputStream;
 | 
						|
  jmethodID outputStreamWriteFunc;
 | 
						|
  jmethodID outputStreamCloseFunc;
 | 
						|
 | 
						|
}
 | 
						|
OutputStreamContext;
 | 
						|
 | 
						|
typedef struct _InputStreamContext
 | 
						|
{
 | 
						|
 | 
						|
  JNIEnv *env;
 | 
						|
  jobject inputStream;
 | 
						|
  jmethodID inputStreamReadFunc;
 | 
						|
  jmethodID inputStreamCloseFunc;
 | 
						|
  jobject bufferByteArray;
 | 
						|
  jint bufferLength;
 | 
						|
 | 
						|
}
 | 
						|
InputStreamContext;
 | 
						|
 | 
						|
InputStreamContext *xmljNewInputStreamContext (JNIEnv * env,
 | 
						|
                                               jobject inputStream);
 | 
						|
 | 
						|
void xmljFreeInputStreamContext (InputStreamContext * inContext);
 | 
						|
 | 
						|
int xmljInputReadCallback (void *context, char *buffer, int len);
 | 
						|
 | 
						|
int xmljInputCloseCallback (void *context);
 | 
						|
 | 
						|
int xmljOutputWriteCallback (void *context, const char *buffer, int len);
 | 
						|
 | 
						|
int xmljOutputCloseCallback (void *context);
 | 
						|
 | 
						|
OutputStreamContext *xmljNewOutputStreamContext (JNIEnv * env,
 | 
						|
                                                 jobject outputStream);
 | 
						|
 | 
						|
void
 | 
						|
xmljFreeOutputStreamContext (OutputStreamContext * outContext);
 | 
						|
 | 
						|
xmlCharEncoding
 | 
						|
xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer);
 | 
						|
 | 
						|
 | 
						|
#ifdef LIBXML2_NEW_BUFFER
 | 
						|
#define GET_XML_OUTPUT_BUFFER_CONTENT(buf) (gchar *) \
 | 
						|
  (char *) xmlOutputBufferGetContent(buf)
 | 
						|
#define GET_XML_OUTPUT_BUFFER_SIZE(buf) \
 | 
						|
  xmlOutputBufferGetSize(buf)
 | 
						|
#else
 | 
						|
#define GET_XML_OUTPUT_BUFFER_CONTENT(buf) \
 | 
						|
 (buf)->buffer->content
 | 
						|
#define GET_XML_OUTPUT_BUFFER_SIZE(buf) \
 | 
						|
  (buf)->buffer->use
 | 
						|
#endif
 | 
						|
 | 
						|
int
 | 
						|
xmljOutputWriteCallback (void *context, const char *buffer, int len)
 | 
						|
{
 | 
						|
  OutputStreamContext *outContext;
 | 
						|
  JNIEnv *env;
 | 
						|
  jbyteArray byteArray;
 | 
						|
 | 
						|
  outContext = (OutputStreamContext *) context;
 | 
						|
  env = outContext->env;
 | 
						|
  byteArray = (*env)->NewByteArray (env, len);
 | 
						|
 | 
						|
  if (0 != byteArray)
 | 
						|
    {
 | 
						|
      (*env)->SetByteArrayRegion (env, byteArray, 0, len, (jbyte *) buffer);
 | 
						|
 | 
						|
      (*env)->CallVoidMethod (env,
 | 
						|
                              outContext->outputStream,
 | 
						|
                              outContext->outputStreamWriteFunc, byteArray);
 | 
						|
 | 
						|
      (*env)->DeleteLocalRef (env, byteArray);
 | 
						|
 | 
						|
      return (*env)->ExceptionOccurred (env) ? -1 : len;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      /* Out of memory, signal error */
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
xmljOutputCloseCallback (void *context)
 | 
						|
{
 | 
						|
  OutputStreamContext *outContext;
 | 
						|
  JNIEnv *env;
 | 
						|
 | 
						|
  outContext = (OutputStreamContext *) context;
 | 
						|
  env = outContext->env;
 | 
						|
  (*env)->CallVoidMethod (env,
 | 
						|
                          outContext->outputStream,
 | 
						|
                          outContext->outputStreamCloseFunc);
 | 
						|
 | 
						|
  return (*env)->ExceptionOccurred (env) ? -1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
xmljInputReadCallback (void *context, char *buffer, int len)
 | 
						|
{
 | 
						|
  InputStreamContext *inContext;
 | 
						|
  JNIEnv *env;
 | 
						|
  jint nread;
 | 
						|
  int offset;
 | 
						|
 | 
						|
  inContext = (InputStreamContext *) context;
 | 
						|
  env = inContext->env;
 | 
						|
  nread = 0;
 | 
						|
 | 
						|
  for (offset = 0; offset < len && nread >= 0;)
 | 
						|
    {
 | 
						|
      nread = (*env)->CallIntMethod (env,
 | 
						|
                                     inContext->inputStream,
 | 
						|
                                     inContext->inputStreamReadFunc,
 | 
						|
                                     inContext->bufferByteArray,
 | 
						|
                                     0, MIN (len - offset,
 | 
						|
                                             inContext->bufferLength));
 | 
						|
 | 
						|
      if (nread > 0)
 | 
						|
        {
 | 
						|
          (*env)->GetByteArrayRegion (env,
 | 
						|
                                      inContext->bufferByteArray,
 | 
						|
                                      0, nread, ((jbyte *) buffer) + offset);
 | 
						|
 | 
						|
          offset += nread;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
  return (*env)->ExceptionOccurred (env) ? -1 : offset;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
xmljInputCloseCallback (void *context)
 | 
						|
{
 | 
						|
  InputStreamContext *inContext;
 | 
						|
  JNIEnv *env;
 | 
						|
 | 
						|
  inContext = (InputStreamContext *) context;
 | 
						|
  env = inContext->env;
 | 
						|
  (*env)->CallVoidMethod (env, inContext->inputStream,
 | 
						|
                          inContext->inputStreamCloseFunc);
 | 
						|
 | 
						|
  return (*env)->ExceptionOccurred (env) ? -1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
InputStreamContext *
 | 
						|
xmljNewInputStreamContext (JNIEnv * env, jobject inputStream)
 | 
						|
{
 | 
						|
  jclass inputStreamClass;
 | 
						|
  InputStreamContext *result;
 | 
						|
 | 
						|
  inputStreamClass = (*env)->FindClass (env, "java/io/InputStream");
 | 
						|
  if (inputStreamClass == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  result = (InputStreamContext *) malloc (sizeof (InputStreamContext));
 | 
						|
  if (result == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  result->env = env;
 | 
						|
  result->inputStream = inputStream;
 | 
						|
  result->inputStreamReadFunc =
 | 
						|
    (*env)->GetMethodID (env, inputStreamClass, "read", "([BII)I");
 | 
						|
  result->inputStreamCloseFunc =
 | 
						|
    (*env)->GetMethodID (env, inputStreamClass, "close", "()V");
 | 
						|
  result->bufferLength = 4096;
 | 
						|
  result->bufferByteArray = (*env)->NewByteArray (env, result->bufferLength);
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljFreeInputStreamContext (InputStreamContext * inContext)
 | 
						|
{
 | 
						|
  JNIEnv *env;
 | 
						|
 | 
						|
  env = inContext->env;
 | 
						|
  (*env)->DeleteLocalRef (env, inContext->bufferByteArray);
 | 
						|
  free (inContext);
 | 
						|
}
 | 
						|
 | 
						|
OutputStreamContext *
 | 
						|
xmljNewOutputStreamContext (JNIEnv * env, jobject outputStream)
 | 
						|
{
 | 
						|
  jclass outputStreamClass;
 | 
						|
  OutputStreamContext *result;
 | 
						|
 | 
						|
  outputStreamClass = (*env)->FindClass (env, "java/io/OutputStream");
 | 
						|
  if (outputStreamClass == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  result = (OutputStreamContext *) malloc (sizeof (OutputStreamContext));
 | 
						|
  if (result == NULL)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  result->env = env;
 | 
						|
  result->outputStream = outputStream;
 | 
						|
  result->outputStreamWriteFunc =
 | 
						|
    (*env)->GetMethodID (env, outputStreamClass, "write", "([B)V");
 | 
						|
  result->outputStreamCloseFunc =
 | 
						|
    (*env)->GetMethodID (env, outputStreamClass, "close", "()V");
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
xmljFreeOutputStreamContext (OutputStreamContext * outContext)
 | 
						|
{
 | 
						|
  free (outContext);
 | 
						|
}
 | 
						|
 | 
						|
SAXParseContext *
 | 
						|
xmljNewSAXParseContext (JNIEnv * env, jobject obj, xmlParserCtxtPtr ctx,
 | 
						|
                        jstring publicId, jstring systemId)
 | 
						|
{
 | 
						|
  SAXParseContext *ret;
 | 
						|
  
 | 
						|
  ret = (SAXParseContext *) malloc (sizeof (SAXParseContext));
 | 
						|
  ret->env = env;
 | 
						|
  ret->obj = obj;
 | 
						|
  ret->ctx = ctx;
 | 
						|
  ret->sax = ctx->sax;
 | 
						|
  ret->loc = NULL;
 | 
						|
  ret->publicId = publicId;
 | 
						|
  ret->systemId = systemId;
 | 
						|
  
 | 
						|
  ret->startDTD = NULL;
 | 
						|
  ret->externalEntityDecl = NULL;
 | 
						|
  ret->internalEntityDecl = NULL;
 | 
						|
  ret->resolveEntity = NULL;
 | 
						|
  ret->notationDecl = NULL;
 | 
						|
  ret->attributeDecl = NULL;
 | 
						|
  ret->elementDecl = NULL;
 | 
						|
  ret->unparsedEntityDecl = NULL;
 | 
						|
  ret->setDocumentLocator = NULL;
 | 
						|
  ret->startDocument = NULL;
 | 
						|
  ret->endDocument = NULL;
 | 
						|
  ret->startElement = NULL;
 | 
						|
  ret->endElement = NULL;
 | 
						|
  ret->characters = NULL;
 | 
						|
  ret->ignorableWhitespace = NULL;
 | 
						|
  ret->processingInstruction = NULL;
 | 
						|
  ret->comment = NULL;
 | 
						|
  ret->cdataBlock = NULL;
 | 
						|
  ret->warning = NULL;
 | 
						|
  ret->error = NULL;
 | 
						|
  ret->fatalError = NULL;
 | 
						|
 | 
						|
  ret->resolveURIAndOpen = NULL;
 | 
						|
  ret->stringClass = NULL; 
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljFreeSAXParseContext (SAXParseContext * saxCtx)
 | 
						|
{
 | 
						|
  free (saxCtx);
 | 
						|
}
 | 
						|
 | 
						|
xmlCharEncoding
 | 
						|
xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer)
 | 
						|
{
 | 
						|
  xmlCharEncoding ret;
 | 
						|
  jint nread;
 | 
						|
 | 
						|
  if (buffer == NULL)
 | 
						|
    {
 | 
						|
      return XML_CHAR_ENCODING_ERROR;
 | 
						|
    }
 | 
						|
  nread = (*env)->GetArrayLength (env, buffer);
 | 
						|
  if (nread >= 5)
 | 
						|
    {
 | 
						|
      jbyte nativeBuffer[DETECT_BUFFER_SIZE + 1];
 | 
						|
      unsigned char converted[DETECT_BUFFER_SIZE + 1];
 | 
						|
      int i;
 | 
						|
 | 
						|
      memset (nativeBuffer, 0, DETECT_BUFFER_SIZE + 1);
 | 
						|
      (*env)->GetByteArrayRegion (env, buffer, 0, nread, nativeBuffer);
 | 
						|
      /* Convert from signed to unsigned */
 | 
						|
      for (i = 0; i < DETECT_BUFFER_SIZE + 1; i++)
 | 
						|
        {
 | 
						|
          converted[i] = UNSIGN (nativeBuffer[i]);
 | 
						|
        }
 | 
						|
      ret = xmlDetectCharEncoding (converted, nread);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      ret = XML_CHAR_ENCODING_NONE;
 | 
						|
    }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
xmlParserCtxtPtr
 | 
						|
xmljNewParserContext (JNIEnv * env,
 | 
						|
                      jobject inputStream,
 | 
						|
                      jbyteArray detectBuffer,
 | 
						|
                      jstring publicId,
 | 
						|
                      jstring systemId,
 | 
						|
                      jstring base,
 | 
						|
                      jboolean validate,
 | 
						|
                      jboolean coalesce,
 | 
						|
                      jboolean expandEntities,
 | 
						|
                      jboolean loadEntities)
 | 
						|
{
 | 
						|
  InputStreamContext *inputContext;
 | 
						|
  xmlCharEncoding encoding;
 | 
						|
  xmlParserCtxtPtr ctx;
 | 
						|
  int options;
 | 
						|
 | 
						|
  encoding = xmljDetectCharEncoding (env, detectBuffer);
 | 
						|
  if (encoding != XML_CHAR_ENCODING_ERROR)
 | 
						|
    {
 | 
						|
      inputContext = xmljNewInputStreamContext (env, inputStream);
 | 
						|
      if (NULL != inputContext)
 | 
						|
        {
 | 
						|
          /* NOTE: userdata must be NULL for DOM to work */
 | 
						|
          ctx = xmlCreateIOParserCtxt (NULL,
 | 
						|
                                       NULL,
 | 
						|
                                       xmljInputReadCallback,
 | 
						|
                                       xmljInputCloseCallback,
 | 
						|
                                       inputContext,
 | 
						|
                                       encoding);
 | 
						|
          if (NULL != ctx)
 | 
						|
            {
 | 
						|
              ctx->userData = ctx;
 | 
						|
              
 | 
						|
              /* Set parsing options */
 | 
						|
              options = 0;
 | 
						|
              if (validate)
 | 
						|
                {
 | 
						|
                  options |= XML_PARSE_DTDVALID;
 | 
						|
                }
 | 
						|
              if (coalesce)
 | 
						|
                {
 | 
						|
                  options |= XML_PARSE_NOCDATA;
 | 
						|
                }
 | 
						|
              if (expandEntities)
 | 
						|
                {
 | 
						|
                  options |= XML_PARSE_NOENT;
 | 
						|
                }
 | 
						|
              if (loadEntities)
 | 
						|
                {
 | 
						|
                  options |= XML_PARSE_DTDLOAD;
 | 
						|
                }
 | 
						|
              if (xmlCtxtUseOptions (ctx, options))
 | 
						|
                {
 | 
						|
                  xmljThrowException (env,
 | 
						|
                                      "java/lang/RuntimeException",
 | 
						|
                                      "Unable to set xmlParserCtxtPtr options");
 | 
						|
                }
 | 
						|
              if (base != NULL)
 | 
						|
                {
 | 
						|
                  ctx->input->directory =
 | 
						|
                    (*env)->GetStringUTFChars (env, base, 0);
 | 
						|
                }
 | 
						|
              return ctx;
 | 
						|
            }
 | 
						|
          xmljFreeInputStreamContext (inputContext);
 | 
						|
        }
 | 
						|
    }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljFreeParserContext (xmlParserCtxtPtr ctx)
 | 
						|
{
 | 
						|
  InputStreamContext *inputStreamContext = NULL;
 | 
						|
 | 
						|
  if (ctx->input != NULL && ctx->input->buf != NULL)
 | 
						|
    {
 | 
						|
      inputStreamContext
 | 
						|
        = (InputStreamContext *) ctx->input->buf->context;
 | 
						|
      
 | 
						|
    }
 | 
						|
  xmlFreeParserCtxt (ctx);
 | 
						|
  if (inputStreamContext != NULL)
 | 
						|
    {
 | 
						|
      xmljFreeInputStreamContext (inputStreamContext);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
xmlDocPtr
 | 
						|
xmljParseDocument (JNIEnv * env,
 | 
						|
                   jobject self,
 | 
						|
                   jobject in,
 | 
						|
                   jbyteArray detectBuffer,
 | 
						|
                   jstring publicId,
 | 
						|
                   jstring systemId,
 | 
						|
                   jstring base,
 | 
						|
                   jboolean validate,
 | 
						|
                   jboolean coalesce,
 | 
						|
                   jboolean expandEntities,
 | 
						|
                   jboolean contentHandler,
 | 
						|
                   jboolean dtdHandler,
 | 
						|
                   jboolean entityResolver,
 | 
						|
                   jboolean errorHandler,
 | 
						|
                   jboolean declarationHandler,
 | 
						|
                   jboolean lexicalHandler,
 | 
						|
                   int mode)
 | 
						|
{
 | 
						|
  xmlParserCtxtPtr ctx;
 | 
						|
  SAXParseContext *saxCtx;
 | 
						|
  xmlSAXHandlerPtr sax;
 | 
						|
 | 
						|
  ctx = xmljNewParserContext (env, in, detectBuffer, publicId, systemId, base,
 | 
						|
                              validate, coalesce, expandEntities,
 | 
						|
                              entityResolver);
 | 
						|
  if (ctx != NULL)
 | 
						|
    {
 | 
						|
      saxCtx = xmljNewSAXParseContext (env, self, ctx, publicId, systemId);
 | 
						|
      if (saxCtx != NULL)
 | 
						|
        {
 | 
						|
          sax = xmljNewSAXHandler (contentHandler,
 | 
						|
                                   dtdHandler,
 | 
						|
                                   entityResolver,
 | 
						|
                                   errorHandler,
 | 
						|
                                   declarationHandler,
 | 
						|
                                   lexicalHandler);
 | 
						|
          if (sax != NULL)
 | 
						|
            {
 | 
						|
              return xmljParseDocument2 (env,
 | 
						|
                                         ctx,
 | 
						|
                                         saxCtx,
 | 
						|
                                         sax,
 | 
						|
                                         mode);
 | 
						|
            }
 | 
						|
          xmljFreeSAXParseContext (saxCtx);
 | 
						|
        }
 | 
						|
      xmljFreeParserContext (ctx);
 | 
						|
    }
 | 
						|
  if (!(*env)->ExceptionOccurred (env))
 | 
						|
    {
 | 
						|
      xmljThrowException (env, "java/io/IOException",
 | 
						|
                          "Unable to create parser context");
 | 
						|
    }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
xmlDocPtr
 | 
						|
xmljParseDocument2 (JNIEnv * env,
 | 
						|
                    xmlParserCtxtPtr ctx,
 | 
						|
                    SAXParseContext *saxCtx,
 | 
						|
                    xmlSAXHandlerPtr sax,
 | 
						|
                    int mode)
 | 
						|
{
 | 
						|
  xmlSAXHandlerPtr orig;
 | 
						|
  xmlDocPtr doc;
 | 
						|
  int ret;
 | 
						|
  
 | 
						|
  ctx->_private = saxCtx;
 | 
						|
  ctx->userData = ctx;
 | 
						|
  orig = ctx->sax;
 | 
						|
  ctx->sax = sax;
 | 
						|
  
 | 
						|
  xmljSetThreadContext (saxCtx);
 | 
						|
 | 
						|
  ret = xmlParseDocument (ctx);
 | 
						|
  doc = ctx->myDoc;
 | 
						|
  if (ret || !doc)
 | 
						|
    {
 | 
						|
      const char *msg = ctx->lastError.message;
 | 
						|
      switch (mode)
 | 
						|
        {
 | 
						|
        case 0:
 | 
						|
          xmljSAXFatalError (ctx, msg);
 | 
						|
          break;
 | 
						|
        case 1:
 | 
						|
          xmljThrowDOMException (env, ret, msg);
 | 
						|
          break;
 | 
						|
        case 2:
 | 
						|
          xmljThrowException (env,
 | 
						|
                              "javax/xml/transform/TransformerException",
 | 
						|
                              msg);
 | 
						|
        }
 | 
						|
    }
 | 
						|
  
 | 
						|
  xmljClearThreadContext ();
 | 
						|
              
 | 
						|
  ctx->sax = orig;
 | 
						|
  free(sax);
 | 
						|
  xmljFreeSAXParseContext (saxCtx);
 | 
						|
  xmljFreeParserContext (ctx);
 | 
						|
  xmljClearStringCache ();
 | 
						|
  return doc;
 | 
						|
}
 | 
						|
 | 
						|
xmlParserInputPtr
 | 
						|
xmljNewParserInput (JNIEnv * env,
 | 
						|
                    jobject inputStream,
 | 
						|
                    jbyteArray detectBuffer,
 | 
						|
                    xmlParserCtxtPtr parserContext)
 | 
						|
{
 | 
						|
  xmlParserInputPtr ret;
 | 
						|
  xmlParserInputBufferPtr input;
 | 
						|
  xmlCharEncoding encoding;
 | 
						|
 | 
						|
  encoding = xmljDetectCharEncoding (env, detectBuffer);
 | 
						|
  if (encoding != XML_CHAR_ENCODING_ERROR)
 | 
						|
    {
 | 
						|
      input = xmljNewParserInputBuffer (env, inputStream, encoding);
 | 
						|
      if (input != NULL)
 | 
						|
        {
 | 
						|
          ret = xmlNewIOInputStream (parserContext, input, encoding);
 | 
						|
          return ret;
 | 
						|
        }
 | 
						|
      xmlFreeParserInputBuffer (input);
 | 
						|
    }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
xmlParserInputBufferPtr
 | 
						|
xmljNewParserInputBuffer (JNIEnv * env,
 | 
						|
                          jobject inputStream, xmlCharEncoding encoding)
 | 
						|
{
 | 
						|
  xmlParserInputBufferPtr ret;
 | 
						|
  InputStreamContext *inputContext;
 | 
						|
 | 
						|
  inputContext = xmljNewInputStreamContext (env, inputStream);
 | 
						|
  if (NULL != inputContext)
 | 
						|
    {
 | 
						|
      ret = xmlParserInputBufferCreateIO (&xmljInputReadCallback,
 | 
						|
                                          &xmljInputCloseCallback,
 | 
						|
                                          inputContext, encoding);
 | 
						|
      if (ret != NULL)
 | 
						|
        return ret;
 | 
						|
      xmljFreeInputStreamContext (inputContext);
 | 
						|
    }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljSaveFileToJavaOutputStream (JNIEnv * env, jobject outputStream,
 | 
						|
                                xmlDocPtr tree,
 | 
						|
                                const char *outputEncodingName)
 | 
						|
{
 | 
						|
  OutputStreamContext *outputContext =
 | 
						|
    xmljNewOutputStreamContext (env, outputStream);
 | 
						|
 | 
						|
  xmlCharEncoding outputEncoding = xmlParseCharEncoding (outputEncodingName);
 | 
						|
 | 
						|
  xmlOutputBufferPtr outputBuffer =
 | 
						|
    xmlOutputBufferCreateIO (xmljOutputWriteCallback,
 | 
						|
                             xmljOutputCloseCallback,
 | 
						|
                             outputContext,
 | 
						|
                             xmlGetCharEncodingHandler (outputEncoding));
 | 
						|
 | 
						|
  /* Write result to output stream */
 | 
						|
 | 
						|
  xmlSaveFileTo (outputBuffer, tree, outputEncodingName);
 | 
						|
 | 
						|
  xmljFreeOutputStreamContext (outputContext);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
jobject
 | 
						|
xmljResolveURI (SaxErrorContext * saxErrorContext,
 | 
						|
                const char *URL, const char *ID)
 | 
						|
{
 | 
						|
  JNIEnv *env = saxErrorContext->env;
 | 
						|
 | 
						|
  jstring hrefString = (*env)->NewStringUTF (env, URL);
 | 
						|
  jstring baseString = saxErrorContext->systemId;
 | 
						|
 | 
						|
  jobject sourceWrapper = (*env)->CallObjectMethod (env,
 | 
						|
                                                    saxErrorContext->
 | 
						|
                                                    saxErrorAdapter,
 | 
						|
                                                    saxErrorContext->
 | 
						|
                                                    resolveURIMethodID,
 | 
						|
                                                    hrefString,
 | 
						|
                                                    baseString);
 | 
						|
  (*env)->DeleteLocalRef (env, hrefString);
 | 
						|
 | 
						|
  if (NULL == sourceWrapper)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      jobject sourceInputStream = (*env)->CallObjectMethod (env,
 | 
						|
                                                            sourceWrapper,
 | 
						|
                                                            saxErrorContext->
 | 
						|
                                                            getInputStreamMethodID);
 | 
						|
 | 
						|
      (*env)->DeleteLocalRef (env, sourceWrapper);
 | 
						|
 | 
						|
      if ((*env)->ExceptionOccurred (env))
 | 
						|
        {
 | 
						|
          -* Report to ErrorAdapter here? *-
 | 
						|
          return NULL;
 | 
						|
        }
 | 
						|
 | 
						|
      return sourceInputStream;
 | 
						|
    }
 | 
						|
}*/
 | 
						|
 | 
						|
xmlDocPtr
 | 
						|
xmljResolveURIAndOpen (SAXParseContext *saxContext,
 | 
						|
                       const char *URL,
 | 
						|
                       const char *ID)
 | 
						|
{
 | 
						|
  jobject libxmlDocument;
 | 
						|
  xmlDocPtr doc;
 | 
						|
  JNIEnv *env = saxContext->env;
 | 
						|
 | 
						|
  jstring hrefString = (*env)->NewStringUTF (env, URL);
 | 
						|
  jstring baseString = saxContext->systemId;
 | 
						|
 | 
						|
  if (saxContext->resolveURIAndOpen == NULL)
 | 
						|
    {
 | 
						|
      jclass cls = (*env)->GetObjectClass (env, saxContext->obj);
 | 
						|
      saxContext->resolveURIAndOpen =
 | 
						|
        (*env)->GetMethodID (env, cls, "resolveURIAndOpen",
 | 
						|
                             "Ljava/lang/String;Ljava/lang/String)Lgnu/xml/libxmlj/transform/LibxmlDocument;");
 | 
						|
    }
 | 
						|
  libxmlDocument =
 | 
						|
    (*env)->CallObjectMethod (env,
 | 
						|
                              saxContext->obj,
 | 
						|
                              saxContext->resolveURIAndOpen,
 | 
						|
                              hrefString,
 | 
						|
                              baseString);
 | 
						|
 | 
						|
  doc = (xmlDocPtr) xmljGetNodeID (env, libxmlDocument);
 | 
						|
 | 
						|
  (*env)->DeleteLocalRef (env, libxmlDocument);
 | 
						|
 | 
						|
  if ((*env)->ExceptionOccurred (env))
 | 
						|
    {
 | 
						|
      /* Report to ErrorAdapter here? */
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      return doc;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*xmlParserInputPtr
 | 
						|
xmljLoadExternalEntity (const char *URL, const char *ID,
 | 
						|
                        xmlParserCtxtPtr ctxt)
 | 
						|
{
 | 
						|
  SaxErrorContext *saxErrorContext = xmljGetThreadContext ();
 | 
						|
 | 
						|
  JNIEnv *env = saxErrorContext->env;
 | 
						|
 | 
						|
  jstring hrefString = (*env)->NewStringUTF (env, URL);
 | 
						|
  jstring baseString = saxErrorContext->systemId;
 | 
						|
 | 
						|
  jobject sourceWrapper = (*env)->CallObjectMethod (env,
 | 
						|
                                                    saxErrorContext->
 | 
						|
                                                    saxErrorAdapter,
 | 
						|
                                                    saxErrorContext->
 | 
						|
                                                    resolveURIMethodID,
 | 
						|
                                                    hrefString,
 | 
						|
                                                    baseString);
 | 
						|
 | 
						|
  (*env)->DeleteLocalRef (env, hrefString);
 | 
						|
 | 
						|
  if (NULL == sourceWrapper)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      InputStreamContext *inputContext;
 | 
						|
      xmlParserInputBufferPtr inputBuffer;
 | 
						|
      xmlParserInputPtr inputStream;
 | 
						|
 | 
						|
      jobject sourceInputStream = (*env)->CallObjectMethod (env,
 | 
						|
                                                            sourceWrapper,
 | 
						|
                                                            saxErrorContext->
 | 
						|
                                                            getInputStreamMethodID);
 | 
						|
 | 
						|
      (*env)->DeleteLocalRef (env, sourceWrapper);
 | 
						|
 | 
						|
      if ((*env)->ExceptionOccurred (env))
 | 
						|
        {
 | 
						|
          -* Report to ErrorAdapter *-
 | 
						|
          return NULL;
 | 
						|
        }
 | 
						|
 | 
						|
      inputContext = xmljNewInputStreamContext (env, sourceInputStream);
 | 
						|
 | 
						|
      inputBuffer
 | 
						|
        = xmlParserInputBufferCreateIO (xmljInputReadCallback,
 | 
						|
                                        xmljInputCloseCallback,
 | 
						|
                                        inputContext, XML_CHAR_ENCODING_NONE);
 | 
						|
 | 
						|
      inputStream = xmlNewInputStream (ctxt);
 | 
						|
      if (inputStream == NULL)
 | 
						|
        {
 | 
						|
          return (NULL);
 | 
						|
        }
 | 
						|
 | 
						|
      inputStream->filename = NULL;
 | 
						|
      inputStream->directory = NULL;
 | 
						|
      inputStream->buf = inputBuffer;
 | 
						|
 | 
						|
      inputStream->base = GET_XML_OUTPUT_BUFFER_CONTENT (inputStream->buf);
 | 
						|
      inputStream->cur = GET_XML_OUTPUT_BUFFER_CONTENT (inputStream->buf);
 | 
						|
      inputStream->end =
 | 
						|
      &inputStream->base[GET_XML_OUTPUT_BUFFER_SIZE (inputStream->buf)];
 | 
						|
      if ((ctxt->directory == NULL) && (inputStream->directory != NULL))
 | 
						|
        ctxt->directory =
 | 
						|
          (char *) xmlStrdup ((const xmlChar *) inputStream->directory);
 | 
						|
      return (inputStream);
 | 
						|
    }
 | 
						|
}*/
 | 
						|
 | 
						|
/* Key for the thread-specific buffer */
 | 
						|
static pthread_key_t thread_context_key;
 | 
						|
 | 
						|
/* Once-only initialisation of the key */
 | 
						|
static pthread_once_t thread_context_once = PTHREAD_ONCE_INIT;
 | 
						|
 | 
						|
static void
 | 
						|
thread_context_key_alloc (void);
 | 
						|
 | 
						|
/* Allocate the key */
 | 
						|
static void
 | 
						|
thread_context_key_alloc ()
 | 
						|
{
 | 
						|
  pthread_key_create (&thread_context_key, NULL);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljSetThreadContext (SAXParseContext * context)
 | 
						|
{
 | 
						|
  pthread_once (&thread_context_once, thread_context_key_alloc);
 | 
						|
  pthread_setspecific (thread_context_key, context);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
xmljClearThreadContext (void)
 | 
						|
{
 | 
						|
  pthread_setspecific (thread_context_key, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/* Return the thread-specific buffer */
 | 
						|
SAXParseContext *
 | 
						|
xmljGetThreadContext (void)
 | 
						|
{
 | 
						|
  return (SAXParseContext *) pthread_getspecific (thread_context_key);
 | 
						|
}
 |