1 /* xmlj_sax.c -
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 #include "xmlj_sax.h"
39 #include "xmlj_io.h"
40 #include "xmlj_util.h"
41 #include <unistd.h>
42 #include <string.h>
43
44 xmlExternalEntityLoader defaultLoader = NULL;
45
46 void
47 xmljDispatchError (xmlParserCtxtPtr ctx,
48 xmlSAXLocatorPtr loc,
49 JNIEnv *env,
50 jobject target,
51 jmethodID method,
52 const char *msg,
53 va_list args);
54
55 /* -- GnomeLocator -- */
56
57 JNIEXPORT jstring JNICALL
Java_gnu_xml_libxmlj_sax_GnomeLocator_publicId(JNIEnv * env,jobject self,jobject j_ctx,jobject j_loc)58 Java_gnu_xml_libxmlj_sax_GnomeLocator_publicId (JNIEnv * env,
59 jobject self
60 __attribute__((__unused__)),
61 jobject j_ctx,
62 jobject j_loc)
63 {
64 xmlParserCtxtPtr ctx;
65 xmlSAXLocatorPtr loc;
66 SAXParseContext *sax;
67
68 ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
69 loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
70 sax = (SAXParseContext *) ctx->_private;
71
72 return sax->publicId;
73 }
74
75 JNIEXPORT jstring JNICALL
Java_gnu_xml_libxmlj_sax_GnomeLocator_systemId(JNIEnv * env,jobject self,jobject j_ctx,jobject j_loc)76 Java_gnu_xml_libxmlj_sax_GnomeLocator_systemId (JNIEnv * env,
77 jobject self
78 __attribute__((__unused__)),
79 jobject j_ctx,
80 jobject j_loc)
81 {
82 xmlParserCtxtPtr ctx;
83 xmlSAXLocatorPtr loc;
84 SAXParseContext *sax;
85
86 ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
87 loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
88 sax = (SAXParseContext *) ctx->_private;
89
90 return sax->systemId;
91 }
92
93 JNIEXPORT jint JNICALL
Java_gnu_xml_libxmlj_sax_GnomeLocator_lineNumber(JNIEnv * env,jobject self,jobject j_ctx,jobject j_loc)94 Java_gnu_xml_libxmlj_sax_GnomeLocator_lineNumber (JNIEnv * env,
95 jobject self
96 __attribute__((__unused__)),
97 jobject j_ctx,
98 jobject j_loc)
99 {
100 xmlParserCtxtPtr ctx;
101 xmlSAXLocatorPtr loc;
102
103 ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
104 loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
105 if (ctx == NULL || ctx->input == NULL)
106 {
107 return -1;
108 }
109 return ctx->input->line;
110 }
111
112 JNIEXPORT jint JNICALL
Java_gnu_xml_libxmlj_sax_GnomeLocator_columnNumber(JNIEnv * env,jobject self,jobject j_ctx,jobject j_loc)113 Java_gnu_xml_libxmlj_sax_GnomeLocator_columnNumber (JNIEnv * env,
114 jobject self
115 __attribute__((__unused__)),
116 jobject j_ctx,
117 jobject j_loc)
118 {
119 xmlParserCtxtPtr ctx;
120 xmlSAXLocatorPtr loc;
121
122 ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx);
123 loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc);
124 if (ctx == NULL || ctx->input == NULL)
125 {
126 return -1;
127 }
128 return ctx->input->col;
129 }
130
131 /* -- GnomeXMLReader -- */
132
133 /*
134 * Entry point for SAX parsing.
135 */
136 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)137 Java_gnu_xml_libxmlj_sax_GnomeXMLReader_parseStream (JNIEnv * env,
138 jobject self,
139 jobject in,
140 jbyteArray detectBuffer,
141 jstring publicId,
142 jstring systemId,
143 jstring base,
144 jboolean validate,
145 jboolean contentHandler,
146 jboolean dtdHandler,
147 jboolean entityResolver,
148 jboolean errorHandler,
149 jboolean
150 declarationHandler,
151 jboolean lexicalHandler)
152 {
153 xmljParseDocument (env,
154 self,
155 in,
156 detectBuffer,
157 publicId,
158 systemId,
159 base,
160 validate,
161 0,
162 0,
163 contentHandler,
164 dtdHandler,
165 entityResolver,
166 errorHandler,
167 declarationHandler,
168 lexicalHandler,
169 0);
170 }
171
172 xmlParserInputPtr
xmljExternalEntityLoader(const char * url,const char * id,xmlParserCtxtPtr ctx)173 xmljExternalEntityLoader (const char *url, const char *id,
174 xmlParserCtxtPtr ctx)
175 {
176 const xmlChar *systemId;
177 const xmlChar *publicId;
178 xmlParserInputPtr ret;
179
180 systemId = xmlCharStrdup (url);
181 publicId = xmlCharStrdup (id);
182 /* TODO convert systemId to absolute URI */
183 ret = xmljSAXResolveEntity (ctx, publicId, systemId);
184 if (ret == NULL)
185 {
186 ret = defaultLoader (url, id, ctx);
187 }
188 return ret;
189 }
190
191 /*
192 * Allocates and configures a SAX handler that can report the various
193 * classes of callback.
194 */
195 xmlSAXHandlerPtr
xmljNewSAXHandler(jboolean contentHandler,jboolean dtdHandler,jboolean entityResolver,jboolean errorHandler,jboolean declarationHandler,jboolean lexicalHandler)196 xmljNewSAXHandler (jboolean contentHandler,
197 jboolean dtdHandler,
198 jboolean entityResolver,
199 jboolean errorHandler,
200 jboolean declarationHandler,
201 jboolean lexicalHandler)
202 {
203 xmlSAXHandlerPtr sax;
204
205 sax = (xmlSAXHandlerPtr) malloc (sizeof (xmlSAXHandler));
206 if (sax == NULL)
207 {
208 return NULL;
209 }
210 memset (sax, 0, sizeof (xmlSAXHandler));
211 xmlSAXVersion (sax, 1); /* TODO SAX2 */
212
213 if (dtdHandler)
214 {
215 sax->internalSubset = &xmljSAXInternalSubset;
216 }
217 if (defaultLoader == NULL)
218 {
219 defaultLoader = xmlGetExternalEntityLoader ();
220 xmlSetExternalEntityLoader (xmljExternalEntityLoader);
221 }
222 if (entityResolver)
223 {
224 sax->resolveEntity = &xmljSAXResolveEntity;
225 }
226
227 if (declarationHandler)
228 {
229 sax->entityDecl = &xmljSAXEntityDecl;
230 sax->notationDecl = &xmljSAXNotationDecl;
231 sax->attributeDecl = &xmljSAXAttributeDecl;
232 sax->elementDecl = &xmljSAXElementDecl;
233 sax->unparsedEntityDecl = &xmljSAXUnparsedEntityDecl;
234 }
235
236 /* We always listen for the locator callback */
237 sax->setDocumentLocator = &xmljSAXSetDocumentLocator;
238 if (contentHandler)
239 {
240 sax->startDocument = &xmljSAXStartDocument;
241 sax->endDocument = &xmljSAXEndDocument;
242 sax->startElement = &xmljSAXStartElement;
243 sax->endElement = &xmljSAXEndElement;
244 sax->characters = &xmljSAXCharacters;
245 sax->ignorableWhitespace = &xmljSAXIgnorableWhitespace;
246 sax->processingInstruction = &xmljSAXProcessingInstruction;
247 }
248
249 /* We always intercept getEntity */
250 /* TODO this should only be if lexicalHandler */
251 sax->getEntity = &xmljSAXGetEntity;
252 if (lexicalHandler)
253 {
254 sax->getEntity = &xmljSAXGetEntity;
255 sax->reference = &xmljSAXReference;
256 sax->comment = &xmljSAXComment;
257 sax->cdataBlock = &xmljSAXCDataBlock;
258 }
259 else if (contentHandler)
260 {
261 sax->cdataBlock = &xmljSAXCharacters;
262 }
263
264 if (errorHandler)
265 {
266 sax->warning = &xmljSAXWarning;
267 sax->error = &xmljSAXError;
268 sax->fatalError = &xmljSAXFatalError;
269 }
270
271 return sax;
272 }
273
274 /* -- Callback functions -- */
275
276 void
xmljSAXInternalSubset(void * vctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)277 xmljSAXInternalSubset (void *vctx,
278 const xmlChar * name,
279 const xmlChar * publicId, const xmlChar * systemId)
280 {
281 xmlParserCtxtPtr ctx;
282 SAXParseContext *sax;
283 JNIEnv *env;
284 jobject target;
285 jstring j_name;
286 jstring j_publicId;
287 jstring j_systemId;
288
289 xmlSAX2InternalSubset (vctx, name, publicId, systemId);
290
291 ctx = (xmlParserCtxtPtr) vctx;
292 sax = (SAXParseContext *) ctx->_private;
293 env = sax->env;
294 target = sax->obj;
295
296 xmljCheckWellFormed (ctx);
297 if ((*env)->ExceptionOccurred (env))
298 {
299 return;
300 }
301
302 if (sax->startDTD == NULL)
303 {
304 sax->startDTD =
305 xmljGetMethodID (env,
306 target,
307 "startDTD",
308 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
309 if (sax->startDTD == NULL)
310 {
311 return;
312 }
313 }
314
315 j_name = xmljNewString (env, name);
316 j_publicId = xmljNewString (env, publicId);
317 j_systemId = xmljNewString (env, systemId);
318
319 (*env)->CallVoidMethod (env,
320 target,
321 sax->startDTD,
322 j_name,
323 j_publicId,
324 j_systemId);
325 }
326
327 xmlParserInputPtr
xmljSAXResolveEntity(void * vctx,const xmlChar * publicId,const xmlChar * systemId)328 xmljSAXResolveEntity (void *vctx,
329 const xmlChar * publicId, const xmlChar * systemId)
330 {
331 xmlParserCtxtPtr ctx;
332 SAXParseContext *sax;
333 JNIEnv *env;
334 jobject target;
335 jstring j_publicId;
336 jstring j_systemId;
337 jobject inputStream;
338
339 /* xmlSAX2ResolveEntity (vctx, publicId, systemId); */
340
341 ctx = (xmlParserCtxtPtr) vctx;
342 if (ctx->_private == NULL)
343 {
344 /* Not in Kansas */
345 return NULL;
346 }
347 sax = (SAXParseContext *) ctx->_private;
348 env = sax->env;
349 target = sax->obj;
350
351 if ((*env)->ExceptionOccurred (env))
352 {
353 return NULL;
354 }
355
356 if (sax->resolveEntity == NULL)
357 {
358 sax->resolveEntity =
359 xmljGetMethodID (env,
360 target,
361 "resolveEntity",
362 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/io/InputStream;");
363 if (sax->resolveEntity == NULL)
364 {
365 return NULL;
366 }
367 }
368
369 j_publicId = xmljNewString (env, publicId);
370 j_systemId = xmljNewString (env, systemId);
371
372 inputStream = (*env)->CallObjectMethod (env,
373 target,
374 sax->resolveEntity,
375 j_publicId,
376 j_systemId,
377 sax->systemId);
378
379 /* Return an xmlParserInputPtr corresponding to the input stream */
380 if (inputStream != NULL)
381 {
382 jbyteArray detectBuffer;
383 jmethodID getDetectBuffer;
384
385 /* Get the detect buffer from the NamedInputStream */
386 getDetectBuffer = xmljGetMethodID (env, inputStream, "getDetectBuffer",
387 "()[B");
388 if (getDetectBuffer == NULL)
389 {
390 return NULL;
391 }
392 detectBuffer = (*env)->CallObjectMethod (env, inputStream,
393 getDetectBuffer);
394
395 return xmljNewParserInput (env, inputStream, detectBuffer, ctx);
396 }
397 else
398 {
399 return NULL;
400 }
401 }
402
403 xmlEntityPtr
xmljSAXGetEntity(void * vctx,const xmlChar * name)404 xmljSAXGetEntity (void *vctx __attribute__((__unused__)), const xmlChar * name)
405 {
406 xmlEntityPtr ret;
407
408 /* TODO */
409 /* ret = xmlSAX2GetEntity (vctx, name); */
410 ret = NULL;
411 return ret;
412 }
413
414 void
xmljSAXEntityDecl(void * vctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)415 xmljSAXEntityDecl (void *vctx,
416 const xmlChar * name,
417 int type,
418 const xmlChar * publicId,
419 const xmlChar * systemId,
420 xmlChar * content)
421 {
422 xmlParserCtxtPtr ctx;
423 SAXParseContext *sax;
424 JNIEnv *env;
425 jobject target;
426 jstring j_name;
427 jstring j_publicId;
428 jstring j_systemId;
429 jstring j_value;
430
431 xmlSAX2EntityDecl (vctx, name, type, publicId, systemId, content);
432
433 ctx = (xmlParserCtxtPtr) vctx;
434 sax = (SAXParseContext *) ctx->_private;
435 env = sax->env;
436 target = sax->obj;
437
438 xmljCheckWellFormed (ctx);
439 if ((*env)->ExceptionOccurred (env))
440 {
441 return;
442 }
443
444 j_name = xmljNewString (env, name);
445 switch (type)
446 {
447 case XML_INTERNAL_GENERAL_ENTITY:
448 case XML_INTERNAL_PARAMETER_ENTITY:
449 case XML_INTERNAL_PREDEFINED_ENTITY:
450 if (sax->internalEntityDecl == NULL)
451 {
452 sax->internalEntityDecl =
453 xmljGetMethodID (env,
454 target,
455 "internalEntityDecl",
456 "(Ljava/lang/String;Ljava/lang/String;)V");
457 if (sax->internalEntityDecl == NULL)
458 {
459 return;
460 }
461 }
462 j_value = xmljNewString (env, content);
463 (*env)->CallVoidMethod (env,
464 target,
465 sax->internalEntityDecl,
466 j_name,
467 j_value);
468 break;
469 default:
470 if (sax->externalEntityDecl == NULL)
471 {
472 sax->externalEntityDecl =
473 xmljGetMethodID (env,
474 target,
475 "externalEntityDecl",
476 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
477 if (sax->externalEntityDecl == NULL)
478 {
479 return;
480 }
481 }
482 j_publicId = xmljNewString (env, publicId);
483 j_systemId = xmljNewString (env, systemId);
484 (*env)->CallVoidMethod (env,
485 target,
486 sax->externalEntityDecl,
487 j_name,
488 j_publicId,
489 j_systemId);
490 }
491 }
492
493 void
xmljSAXNotationDecl(void * vctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)494 xmljSAXNotationDecl (void *vctx,
495 const xmlChar * name,
496 const xmlChar * publicId,
497 const xmlChar * systemId)
498 {
499 xmlParserCtxtPtr ctx;
500 SAXParseContext *sax;
501 JNIEnv *env;
502 jobject target;
503 jstring j_name;
504 jstring j_publicId;
505 jstring j_systemId;
506
507 xmlSAX2NotationDecl (vctx, name, publicId, systemId);
508
509 ctx = (xmlParserCtxtPtr) vctx;
510 sax = (SAXParseContext *) ctx->_private;
511 env = sax->env;
512 target = sax->obj;
513
514 xmljCheckWellFormed (ctx);
515 if ((*env)->ExceptionOccurred (env))
516 {
517 return;
518 }
519
520 if (sax->notationDecl == NULL)
521 {
522 sax->notationDecl =
523 xmljGetMethodID (env,
524 target,
525 "notationDecl",
526 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
527 if (sax->notationDecl == NULL)
528 {
529 return;
530 }
531 }
532
533 j_name = xmljNewString (env, name);
534 j_publicId = xmljNewString (env, publicId);
535 j_systemId = xmljNewString (env, systemId);
536
537 /* Invoke the method */
538 (*env)->CallVoidMethod (env,
539 target,
540 sax->notationDecl,
541 j_name,
542 j_publicId,
543 j_systemId);
544 }
545
546 void
xmljSAXAttributeDecl(void * vctx,const xmlChar * elem,const xmlChar * fullName,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)547 xmljSAXAttributeDecl (void *vctx,
548 const xmlChar * elem,
549 const xmlChar * fullName,
550 int type,
551 int def,
552 const xmlChar * defaultValue,
553 xmlEnumerationPtr tree)
554 {
555 xmlParserCtxtPtr ctx;
556 SAXParseContext *sax;
557 JNIEnv *env;
558 jobject target;
559 jstring j_eName;
560 jstring j_aName;
561 jstring j_type;
562 jstring j_mode;
563 jstring j_value;
564
565 xmlSAX2AttributeDecl (vctx, elem, fullName, type, def, defaultValue, tree);
566
567 ctx = (xmlParserCtxtPtr) vctx;
568 sax = (SAXParseContext *) ctx->_private;
569 env = sax->env;
570 target = sax->obj;
571
572 xmljCheckWellFormed (ctx);
573 if ((*env)->ExceptionOccurred (env))
574 {
575 return;
576 }
577
578 if (sax->attributeDecl == NULL)
579 {
580 sax->attributeDecl =
581 xmljGetMethodID (env,
582 target,
583 "attributeDecl",
584 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
585 if (sax->attributeDecl == NULL)
586 {
587 return;
588 }
589 }
590
591 j_eName = xmljNewString (env, elem);
592 j_aName = xmljNewString (env, fullName);
593 j_type = xmljAttributeTypeName (env, type);
594 j_mode = xmljAttributeModeName (env, def);
595 j_value = xmljNewString (env, defaultValue);
596
597 (*env)->CallVoidMethod (env,
598 target,
599 sax->attributeDecl,
600 j_eName,
601 j_aName,
602 j_type,
603 j_mode,
604 j_value);
605 }
606
607 void
xmljSAXElementDecl(void * vctx,const xmlChar * name,int type,xmlElementContentPtr content)608 xmljSAXElementDecl (void *vctx,
609 const xmlChar * name,
610 int type,
611 xmlElementContentPtr content)
612 {
613 xmlParserCtxtPtr ctx;
614 SAXParseContext *sax;
615 JNIEnv *env;
616 jobject target;
617 jstring j_name;
618 jstring j_model;
619
620 xmlSAX2ElementDecl (vctx, name, type, content);
621
622 ctx = (xmlParserCtxtPtr) vctx;
623 sax = (SAXParseContext *) ctx->_private;
624 env = sax->env;
625 target = sax->obj;
626
627 xmljCheckWellFormed (ctx);
628 if ((*env)->ExceptionOccurred (env))
629 {
630 return;
631 }
632
633 if (sax->elementDecl == NULL)
634 {
635 sax->elementDecl =
636 xmljGetMethodID (env,
637 target,
638 "elementDecl",
639 "(Ljava/lang/String;Ljava/lang/String;)V");
640 if (sax->elementDecl == NULL)
641 {
642 return;
643 }
644 }
645
646 j_name = xmljNewString (env, name);
647 j_model = NULL; /* TODO */
648
649 (*env)->CallVoidMethod (env,
650 target,
651 sax->elementDecl,
652 j_name,
653 j_model);
654 }
655
656 void
xmljSAXUnparsedEntityDecl(void * vctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)657 xmljSAXUnparsedEntityDecl (void *vctx,
658 const xmlChar * name,
659 const xmlChar * publicId,
660 const xmlChar * systemId,
661 const xmlChar * notationName)
662 {
663 xmlParserCtxtPtr ctx;
664 SAXParseContext *sax;
665 JNIEnv *env;
666 jobject target;
667 jstring j_name;
668 jstring j_publicId;
669 jstring j_systemId;
670 jstring j_notationName;
671
672 xmlSAX2UnparsedEntityDecl (vctx, name, publicId, systemId, notationName);
673
674 ctx = (xmlParserCtxtPtr) vctx;
675 sax = (SAXParseContext *) ctx->_private;
676 env = sax->env;
677 target = sax->obj;
678
679 xmljCheckWellFormed (ctx);
680 if ((*env)->ExceptionOccurred (env))
681 {
682 return;
683 }
684
685 if (sax->unparsedEntityDecl == NULL)
686 {
687 sax->unparsedEntityDecl =
688 xmljGetMethodID (env,
689 target,
690 "unparsedEntityDecl",
691 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
692 if (sax->unparsedEntityDecl == NULL)
693 {
694 return;
695 }
696 }
697
698 j_name = xmljNewString (env, name);
699 j_publicId = xmljNewString (env, publicId);
700 j_systemId = xmljNewString (env, systemId);
701 j_notationName = xmljNewString (env, notationName);
702
703 (*env)->CallVoidMethod (env,
704 target,
705 sax->unparsedEntityDecl,
706 j_name,
707 j_publicId,
708 j_systemId,
709 j_notationName);
710 }
711
712 void
xmljSAXSetDocumentLocator(void * vctx,xmlSAXLocatorPtr loc)713 xmljSAXSetDocumentLocator (void *vctx, xmlSAXLocatorPtr loc)
714 {
715 xmlParserCtxtPtr ctx;
716 SAXParseContext *sax;
717 JNIEnv *env;
718 jobject target;
719
720 xmlSAX2SetDocumentLocator (vctx, loc);
721
722 ctx = (xmlParserCtxtPtr) vctx;
723 sax = (SAXParseContext *) ctx->_private;
724 env = sax->env;
725 target = sax->obj;
726
727 if (target == NULL)
728 {
729 /* No Java parse context */
730 return;
731 }
732
733 /* Update locator on sax context */
734 sax->loc = loc;
735 if ((*env)->ExceptionOccurred (env))
736 {
737 return;
738 }
739
740 if (sax->setDocumentLocator == NULL)
741 {
742 sax->setDocumentLocator = xmljGetMethodID (env,
743 target,
744 "setDocumentLocator",
745 "(Ljava/lang/Object;Ljava/lang/Object;)V");
746 if (sax->setDocumentLocator == NULL)
747 {
748 return;
749 }
750 }
751
752 (*env)->CallVoidMethod (env,
753 target,
754 sax->setDocumentLocator,
755 xmljAsField (env, ctx),
756 xmljAsField (env, loc));
757 }
758
759 void
xmljSAXStartDocument(void * vctx)760 xmljSAXStartDocument (void *vctx)
761 {
762 xmlParserCtxtPtr ctx;
763 SAXParseContext *sax;
764 JNIEnv *env;
765 jobject target;
766
767 xmlSAX2StartDocument (vctx);
768
769 ctx = (xmlParserCtxtPtr) vctx;
770 sax = (SAXParseContext *) ctx->_private;
771 env = sax->env;
772 target = sax->obj;
773
774 xmljCheckWellFormed (ctx);
775 if ((*env)->ExceptionOccurred (env))
776 {
777 return;
778 }
779
780 if (sax->startDocument == NULL)
781 {
782 sax->startDocument = xmljGetMethodID (env,
783 target,
784 "startDocument",
785 "(Z)V");
786 if (sax->startDocument == NULL)
787 {
788 return;
789 }
790 }
791
792 (*env)->CallVoidMethod (env,
793 target,
794 sax->startDocument,
795 ctx->standalone);
796 }
797
798 void
xmljSAXEndDocument(void * vctx)799 xmljSAXEndDocument (void *vctx)
800 {
801 xmlParserCtxtPtr ctx;
802 SAXParseContext *sax;
803 JNIEnv *env;
804 jobject target;
805
806 xmlSAX2EndDocument (vctx);
807
808 ctx = (xmlParserCtxtPtr) vctx;
809 sax = (SAXParseContext *) ctx->_private;
810 env = sax->env;
811 target = sax->obj;
812
813 xmljCheckWellFormed (ctx);
814 if ((*env)->ExceptionOccurred (env))
815 {
816 return;
817 }
818
819 if (sax->endDocument == NULL)
820 {
821 sax->endDocument = xmljGetMethodID (env,
822 target,
823 "endDocument",
824 "()V");
825 if (sax->endDocument == NULL)
826 {
827 return;
828 }
829 }
830
831 (*env)->CallVoidMethod (env,
832 target,
833 sax->endDocument);
834 }
835
836 void
xmljSAXStartElement(void * vctx,const xmlChar * name,const xmlChar ** attrs)837 xmljSAXStartElement (void *vctx,
838 const xmlChar * name,
839 const xmlChar ** attrs)
840 {
841 xmlParserCtxtPtr ctx;
842 SAXParseContext *sax;
843 JNIEnv *env;
844 jobject target;
845 jstring j_name;
846 jobjectArray j_attrs;
847 jstring j_attr;
848 jsize len;
849
850 xmlSAX2StartElement (vctx, name, attrs);
851
852 ctx = (xmlParserCtxtPtr) vctx;
853 sax = (SAXParseContext *) ctx->_private;
854 env = sax->env;
855 target = sax->obj;
856
857 xmljCheckWellFormed (ctx);
858 if ((*env)->ExceptionOccurred (env))
859 {
860 return;
861 }
862
863 if (sax->startElement == NULL)
864 {
865 sax->startElement =
866 xmljGetMethodID (env,
867 target,
868 "startElement",
869 "(Ljava/lang/String;[Ljava/lang/String;)V");
870 if (sax->startElement == NULL)
871 {
872 return;
873 }
874 }
875
876 j_name = xmljNewString (env, name);
877 /* build attributes array */
878 len = 0;
879 for (len = 0; attrs && attrs[len]; len++)
880 {
881 }
882 if (len)
883 {
884 if (sax->stringClass == NULL)
885 {
886 sax->stringClass = (*env)->FindClass (env, "java/lang/String");
887 if (sax->stringClass == NULL)
888 {
889 fprintf (stderr, "Can't find java.lang.String class!\n");
890 return;
891 }
892 }
893 j_attrs = (*env)->NewObjectArray (env, len, sax->stringClass, NULL);
894 if (j_attrs == NULL)
895 {
896 fprintf (stderr, "Can't allocate attributes array!\n");
897 return;
898 }
899 len = 0;
900 for (len = 0; attrs && attrs[len]; len++)
901 {
902 j_attr = xmljNewString (env, attrs[len]);
903 (*env)->SetObjectArrayElement (env, j_attrs, len, j_attr);
904 }
905
906 (*env)->CallVoidMethod (env,
907 target,
908 sax->startElement,
909 j_name,
910 j_attrs);
911 (*env)->DeleteLocalRef (env, j_attrs);
912 }
913 else
914 {
915 (*env)->CallVoidMethod (env,
916 target,
917 sax->startElement,
918 j_name,
919 NULL);
920
921 }
922 }
923
924 void
xmljSAXEndElement(void * vctx,const xmlChar * name)925 xmljSAXEndElement (void *vctx,
926 const xmlChar * name)
927 {
928 xmlParserCtxtPtr ctx;
929 SAXParseContext *sax;
930 JNIEnv *env;
931 jobject target;
932 jstring j_name;
933
934 xmlSAX2EndElement (vctx, name);
935
936 ctx = (xmlParserCtxtPtr) vctx;
937 sax = (SAXParseContext *) ctx->_private;
938 env = sax->env;
939 target = sax->obj;
940
941 xmljCheckWellFormed (ctx);
942 if ((*env)->ExceptionOccurred (env))
943 {
944 return;
945 }
946
947 if (sax->endElement == NULL)
948 {
949 sax->endElement = xmljGetMethodID (env,
950 target,
951 "endElement",
952 "(Ljava/lang/String;)V");
953 if (sax->endElement == NULL)
954 {
955 return;
956 }
957 }
958
959 j_name = xmljNewString (env, name);
960
961 (*env)->CallVoidMethod (env,
962 target,
963 sax->endElement,
964 j_name);
965 }
966
967 void
xmljSAXReference(void * vctx,const xmlChar * name)968 xmljSAXReference (void *vctx,
969 const xmlChar * name)
970 {
971 xmlSAX2Reference (vctx, name);
972 }
973
974 void
xmljSAXCharacters(void * vctx,const xmlChar * ch,int len)975 xmljSAXCharacters (void *vctx,
976 const xmlChar * ch,
977 int len)
978 {
979 xmlParserCtxtPtr ctx;
980 SAXParseContext *sax;
981 JNIEnv *env;
982 jobject target;
983 jstring j_ch;
984 xmlChar *dup;
985
986 xmlSAX2Characters (vctx, ch, len);
987
988 ctx = (xmlParserCtxtPtr) vctx;
989 sax = (SAXParseContext *) ctx->_private;
990 env = sax->env;
991 target = sax->obj;
992
993 xmljCheckWellFormed (ctx);
994 if ((*env)->ExceptionOccurred (env))
995 {
996 return;
997 }
998
999 if (sax->characters == NULL)
1000 {
1001 sax->characters = xmljGetMethodID (env,
1002 target,
1003 "characters",
1004 "(Ljava/lang/String;)V");
1005 if (sax->characters == NULL)
1006 {
1007 return;
1008 }
1009 }
1010
1011 dup = xmlStrndup (ch, len);
1012 j_ch = xmljNewString (env, dup);
1013
1014 (*env)->CallVoidMethod (env,
1015 target,
1016 sax->characters,
1017 j_ch);
1018 xmlFree (dup);
1019 }
1020
1021 void
xmljSAXIgnorableWhitespace(void * vctx,const xmlChar * ch,int len)1022 xmljSAXIgnorableWhitespace (void *vctx,
1023 const xmlChar * ch,
1024 int len)
1025 {
1026 xmlParserCtxtPtr ctx;
1027 SAXParseContext *sax;
1028 JNIEnv *env;
1029 jobject target;
1030 jstring j_ch;
1031 xmlChar *dup;
1032
1033 xmlSAX2IgnorableWhitespace (vctx, ch, len);
1034
1035 ctx = (xmlParserCtxtPtr) vctx;
1036 sax = (SAXParseContext *) ctx->_private;
1037 env = sax->env;
1038 target = sax->obj;
1039
1040 xmljCheckWellFormed (ctx);
1041 if ((*env)->ExceptionOccurred (env))
1042 {
1043 return;
1044 }
1045
1046 if (sax->ignorableWhitespace == NULL)
1047 {
1048 sax->ignorableWhitespace = xmljGetMethodID (env,
1049 target,
1050 "ignorableWhitespace",
1051 "(Ljava/lang/String;)V");
1052 if (sax->ignorableWhitespace == NULL)
1053 {
1054 return;
1055 }
1056 }
1057
1058 dup = xmlStrndup (ch, len);
1059 j_ch = xmljNewString (env, dup);
1060
1061 (*env)->CallVoidMethod (env,
1062 target,
1063 sax->ignorableWhitespace,
1064 j_ch);
1065 xmlFree (dup);
1066 }
1067
1068 void
xmljSAXProcessingInstruction(void * vctx,const xmlChar * targ,const xmlChar * data)1069 xmljSAXProcessingInstruction (void *vctx,
1070 const xmlChar * targ,
1071 const xmlChar * data)
1072 {
1073 xmlParserCtxtPtr ctx;
1074 SAXParseContext *sax;
1075 JNIEnv *env;
1076 jobject target;
1077 jstring j_targ;
1078 jstring j_data;
1079
1080 xmlSAX2ProcessingInstruction (vctx, targ, data);
1081
1082 ctx = (xmlParserCtxtPtr) vctx;
1083 sax = (SAXParseContext *) ctx->_private;
1084 env = sax->env;
1085 target = sax->obj;
1086
1087 xmljCheckWellFormed (ctx);
1088 if ((*env)->ExceptionOccurred (env))
1089 {
1090 return;
1091 }
1092
1093 if (sax->processingInstruction == NULL)
1094 {
1095 sax->processingInstruction =
1096 xmljGetMethodID (env,
1097 target,
1098 "processingInstruction",
1099 "(Ljava/lang/String;Ljava/lang/String;)V");
1100 if (sax->processingInstruction == NULL)
1101 {
1102 return;
1103 }
1104 }
1105
1106 j_targ = xmljNewString (env, targ);
1107 j_data = xmljNewString (env, data);
1108
1109 (*env)->CallVoidMethod (env,
1110 target,
1111 sax->processingInstruction,
1112 j_targ,
1113 j_data);
1114 }
1115
1116 void
xmljSAXComment(void * vctx,const xmlChar * value)1117 xmljSAXComment (void *vctx,
1118 const xmlChar * value)
1119 {
1120 xmlParserCtxtPtr ctx;
1121 SAXParseContext *sax;
1122 JNIEnv *env;
1123 jobject target;
1124 jstring j_text;
1125
1126 xmlSAX2Comment (vctx, value);
1127
1128 ctx = (xmlParserCtxtPtr) vctx;
1129 sax = (SAXParseContext *) ctx->_private;
1130 env = sax->env;
1131 target = sax->obj;
1132
1133 xmljCheckWellFormed (ctx);
1134 if ((*env)->ExceptionOccurred (env))
1135 {
1136 return;
1137 }
1138
1139 if (sax->comment == NULL)
1140 {
1141 sax->comment =
1142 xmljGetMethodID (env,
1143 target,
1144 "comment",
1145 "(Ljava/lang/String;)V");
1146 if (sax->comment == NULL)
1147 {
1148 return;
1149 }
1150 }
1151
1152 j_text = xmljNewString (env, value);
1153
1154 (*env)->CallVoidMethod (env,
1155 target,
1156 sax->comment,
1157 j_text);
1158 }
1159
1160 void
xmljSAXCDataBlock(void * vctx,const xmlChar * ch,int len)1161 xmljSAXCDataBlock (void *vctx,
1162 const xmlChar * ch,
1163 int len)
1164 {
1165 xmlParserCtxtPtr ctx;
1166 SAXParseContext *sax;
1167 JNIEnv *env;
1168 jobject target;
1169 jstring j_ch;
1170 xmlChar *dup;
1171
1172 xmlSAX2CDataBlock (vctx, ch, len);
1173
1174 ctx = (xmlParserCtxtPtr) vctx;
1175 sax = (SAXParseContext *) ctx->_private;
1176 env = sax->env;
1177 target = sax->obj;
1178
1179 xmljCheckWellFormed (ctx);
1180 if ((*env)->ExceptionOccurred (env))
1181 {
1182 return;
1183 }
1184
1185 if (sax->cdataBlock == NULL)
1186 {
1187 sax->cdataBlock =
1188 xmljGetMethodID (env,
1189 target,
1190 "cdataBlock",
1191 "(Ljava/lang/String;)V");
1192 if (sax->cdataBlock == NULL)
1193 {
1194 return;
1195 }
1196 }
1197
1198 dup = xmlStrndup (ch, len);
1199 j_ch = xmljNewString (env, dup);
1200
1201 (*env)->CallVoidMethod (env,
1202 target,
1203 sax->cdataBlock,
1204 j_ch);
1205 xmlFree (dup);
1206 }
1207
1208 void
xmljDispatchError(xmlParserCtxtPtr ctx,xmlSAXLocatorPtr loc,JNIEnv * env,jobject target,jmethodID method,const char * msg,va_list args)1209 xmljDispatchError (xmlParserCtxtPtr ctx,
1210 xmlSAXLocatorPtr loc,
1211 JNIEnv *env,
1212 jobject target,
1213 jmethodID method,
1214 const char *msg,
1215 va_list args)
1216 {
1217 jint lineNumber;
1218 jint columnNumber;
1219 jstring publicId;
1220 jstring systemId;
1221 char buffer[2048] = "";
1222
1223 if (msg != NULL)
1224 {
1225 vsnprintf (buffer, sizeof buffer, msg, args);
1226 }
1227 lineNumber = loc->getLineNumber (ctx);
1228 columnNumber = loc->getColumnNumber (ctx);
1229 publicId = xmljNewString (env, loc->getPublicId (ctx));
1230 systemId = xmljNewString (env, loc->getSystemId (ctx));
1231 (*env)->CallVoidMethod (env,
1232 target,
1233 method,
1234 (*env)->NewStringUTF (env, buffer),
1235 lineNumber,
1236 columnNumber,
1237 publicId,
1238 systemId);
1239 }
1240
1241 void
xmljSAXWarning(void * vctx,const char * msg,...)1242 xmljSAXWarning (void *vctx,
1243 const char *msg,
1244 ...)
1245 {
1246 va_list args;
1247
1248 xmlParserCtxtPtr ctx;
1249 SAXParseContext *sax;
1250 xmlSAXLocatorPtr loc;
1251 JNIEnv *env;
1252 jobject target;
1253
1254 ctx = (xmlParserCtxtPtr) vctx;
1255 sax = (SAXParseContext *) ctx->_private;
1256 loc = (xmlSAXLocatorPtr) sax->loc;
1257 env = sax->env;
1258 target = sax->obj;
1259
1260 if ((*env)->ExceptionOccurred (env))
1261 {
1262 return;
1263 }
1264 if (sax->warning == NULL)
1265 {
1266 sax->warning =
1267 xmljGetMethodID (env,
1268 target,
1269 "warning",
1270 "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
1271 if (sax->warning == NULL)
1272 {
1273 return;
1274 }
1275 }
1276
1277 va_start (args, msg);
1278 /* xmlParserWarning (vctx, msg, args); */
1279 xmljDispatchError (ctx, loc, env, target, sax->warning, msg, args);
1280 va_end (args);
1281 }
1282
1283 void
xmljSAXError(void * vctx,const char * msg,...)1284 xmljSAXError (void *vctx,
1285 const char *msg,
1286 ...)
1287 {
1288 va_list args;
1289
1290 xmlParserCtxtPtr ctx;
1291 SAXParseContext *sax;
1292 xmlSAXLocatorPtr loc;
1293 JNIEnv *env;
1294 jobject target;
1295
1296 ctx = (xmlParserCtxtPtr) vctx;
1297 sax = (SAXParseContext *) ctx->_private;
1298 loc = (xmlSAXLocatorPtr) sax->loc;
1299 env = sax->env;
1300 target = sax->obj;
1301
1302 if ((*env)->ExceptionOccurred (env))
1303 {
1304 return;
1305 }
1306 if (sax->error == NULL)
1307 {
1308 sax->error =
1309 xmljGetMethodID (env,
1310 target,
1311 "error",
1312 "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
1313 if (sax->error == NULL)
1314 {
1315 return;
1316 }
1317 }
1318
1319 va_start (args, msg);
1320 /* xmlParserError (vctx, msg, args); */
1321 xmljDispatchError (ctx, loc, env, target, sax->error, msg, args);
1322 va_end (args);
1323 }
1324
1325 void
xmljSAXFatalError(void * vctx,const char * msg,...)1326 xmljSAXFatalError (void *vctx,
1327 const char *msg,
1328 ...)
1329 {
1330 va_list args;
1331
1332 xmlParserCtxtPtr ctx;
1333 SAXParseContext *sax;
1334 xmlSAXLocatorPtr loc;
1335 JNIEnv *env;
1336 jobject target;
1337
1338 ctx = (xmlParserCtxtPtr) vctx;
1339 sax = (SAXParseContext *) ctx->_private;
1340 loc = (xmlSAXLocatorPtr) sax->loc;
1341 env = sax->env;
1342 target = sax->obj;
1343
1344 if ((*env)->ExceptionOccurred (env))
1345 {
1346 return;
1347 }
1348 if (sax->fatalError == NULL)
1349 {
1350 sax->fatalError =
1351 xmljGetMethodID (env,
1352 target,
1353 "fatalError",
1354 "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
1355 if (sax->fatalError == NULL)
1356 {
1357 return;
1358 }
1359 }
1360
1361 va_start (args, msg);
1362 /* xmlParserError (vctx, msg, args); */
1363 xmljDispatchError (ctx, loc, env, target, sax->fatalError, msg, args);
1364 va_end (args);
1365 }
1366
1367 void
xmljCheckWellFormed(xmlParserCtxtPtr ctx)1368 xmljCheckWellFormed (xmlParserCtxtPtr ctx)
1369 {
1370 if (!ctx->wellFormed)
1371 {
1372 xmljSAXFatalError (ctx, "document is not well-formed");
1373 }
1374 if (ctx->validate && !ctx->valid)
1375 {
1376 xmljSAXFatalError (ctx, "document is not valid");
1377 }
1378 }
1379
1380 /*
1381 * Convert a libxml2 attribute type to a string.
1382 */
1383 jstring
xmljAttributeTypeName(JNIEnv * env,int type)1384 xmljAttributeTypeName (JNIEnv * env, int type)
1385 {
1386 const char *text;
1387
1388 switch (type)
1389 {
1390 case XML_ATTRIBUTE_CDATA:
1391 text = "CDATA";
1392 break;
1393 case XML_ATTRIBUTE_ID:
1394 text = "ID";
1395 break;
1396 case XML_ATTRIBUTE_IDREF:
1397 text = "IDREF";
1398 break;
1399 case XML_ATTRIBUTE_IDREFS:
1400 text = "IDREFS";
1401 break;
1402 case XML_ATTRIBUTE_NMTOKEN:
1403 text = "NMTOKEN";
1404 break;
1405 case XML_ATTRIBUTE_NMTOKENS:
1406 text = "NMTOKENS";
1407 break;
1408 case XML_ATTRIBUTE_ENTITY:
1409 text = "ID";
1410 break;
1411 case XML_ATTRIBUTE_ENTITIES:
1412 text = "ID";
1413 break;
1414 default:
1415 return NULL;
1416 }
1417
1418 return (*env)->NewStringUTF (env, text);
1419 }
1420
1421 /*
1422 * Convert a libxml2 attribute default value type to a string.
1423 */
1424 jstring
xmljAttributeModeName(JNIEnv * env,int type)1425 xmljAttributeModeName (JNIEnv * env, int type)
1426 {
1427 const char *text;
1428
1429 switch (type)
1430 {
1431 case XML_ATTRIBUTE_IMPLIED:
1432 text = "#IMPLIED";
1433 break;
1434 case XML_ATTRIBUTE_REQUIRED:
1435 text = "#REQUIRED";
1436 break;
1437 case XML_ATTRIBUTE_FIXED:
1438 text = "#FIXED";
1439 break;
1440 default:
1441 return NULL;
1442 }
1443
1444 return (*env)->NewStringUTF (env, text);
1445 }
1446