f911ba985a
From-SVN: r102074
1446 lines
36 KiB
C
1446 lines
36 KiB
C
/* xmlj_sax.c -
|
|
Copyright (C) 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_sax.h"
|
|
#include "xmlj_io.h"
|
|
#include "xmlj_util.h"
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
xmlExternalEntityLoader defaultLoader = NULL;
|
|
|
|
void
|
|
xmljDispatchError (xmlParserCtxtPtr ctx,
|
|
xmlSAXLocatorPtr loc,
|
|
JNIEnv *env,
|
|
jobject target,
|
|
jmethodID method,
|
|
const char *msg,
|
|
va_list args);
|
|
|
|
/* -- GnomeLocator -- */
|
|
|
|
JNIEXPORT jstring JNICALL
|
|
Java_gnu_xml_libxmlj_sax_GnomeLocator_publicId (JNIEnv * env,
|
|
jobject self
|
|
__attribute__((__unused__)),
|
|
jobject j_ctx,
|
|
jobject j_loc)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
xmlSAXLocatorPtr loc;
|
|
SAXParseContext *sax;
|
|
|
|
ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
|
|
loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
|
|
return sax->publicId;
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL
|
|
Java_gnu_xml_libxmlj_sax_GnomeLocator_systemId (JNIEnv * env,
|
|
jobject self
|
|
__attribute__((__unused__)),
|
|
jobject j_ctx,
|
|
jobject j_loc)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
xmlSAXLocatorPtr loc;
|
|
SAXParseContext *sax;
|
|
|
|
ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
|
|
loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
|
|
return sax->systemId;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_gnu_xml_libxmlj_sax_GnomeLocator_lineNumber (JNIEnv * env,
|
|
jobject self
|
|
__attribute__((__unused__)),
|
|
jobject j_ctx,
|
|
jobject j_loc)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
xmlSAXLocatorPtr loc;
|
|
|
|
ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
|
|
loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
|
|
if (ctx == NULL || ctx->input == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
return ctx->input->line;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_gnu_xml_libxmlj_sax_GnomeLocator_columnNumber (JNIEnv * env,
|
|
jobject self
|
|
__attribute__((__unused__)),
|
|
jobject j_ctx,
|
|
jobject j_loc)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
xmlSAXLocatorPtr loc;
|
|
|
|
ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
|
|
loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
|
|
if (ctx == NULL || ctx->input == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
return ctx->input->col;
|
|
}
|
|
|
|
/* -- GnomeXMLReader -- */
|
|
|
|
/*
|
|
* Entry point for SAX parsing.
|
|
*/
|
|
JNIEXPORT void JNICALL
|
|
Java_gnu_xml_libxmlj_sax_GnomeXMLReader_parseStream (JNIEnv * env,
|
|
jobject self,
|
|
jobject in,
|
|
jbyteArray detectBuffer,
|
|
jstring publicId,
|
|
jstring systemId,
|
|
jstring base,
|
|
jboolean validate,
|
|
jboolean contentHandler,
|
|
jboolean dtdHandler,
|
|
jboolean entityResolver,
|
|
jboolean errorHandler,
|
|
jboolean
|
|
declarationHandler,
|
|
jboolean lexicalHandler)
|
|
{
|
|
xmljParseDocument (env,
|
|
self,
|
|
in,
|
|
detectBuffer,
|
|
publicId,
|
|
systemId,
|
|
base,
|
|
validate,
|
|
0,
|
|
0,
|
|
contentHandler,
|
|
dtdHandler,
|
|
entityResolver,
|
|
errorHandler,
|
|
declarationHandler,
|
|
lexicalHandler,
|
|
0);
|
|
}
|
|
|
|
xmlParserInputPtr
|
|
xmljExternalEntityLoader (const char *url, const char *id,
|
|
xmlParserCtxtPtr ctx)
|
|
{
|
|
const xmlChar *systemId;
|
|
const xmlChar *publicId;
|
|
xmlParserInputPtr ret;
|
|
|
|
systemId = xmlCharStrdup (url);
|
|
publicId = xmlCharStrdup (id);
|
|
/* TODO convert systemId to absolute URI */
|
|
ret = xmljSAXResolveEntity (ctx, publicId, systemId);
|
|
if (ret == NULL)
|
|
{
|
|
ret = defaultLoader (url, id, ctx);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Allocates and configures a SAX handler that can report the various
|
|
* classes of callback.
|
|
*/
|
|
xmlSAXHandlerPtr
|
|
xmljNewSAXHandler (jboolean contentHandler,
|
|
jboolean dtdHandler,
|
|
jboolean entityResolver,
|
|
jboolean errorHandler,
|
|
jboolean declarationHandler,
|
|
jboolean lexicalHandler)
|
|
{
|
|
xmlSAXHandlerPtr sax;
|
|
|
|
sax = (xmlSAXHandlerPtr) malloc (sizeof (xmlSAXHandler));
|
|
if (sax == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
memset (sax, 0, sizeof (xmlSAXHandler));
|
|
xmlSAXVersion (sax, 1); /* TODO SAX2 */
|
|
|
|
if (dtdHandler)
|
|
{
|
|
sax->internalSubset = &xmljSAXInternalSubset;
|
|
}
|
|
if (defaultLoader == NULL)
|
|
{
|
|
defaultLoader = xmlGetExternalEntityLoader ();
|
|
xmlSetExternalEntityLoader (xmljExternalEntityLoader);
|
|
}
|
|
if (entityResolver)
|
|
{
|
|
sax->resolveEntity = &xmljSAXResolveEntity;
|
|
}
|
|
|
|
if (declarationHandler)
|
|
{
|
|
sax->entityDecl = &xmljSAXEntityDecl;
|
|
sax->notationDecl = &xmljSAXNotationDecl;
|
|
sax->attributeDecl = &xmljSAXAttributeDecl;
|
|
sax->elementDecl = &xmljSAXElementDecl;
|
|
sax->unparsedEntityDecl = &xmljSAXUnparsedEntityDecl;
|
|
}
|
|
|
|
/* We always listen for the locator callback */
|
|
sax->setDocumentLocator = &xmljSAXSetDocumentLocator;
|
|
if (contentHandler)
|
|
{
|
|
sax->startDocument = &xmljSAXStartDocument;
|
|
sax->endDocument = &xmljSAXEndDocument;
|
|
sax->startElement = &xmljSAXStartElement;
|
|
sax->endElement = &xmljSAXEndElement;
|
|
sax->characters = &xmljSAXCharacters;
|
|
sax->ignorableWhitespace = &xmljSAXIgnorableWhitespace;
|
|
sax->processingInstruction = &xmljSAXProcessingInstruction;
|
|
}
|
|
|
|
/* We always intercept getEntity */
|
|
/* TODO this should only be if lexicalHandler */
|
|
sax->getEntity = &xmljSAXGetEntity;
|
|
if (lexicalHandler)
|
|
{
|
|
sax->getEntity = &xmljSAXGetEntity;
|
|
sax->reference = &xmljSAXReference;
|
|
sax->comment = &xmljSAXComment;
|
|
sax->cdataBlock = &xmljSAXCDataBlock;
|
|
}
|
|
else if (contentHandler)
|
|
{
|
|
sax->cdataBlock = &xmljSAXCharacters;
|
|
}
|
|
|
|
if (errorHandler)
|
|
{
|
|
sax->warning = &xmljSAXWarning;
|
|
sax->error = &xmljSAXError;
|
|
sax->fatalError = &xmljSAXFatalError;
|
|
}
|
|
|
|
return sax;
|
|
}
|
|
|
|
/* -- Callback functions -- */
|
|
|
|
void
|
|
xmljSAXInternalSubset (void *vctx,
|
|
const xmlChar * name,
|
|
const xmlChar * publicId, const xmlChar * systemId)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_name;
|
|
jstring j_publicId;
|
|
jstring j_systemId;
|
|
|
|
xmlSAX2InternalSubset (vctx, name, publicId, systemId);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->startDTD == NULL)
|
|
{
|
|
sax->startDTD =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"startDTD",
|
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->startDTD == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_name = xmljNewString (env, name);
|
|
j_publicId = xmljNewString (env, publicId);
|
|
j_systemId = xmljNewString (env, systemId);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->startDTD,
|
|
j_name,
|
|
j_publicId,
|
|
j_systemId);
|
|
}
|
|
|
|
xmlParserInputPtr
|
|
xmljSAXResolveEntity (void *vctx,
|
|
const xmlChar * publicId, const xmlChar * systemId)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_publicId;
|
|
jstring j_systemId;
|
|
jobject inputStream;
|
|
|
|
/* xmlSAX2ResolveEntity (vctx, publicId, systemId); */
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
if (ctx->_private == NULL)
|
|
{
|
|
/* Not in Kansas */
|
|
return NULL;
|
|
}
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (sax->resolveEntity == NULL)
|
|
{
|
|
sax->resolveEntity =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"resolveEntity",
|
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/io/InputStream;");
|
|
if (sax->resolveEntity == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
j_publicId = xmljNewString (env, publicId);
|
|
j_systemId = xmljNewString (env, systemId);
|
|
|
|
inputStream = (*env)->CallObjectMethod (env,
|
|
target,
|
|
sax->resolveEntity,
|
|
j_publicId,
|
|
j_systemId,
|
|
sax->systemId);
|
|
|
|
/* Return an xmlParserInputPtr corresponding to the input stream */
|
|
if (inputStream != NULL)
|
|
{
|
|
jbyteArray detectBuffer;
|
|
jmethodID getDetectBuffer;
|
|
|
|
/* Get the detect buffer from the NamedInputStream */
|
|
getDetectBuffer = xmljGetMethodID (env, inputStream, "getDetectBuffer",
|
|
"()[B");
|
|
if (getDetectBuffer == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
detectBuffer = (*env)->CallObjectMethod (env, inputStream,
|
|
getDetectBuffer);
|
|
|
|
return xmljNewParserInput (env, inputStream, detectBuffer, ctx);
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
xmlEntityPtr
|
|
xmljSAXGetEntity (void *vctx __attribute__((__unused__)), const xmlChar * name)
|
|
{
|
|
xmlEntityPtr ret;
|
|
|
|
/* TODO */
|
|
/* ret = xmlSAX2GetEntity (vctx, name); */
|
|
ret = NULL;
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
xmljSAXEntityDecl (void *vctx,
|
|
const xmlChar * name,
|
|
int type,
|
|
const xmlChar * publicId,
|
|
const xmlChar * systemId,
|
|
xmlChar * content)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_name;
|
|
jstring j_publicId;
|
|
jstring j_systemId;
|
|
jstring j_value;
|
|
|
|
xmlSAX2EntityDecl (vctx, name, type, publicId, systemId, content);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
j_name = xmljNewString (env, name);
|
|
switch (type)
|
|
{
|
|
case XML_INTERNAL_GENERAL_ENTITY:
|
|
case XML_INTERNAL_PARAMETER_ENTITY:
|
|
case XML_INTERNAL_PREDEFINED_ENTITY:
|
|
if (sax->internalEntityDecl == NULL)
|
|
{
|
|
sax->internalEntityDecl =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"internalEntityDecl",
|
|
"(Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->internalEntityDecl == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
j_value = xmljNewString (env, content);
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->internalEntityDecl,
|
|
j_name,
|
|
j_value);
|
|
break;
|
|
default:
|
|
if (sax->externalEntityDecl == NULL)
|
|
{
|
|
sax->externalEntityDecl =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"externalEntityDecl",
|
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->externalEntityDecl == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
j_publicId = xmljNewString (env, publicId);
|
|
j_systemId = xmljNewString (env, systemId);
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->externalEntityDecl,
|
|
j_name,
|
|
j_publicId,
|
|
j_systemId);
|
|
}
|
|
}
|
|
|
|
void
|
|
xmljSAXNotationDecl (void *vctx,
|
|
const xmlChar * name,
|
|
const xmlChar * publicId,
|
|
const xmlChar * systemId)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_name;
|
|
jstring j_publicId;
|
|
jstring j_systemId;
|
|
|
|
xmlSAX2NotationDecl (vctx, name, publicId, systemId);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->notationDecl == NULL)
|
|
{
|
|
sax->notationDecl =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"notationDecl",
|
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->notationDecl == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_name = xmljNewString (env, name);
|
|
j_publicId = xmljNewString (env, publicId);
|
|
j_systemId = xmljNewString (env, systemId);
|
|
|
|
/* Invoke the method */
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->notationDecl,
|
|
j_name,
|
|
j_publicId,
|
|
j_systemId);
|
|
}
|
|
|
|
void
|
|
xmljSAXAttributeDecl (void *vctx,
|
|
const xmlChar * elem,
|
|
const xmlChar * fullName,
|
|
int type,
|
|
int def,
|
|
const xmlChar * defaultValue,
|
|
xmlEnumerationPtr tree)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_eName;
|
|
jstring j_aName;
|
|
jstring j_type;
|
|
jstring j_mode;
|
|
jstring j_value;
|
|
|
|
xmlSAX2AttributeDecl (vctx, elem, fullName, type, def, defaultValue, tree);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->attributeDecl == NULL)
|
|
{
|
|
sax->attributeDecl =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"attributeDecl",
|
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->attributeDecl == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_eName = xmljNewString (env, elem);
|
|
j_aName = xmljNewString (env, fullName);
|
|
j_type = xmljAttributeTypeName (env, type);
|
|
j_mode = xmljAttributeModeName (env, def);
|
|
j_value = xmljNewString (env, defaultValue);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->attributeDecl,
|
|
j_eName,
|
|
j_aName,
|
|
j_type,
|
|
j_mode,
|
|
j_value);
|
|
}
|
|
|
|
void
|
|
xmljSAXElementDecl (void *vctx,
|
|
const xmlChar * name,
|
|
int type,
|
|
xmlElementContentPtr content)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_name;
|
|
jstring j_model;
|
|
|
|
xmlSAX2ElementDecl (vctx, name, type, content);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->elementDecl == NULL)
|
|
{
|
|
sax->elementDecl =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"elementDecl",
|
|
"(Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->elementDecl == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_name = xmljNewString (env, name);
|
|
j_model = NULL; /* TODO */
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->elementDecl,
|
|
j_name,
|
|
j_model);
|
|
}
|
|
|
|
void
|
|
xmljSAXUnparsedEntityDecl (void *vctx,
|
|
const xmlChar * name,
|
|
const xmlChar * publicId,
|
|
const xmlChar * systemId,
|
|
const xmlChar * notationName)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_name;
|
|
jstring j_publicId;
|
|
jstring j_systemId;
|
|
jstring j_notationName;
|
|
|
|
xmlSAX2UnparsedEntityDecl (vctx, name, publicId, systemId, notationName);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->unparsedEntityDecl == NULL)
|
|
{
|
|
sax->unparsedEntityDecl =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"unparsedEntityDecl",
|
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->unparsedEntityDecl == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_name = xmljNewString (env, name);
|
|
j_publicId = xmljNewString (env, publicId);
|
|
j_systemId = xmljNewString (env, systemId);
|
|
j_notationName = xmljNewString (env, notationName);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->unparsedEntityDecl,
|
|
j_name,
|
|
j_publicId,
|
|
j_systemId,
|
|
j_notationName);
|
|
}
|
|
|
|
void
|
|
xmljSAXSetDocumentLocator (void *vctx, xmlSAXLocatorPtr loc)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
|
|
xmlSAX2SetDocumentLocator (vctx, loc);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
if (target == NULL)
|
|
{
|
|
/* No Java parse context */
|
|
return;
|
|
}
|
|
|
|
/* Update locator on sax context */
|
|
sax->loc = loc;
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->setDocumentLocator == NULL)
|
|
{
|
|
sax->setDocumentLocator = xmljGetMethodID (env,
|
|
target,
|
|
"setDocumentLocator",
|
|
"(Ljava/lang/Object;Ljava/lang/Object;)V");
|
|
if (sax->setDocumentLocator == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->setDocumentLocator,
|
|
xmljAsField (env, ctx),
|
|
xmljAsField (env, loc));
|
|
}
|
|
|
|
void
|
|
xmljSAXStartDocument (void *vctx)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
|
|
xmlSAX2StartDocument (vctx);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->startDocument == NULL)
|
|
{
|
|
sax->startDocument = xmljGetMethodID (env,
|
|
target,
|
|
"startDocument",
|
|
"(Z)V");
|
|
if (sax->startDocument == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->startDocument,
|
|
ctx->standalone);
|
|
}
|
|
|
|
void
|
|
xmljSAXEndDocument (void *vctx)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
|
|
xmlSAX2EndDocument (vctx);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->endDocument == NULL)
|
|
{
|
|
sax->endDocument = xmljGetMethodID (env,
|
|
target,
|
|
"endDocument",
|
|
"()V");
|
|
if (sax->endDocument == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->endDocument);
|
|
}
|
|
|
|
void
|
|
xmljSAXStartElement (void *vctx,
|
|
const xmlChar * name,
|
|
const xmlChar ** attrs)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_name;
|
|
jobjectArray j_attrs;
|
|
jstring j_attr;
|
|
jsize len;
|
|
|
|
xmlSAX2StartElement (vctx, name, attrs);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->startElement == NULL)
|
|
{
|
|
sax->startElement =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"startElement",
|
|
"(Ljava/lang/String;[Ljava/lang/String;)V");
|
|
if (sax->startElement == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_name = xmljNewString (env, name);
|
|
/* build attributes array */
|
|
len = 0;
|
|
for (len = 0; attrs && attrs[len]; len++)
|
|
{
|
|
}
|
|
if (len)
|
|
{
|
|
if (sax->stringClass == NULL)
|
|
{
|
|
sax->stringClass = (*env)->FindClass (env, "java/lang/String");
|
|
if (sax->stringClass == NULL)
|
|
{
|
|
fprintf (stderr, "Can't find java.lang.String class!\n");
|
|
return;
|
|
}
|
|
}
|
|
j_attrs = (*env)->NewObjectArray (env, len, sax->stringClass, NULL);
|
|
if (j_attrs == NULL)
|
|
{
|
|
fprintf (stderr, "Can't allocate attributes array!\n");
|
|
return;
|
|
}
|
|
len = 0;
|
|
for (len = 0; attrs && attrs[len]; len++)
|
|
{
|
|
j_attr = xmljNewString (env, attrs[len]);
|
|
(*env)->SetObjectArrayElement (env, j_attrs, len, j_attr);
|
|
}
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->startElement,
|
|
j_name,
|
|
j_attrs);
|
|
(*env)->DeleteLocalRef (env, j_attrs);
|
|
}
|
|
else
|
|
{
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->startElement,
|
|
j_name,
|
|
NULL);
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
xmljSAXEndElement (void *vctx,
|
|
const xmlChar * name)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_name;
|
|
|
|
xmlSAX2EndElement (vctx, name);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->endElement == NULL)
|
|
{
|
|
sax->endElement = xmljGetMethodID (env,
|
|
target,
|
|
"endElement",
|
|
"(Ljava/lang/String;)V");
|
|
if (sax->endElement == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_name = xmljNewString (env, name);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->endElement,
|
|
j_name);
|
|
}
|
|
|
|
void
|
|
xmljSAXReference (void *vctx,
|
|
const xmlChar * name)
|
|
{
|
|
xmlSAX2Reference (vctx, name);
|
|
}
|
|
|
|
void
|
|
xmljSAXCharacters (void *vctx,
|
|
const xmlChar * ch,
|
|
int len)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_ch;
|
|
xmlChar *dup;
|
|
|
|
xmlSAX2Characters (vctx, ch, len);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->characters == NULL)
|
|
{
|
|
sax->characters = xmljGetMethodID (env,
|
|
target,
|
|
"characters",
|
|
"(Ljava/lang/String;)V");
|
|
if (sax->characters == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
dup = xmlStrndup (ch, len);
|
|
j_ch = xmljNewString (env, dup);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->characters,
|
|
j_ch);
|
|
xmlFree (dup);
|
|
}
|
|
|
|
void
|
|
xmljSAXIgnorableWhitespace (void *vctx,
|
|
const xmlChar * ch,
|
|
int len)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_ch;
|
|
xmlChar *dup;
|
|
|
|
xmlSAX2IgnorableWhitespace (vctx, ch, len);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->ignorableWhitespace == NULL)
|
|
{
|
|
sax->ignorableWhitespace = xmljGetMethodID (env,
|
|
target,
|
|
"ignorableWhitespace",
|
|
"(Ljava/lang/String;)V");
|
|
if (sax->ignorableWhitespace == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
dup = xmlStrndup (ch, len);
|
|
j_ch = xmljNewString (env, dup);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->ignorableWhitespace,
|
|
j_ch);
|
|
xmlFree (dup);
|
|
}
|
|
|
|
void
|
|
xmljSAXProcessingInstruction (void *vctx,
|
|
const xmlChar * targ,
|
|
const xmlChar * data)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_targ;
|
|
jstring j_data;
|
|
|
|
xmlSAX2ProcessingInstruction (vctx, targ, data);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->processingInstruction == NULL)
|
|
{
|
|
sax->processingInstruction =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"processingInstruction",
|
|
"(Ljava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->processingInstruction == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_targ = xmljNewString (env, targ);
|
|
j_data = xmljNewString (env, data);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->processingInstruction,
|
|
j_targ,
|
|
j_data);
|
|
}
|
|
|
|
void
|
|
xmljSAXComment (void *vctx,
|
|
const xmlChar * value)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_text;
|
|
|
|
xmlSAX2Comment (vctx, value);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->comment == NULL)
|
|
{
|
|
sax->comment =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"comment",
|
|
"(Ljava/lang/String;)V");
|
|
if (sax->comment == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
j_text = xmljNewString (env, value);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->comment,
|
|
j_text);
|
|
}
|
|
|
|
void
|
|
xmljSAXCDataBlock (void *vctx,
|
|
const xmlChar * ch,
|
|
int len)
|
|
{
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
jstring j_ch;
|
|
xmlChar *dup;
|
|
|
|
xmlSAX2CDataBlock (vctx, ch, len);
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
xmljCheckWellFormed (ctx);
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sax->cdataBlock == NULL)
|
|
{
|
|
sax->cdataBlock =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"cdataBlock",
|
|
"(Ljava/lang/String;)V");
|
|
if (sax->cdataBlock == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
dup = xmlStrndup (ch, len);
|
|
j_ch = xmljNewString (env, dup);
|
|
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
sax->cdataBlock,
|
|
j_ch);
|
|
xmlFree (dup);
|
|
}
|
|
|
|
void
|
|
xmljDispatchError (xmlParserCtxtPtr ctx,
|
|
xmlSAXLocatorPtr loc,
|
|
JNIEnv *env,
|
|
jobject target,
|
|
jmethodID method,
|
|
const char *msg,
|
|
va_list args)
|
|
{
|
|
jint lineNumber;
|
|
jint columnNumber;
|
|
jstring publicId;
|
|
jstring systemId;
|
|
char buffer[2048] = "";
|
|
|
|
if (msg != NULL)
|
|
{
|
|
vsnprintf (buffer, sizeof buffer, msg, args);
|
|
}
|
|
lineNumber = loc->getLineNumber (ctx);
|
|
columnNumber = loc->getColumnNumber (ctx);
|
|
publicId = xmljNewString (env, loc->getPublicId (ctx));
|
|
systemId = xmljNewString (env, loc->getSystemId (ctx));
|
|
(*env)->CallVoidMethod (env,
|
|
target,
|
|
method,
|
|
(*env)->NewStringUTF (env, buffer),
|
|
lineNumber,
|
|
columnNumber,
|
|
publicId,
|
|
systemId);
|
|
}
|
|
|
|
void
|
|
xmljSAXWarning (void *vctx,
|
|
const char *msg,
|
|
...)
|
|
{
|
|
va_list args;
|
|
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
xmlSAXLocatorPtr loc;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
loc = (xmlSAXLocatorPtr) sax->loc;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
if (sax->warning == NULL)
|
|
{
|
|
sax->warning =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"warning",
|
|
"(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->warning == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
va_start (args, msg);
|
|
/* xmlParserWarning (vctx, msg, args); */
|
|
xmljDispatchError (ctx, loc, env, target, sax->warning, msg, args);
|
|
va_end (args);
|
|
}
|
|
|
|
void
|
|
xmljSAXError (void *vctx,
|
|
const char *msg,
|
|
...)
|
|
{
|
|
va_list args;
|
|
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
xmlSAXLocatorPtr loc;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
loc = (xmlSAXLocatorPtr) sax->loc;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
if (sax->error == NULL)
|
|
{
|
|
sax->error =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"error",
|
|
"(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->error == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
va_start (args, msg);
|
|
/* xmlParserError (vctx, msg, args); */
|
|
xmljDispatchError (ctx, loc, env, target, sax->error, msg, args);
|
|
va_end (args);
|
|
}
|
|
|
|
void
|
|
xmljSAXFatalError (void *vctx,
|
|
const char *msg,
|
|
...)
|
|
{
|
|
va_list args;
|
|
|
|
xmlParserCtxtPtr ctx;
|
|
SAXParseContext *sax;
|
|
xmlSAXLocatorPtr loc;
|
|
JNIEnv *env;
|
|
jobject target;
|
|
|
|
ctx = (xmlParserCtxtPtr) vctx;
|
|
sax = (SAXParseContext *) ctx->_private;
|
|
loc = (xmlSAXLocatorPtr) sax->loc;
|
|
env = sax->env;
|
|
target = sax->obj;
|
|
|
|
if ((*env)->ExceptionOccurred (env))
|
|
{
|
|
return;
|
|
}
|
|
if (sax->fatalError == NULL)
|
|
{
|
|
sax->fatalError =
|
|
xmljGetMethodID (env,
|
|
target,
|
|
"fatalError",
|
|
"(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
|
|
if (sax->fatalError == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
va_start (args, msg);
|
|
/* xmlParserError (vctx, msg, args); */
|
|
xmljDispatchError (ctx, loc, env, target, sax->fatalError, msg, args);
|
|
va_end (args);
|
|
}
|
|
|
|
void
|
|
xmljCheckWellFormed (xmlParserCtxtPtr ctx)
|
|
{
|
|
if (!ctx->wellFormed)
|
|
{
|
|
xmljSAXFatalError (ctx, "document is not well-formed");
|
|
}
|
|
if (ctx->validate && !ctx->valid)
|
|
{
|
|
xmljSAXFatalError (ctx, "document is not valid");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Convert a libxml2 attribute type to a string.
|
|
*/
|
|
jstring
|
|
xmljAttributeTypeName (JNIEnv * env, int type)
|
|
{
|
|
const char *text;
|
|
|
|
switch (type)
|
|
{
|
|
case XML_ATTRIBUTE_CDATA:
|
|
text = "CDATA";
|
|
break;
|
|
case XML_ATTRIBUTE_ID:
|
|
text = "ID";
|
|
break;
|
|
case XML_ATTRIBUTE_IDREF:
|
|
text = "IDREF";
|
|
break;
|
|
case XML_ATTRIBUTE_IDREFS:
|
|
text = "IDREFS";
|
|
break;
|
|
case XML_ATTRIBUTE_NMTOKEN:
|
|
text = "NMTOKEN";
|
|
break;
|
|
case XML_ATTRIBUTE_NMTOKENS:
|
|
text = "NMTOKENS";
|
|
break;
|
|
case XML_ATTRIBUTE_ENTITY:
|
|
text = "ID";
|
|
break;
|
|
case XML_ATTRIBUTE_ENTITIES:
|
|
text = "ID";
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
return (*env)->NewStringUTF (env, text);
|
|
}
|
|
|
|
/*
|
|
* Convert a libxml2 attribute default value type to a string.
|
|
*/
|
|
jstring
|
|
xmljAttributeModeName (JNIEnv * env, int type)
|
|
{
|
|
const char *text;
|
|
|
|
switch (type)
|
|
{
|
|
case XML_ATTRIBUTE_IMPLIED:
|
|
text = "#IMPLIED";
|
|
break;
|
|
case XML_ATTRIBUTE_REQUIRED:
|
|
text = "#REQUIRED";
|
|
break;
|
|
case XML_ATTRIBUTE_FIXED:
|
|
text = "#FIXED";
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
return (*env)->NewStringUTF (env, text);
|
|
}
|