1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50:
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65:
66: import ;
67: import ;
68: import ;
69:
70:
75: public class GnomeXMLReader
76: implements XMLReader
77: {
78:
79: static
80: {
81: XMLJ.init ();
82: }
83:
84: private static final String FEATURES_PREFIX =
85: "http://xml.org/sax/features/";
86:
87: private static final List RECOGNIZED_FEATURES =
88: Arrays.asList (new String[]
89: {
90: "external-general-entities",
91: "external-parameter-entities",
92: "is-standalone",
93: "lexical-handler/parameter-entities",
94: "namespaces",
95: "namespace-prefixes",
96: "resolve-dtd-uris",
97: "string-interning",
98: "use-attributes2",
99: "use-locator2",
100: "use-entity-resolver2",
101: "validation"
102: });
103:
104: private static final String PROPERTIES_PREFIX =
105: "http://xml.org/sax/properties/";
106:
107: private static final List RECOGNIZED_PROPERTIES =
108: Arrays.asList (new String[]
109: {
110: "declaration-handler",
111: "dom-node",
112: "lexical-handler",
113: "xml-string"
114: });
115:
116:
117:
118: private transient boolean standalone;
119: private boolean namespaces;
120: private boolean namespacePrefixes;
121: private boolean validation;
122:
123:
124:
125: private ContentHandler contentHandler;
126:
127: private DTDHandler dtdHandler;
128:
129: private EntityResolver entityResolver;
130:
131: private ErrorHandler errorHandler;
132:
133: private DeclHandler declarationHandler;
134:
135: private LexicalHandler lexicalHandler;
136:
137: private GnomeLocator locator;
138:
139:
140: private transient Namespaces ns;
141:
142:
143: private transient boolean seenFatalError;
144:
145: private transient boolean seenStartDocument;
146:
147: private transient String base;
148:
149: public GnomeXMLReader ()
150: {
151: this (true, true);
152: }
153:
154: public GnomeXMLReader (boolean namespaces, boolean validation)
155: {
156: this.namespaces = namespaces;
157: this.validation = validation;
158: ns = new Namespaces ();
159: }
160:
161: public ContentHandler getContentHandler ()
162: {
163: return contentHandler;
164: }
165:
166: public void setContentHandler (ContentHandler handler)
167: {
168: contentHandler = handler;
169: }
170:
171: public DTDHandler getDTDHandler ()
172: {
173: return dtdHandler;
174: }
175:
176: public void setDTDHandler (DTDHandler handler)
177: {
178: dtdHandler = handler;
179: }
180:
181: public EntityResolver getEntityResolver ()
182: {
183: return entityResolver;
184: }
185:
186: public void setEntityResolver (EntityResolver resolver)
187: {
188: entityResolver = resolver;
189: }
190:
191: public ErrorHandler getErrorHandler ()
192: {
193: return errorHandler;
194: }
195:
196: public void setErrorHandler (ErrorHandler handler)
197: {
198: errorHandler = handler;
199: }
200:
201:
202:
203: public boolean getFeature (String name)
204: throws SAXNotRecognizedException, SAXNotSupportedException
205: {
206: checkFeatureName (name);
207: String key = name.substring (FEATURES_PREFIX.length ());
208: if ("external-general-entities".equals (key))
209: {
210: return validation;
211: }
212: else if ("external-parameter-entities".equals (key))
213: {
214: return validation;
215: }
216: else if ("is-standalone".equals (key))
217: {
218: return standalone;
219: }
220: else if ("namespaces".equals (key))
221: {
222: return namespaces;
223: }
224: else if ("namespace-prefixes".equals (key))
225: {
226: return namespacePrefixes;
227: }
228: else if ("resolve-dtd-uris".equals (key))
229: {
230: return true;
231: }
232: else if ("validation".equals (key))
233: {
234: return validation;
235: }
236: else
237: {
238: return false;
239: }
240: }
241:
242: public void setFeature (String name, boolean value)
243: throws SAXNotRecognizedException, SAXNotSupportedException
244: {
245: checkFeatureName (name);
246: String key = name.substring (FEATURES_PREFIX.length ());
247: if ("namespaces".equals (key))
248: {
249: namespaces = value;
250: }
251: else if ("namespace-prefixes".equals (key))
252: {
253: namespacePrefixes = value;
254: }
255: else if ("validation".equals (key))
256: {
257: validation = value;
258: }
259: }
260:
261:
264: static void checkFeatureName (String name)
265: throws SAXNotRecognizedException
266: {
267: if (name == null || !name.startsWith (FEATURES_PREFIX))
268: {
269: throw new SAXNotRecognizedException (name);
270: }
271: String key = name.substring (FEATURES_PREFIX.length ());
272: if (!RECOGNIZED_FEATURES.contains (key))
273: {
274: throw new SAXNotRecognizedException (name);
275: }
276: }
277:
278:
279:
280: public Object getProperty (String name)
281: throws SAXNotRecognizedException, SAXNotSupportedException
282: {
283: checkPropertyName (name);
284: String key = name.substring (PROPERTIES_PREFIX.length ());
285: if ("declaration-handler".equals (key))
286: {
287: return getDeclarationHandler ();
288: }
289: else if ("lexical-handler".equals (key))
290: {
291: return getLexicalHandler ();
292: }
293: else
294: {
295: throw new SAXNotSupportedException (name);
296: }
297: }
298:
299: public void setProperty (String name, Object value)
300: throws SAXNotRecognizedException, SAXNotSupportedException
301: {
302: checkPropertyName (name);
303: String key = name.substring (PROPERTIES_PREFIX.length ());
304: if ("declaration-handler".equals (key))
305: {
306: setDeclarationHandler ((DeclHandler) value);
307: }
308: else if ("lexical-handler".equals (key))
309: {
310: setLexicalHandler ((LexicalHandler) value);
311: }
312: }
313:
314: public DeclHandler getDeclarationHandler ()
315: {
316: return declarationHandler;
317: }
318:
319: public void setDeclarationHandler (DeclHandler declarationHandler)
320: {
321: this.declarationHandler = declarationHandler;
322: }
323:
324: public LexicalHandler getLexicalHandler ()
325: {
326: return lexicalHandler;
327: }
328:
329: public void setLexicalHandler (LexicalHandler lexicalHandler)
330: {
331: this.lexicalHandler = lexicalHandler;
332: }
333:
334:
337: static void checkPropertyName (String name)
338: throws SAXNotRecognizedException
339: {
340: if (!name.startsWith (PROPERTIES_PREFIX))
341: {
342: throw new SAXNotRecognizedException (name);
343: }
344: String key = name.substring (PROPERTIES_PREFIX.length ());
345: if (!RECOGNIZED_PROPERTIES.contains (key))
346: {
347: throw new SAXNotRecognizedException (name);
348: }
349: }
350:
351:
352:
353: public void parse (String systemId)
354: throws IOException, SAXException
355: {
356: URL url = null;
357: try
358: {
359: url = new URL (systemId);
360: }
361: catch (MalformedURLException e)
362: {
363: File file = new File(systemId);
364: if (!file.exists ())
365: {
366: throw new FileNotFoundException (systemId);
367: }
368: String path = file.getAbsolutePath();
369: if (File.separatorChar != '/')
370: {
371: path = path.replace (File.separatorChar, '/');
372: }
373: if (!path.startsWith ("/"))
374: {
375: path = "/" + path;
376: }
377: if (!path.endsWith ("/") && file.isDirectory ())
378: {
379: path = path + "/";
380: }
381: url = new URL ("file:" + path);
382: }
383: InputSource source = new InputSource(url.toString ());
384: source.setByteStream (url.openStream ());
385: parse (source);
386: }
387:
388: public synchronized void parse (InputSource input)
389: throws IOException, SAXException
390: {
391: NamedInputStream in = XMLJ.getInputStream (input);
392: byte[] detectBuffer = in.getDetectBuffer ();
393: String publicId = input.getPublicId ();
394: String systemId = input.getSystemId ();
395: base = XMLJ.getBaseURI (systemId);
396:
397: standalone = false;
398: seenFatalError = false;
399: seenStartDocument = false;
400: if (systemId != null)
401: {
402: int lsi = systemId.lastIndexOf ('/');
403: if (lsi != -1)
404: {
405: base = systemId.substring (0, lsi + 1);
406: }
407: }
408:
409: if (detectBuffer == null)
410: {
411: startDocument (true);
412: fatalError ("No document element", 0, 0, publicId, systemId);
413: endDocument ();
414: return;
415: }
416:
417: parseStream(in,
418: detectBuffer,
419: publicId,
420: systemId,
421: base,
422: validation,
423: contentHandler != null,
424: dtdHandler != null,
425: entityResolver != null,
426: errorHandler != null,
427: declarationHandler != null,
428: lexicalHandler != null);
429: in.close ();
430: }
431:
432: native void parseStream (InputStream in,
433: byte[] detectBuffer,
434: String publicId,
435: String systemId,
436: String base,
437: boolean validate,
438: boolean contentHandler,
439: boolean dtdHandler,
440: boolean entityResolver,
441: boolean errorHandler,
442: boolean declarationHandler,
443: boolean lexicalHandler)
444: throws IOException, SAXException;
445:
446: String getURI (String prefix)
447: {
448: if (!namespaces)
449: {
450: return null;
451: }
452: return ns.getURI (prefix);
453: }
454:
455:
456:
457: private void startDTD (String name, String publicId, String systemId)
458: throws SAXException
459: {
460: if (seenFatalError || lexicalHandler == null)
461: {
462: return;
463: }
464: try
465: {
466: systemId = XMLJ.getAbsoluteURI (base, systemId);
467: lexicalHandler.startDTD (name, publicId, systemId);
468: }
469: catch (Exception e)
470: {
471: if (e instanceof SAXException)
472: {
473: throw (SAXException) e;
474: }
475: else
476: {
477: throw new SAXException (e);
478: }
479: }
480: }
481:
482: private void externalEntityDecl (String name, String publicId,
483: String systemId)
484: throws SAXException
485: {
486: if (seenFatalError || declarationHandler == null)
487: {
488: return;
489: }
490: try
491: {
492: systemId = XMLJ.getAbsoluteURI (base, systemId);
493: declarationHandler.externalEntityDecl (name, publicId, systemId);
494: }
495: catch (Exception e)
496: {
497: if (e instanceof SAXException)
498: {
499: throw (SAXException) e;
500: }
501: else
502: {
503: throw new SAXException (e);
504: }
505: }
506: }
507:
508: private void internalEntityDecl (String name, String value)
509: throws SAXException
510: {
511: if (seenFatalError || declarationHandler == null)
512: {
513: return;
514: }
515: try
516: {
517: declarationHandler.internalEntityDecl (name, value);
518: }
519: catch (Exception e)
520: {
521: if (e instanceof SAXException)
522: {
523: throw (SAXException) e;
524: }
525: else
526: {
527: throw new SAXException (e);
528: }
529: }
530: }
531:
532: private InputStream resolveEntity (String publicId, String systemId)
533: throws SAXException, IOException
534: {
535: if (entityResolver == null)
536: {
537: return null;
538: }
539: try
540: {
541: systemId = XMLJ.getAbsoluteURI (base, systemId);
542: InputSource source = entityResolver.resolveEntity (publicId, systemId);
543: return (source == null) ? null : XMLJ.getInputStream (source);
544: }
545: catch (Exception e)
546: {
547: if (e instanceof SAXException)
548: {
549: throw (SAXException) e;
550: }
551: else
552: {
553: throw new SAXException (e);
554: }
555: }
556: }
557:
558: private void notationDecl (String name, String publicId, String systemId)
559: throws SAXException
560: {
561: if (seenFatalError || dtdHandler == null)
562: {
563: return;
564: }
565: try
566: {
567: systemId = XMLJ.getAbsoluteURI (base, systemId);
568: dtdHandler.notationDecl (name, publicId, systemId);
569: }
570: catch (Exception e)
571: {
572: if (e instanceof SAXException)
573: {
574: throw (SAXException) e;
575: }
576: else
577: {
578: throw new SAXException (e);
579: }
580: }
581: }
582:
583: private void attributeDecl (String eName, String aName, String type,
584: String mode, String value)
585: throws SAXException
586: {
587: if (seenFatalError || declarationHandler == null)
588: {
589: return;
590: }
591: try
592: {
593: declarationHandler.attributeDecl (eName, aName, type, mode, value);
594: }
595: catch (Exception e)
596: {
597: if (e instanceof SAXException)
598: {
599: throw (SAXException) e;
600: }
601: else
602: {
603: throw new SAXException (e);
604: }
605: }
606: }
607:
608: private void elementDecl (String name, String model)
609: throws SAXException
610: {
611: if (seenFatalError || declarationHandler == null)
612: {
613: return;
614: }
615: try
616: {
617: declarationHandler.elementDecl (name, model);
618: }
619: catch (Exception e)
620: {
621: if (e instanceof SAXException)
622: {
623: throw (SAXException) e;
624: }
625: else
626: {
627: throw new SAXException (e);
628: }
629: }
630: }
631:
632: private void unparsedEntityDecl (String name, String publicId,
633: String systemId, String notationName)
634: throws SAXException
635: {
636: if (seenFatalError || dtdHandler == null)
637: {
638: return;
639: }
640: try
641: {
642: systemId = XMLJ.getAbsoluteURI (base, systemId);
643: dtdHandler.unparsedEntityDecl (name, publicId, systemId,
644: notationName);
645: }
646: catch (Exception e)
647: {
648: if (e instanceof SAXException)
649: {
650: throw (SAXException) e;
651: }
652: else
653: {
654: throw new SAXException (e);
655: }
656: }
657: }
658:
659: private void setDocumentLocator (Object ctx, Object loc)
660: {
661: locator = new GnomeLocator (ctx, loc);
662: if (seenFatalError || contentHandler == null)
663: {
664: return;
665: }
666: try
667: {
668: contentHandler.setDocumentLocator (locator);
669: }
670: catch (Exception e)
671: {
672: }
673: }
674:
675: private void startDocument (boolean standalone)
676: throws SAXException
677: {
678: this.standalone = standalone;
679: seenStartDocument = true;
680: if (contentHandler == null)
681: {
682: return;
683: }
684: try
685: {
686: contentHandler.startDocument ();
687: }
688: catch (Exception e)
689: {
690: if (e instanceof SAXException)
691: {
692: throw (SAXException) e;
693: }
694: else
695: {
696: throw new SAXException (e);
697: }
698: }
699: }
700:
701: private void endDocument ()
702: throws SAXException
703: {
704: if (contentHandler == null)
705: {
706: return;
707: }
708: try
709: {
710: contentHandler.endDocument();
711: }
712: catch (Exception e)
713: {
714: if (e instanceof SAXException)
715: {
716: throw (SAXException) e;
717: }
718: else
719: {
720: throw new SAXException (e);
721: }
722: }
723: }
724:
725: private void startElement(String name, String[] attrs)
726: throws SAXException
727: {
728: if (seenFatalError || contentHandler == null)
729: {
730: return;
731: }
732: try
733: {
734: XMLName xName = new XMLName (this, name);
735: if (namespaces)
736: {
737:
738: ns.push ();
739: int len = (attrs == null) ? 0 : attrs.length;
740: if (len > 0)
741: {
742: ArrayList filtered = new ArrayList (len);
743: for (int i = 0; i < len; i += 2)
744: {
745: String attName = attrs[i];
746: String attValue = attrs[i + 1];
747: if (attName.equals ("xmlns"))
748: {
749: startPrefixMapping ("", attValue);
750: }
751: else if (attName.startsWith ("xmlns:"))
752: {
753: startPrefixMapping (attName.substring (6), attValue);
754: }
755: else
756: {
757: filtered.add (attName);
758: filtered.add (attValue);
759: }
760: }
761:
762: attrs = new String[filtered.size ()];
763: filtered.toArray (attrs);
764: }
765: }
766:
767: Attributes atts = new StringArrayAttributes (this, attrs);
768: contentHandler.startElement (xName.uri, xName.localName, xName.qName,
769: atts);
770: }
771: catch (Exception e)
772: {
773: if (e instanceof SAXException)
774: {
775: throw (SAXException) e;
776: }
777: else
778: {
779: throw new SAXException (e);
780: }
781: }
782: }
783:
784: private void endElement (String name)
785: throws SAXException
786: {
787: if (seenFatalError || contentHandler == null)
788: {
789: return;
790: }
791: try
792: {
793: XMLName xName = new XMLName (this, name);
794: String uri = (xName.uri == null) ? "" : xName.uri;
795: contentHandler.endElement (uri, xName.localName, xName.qName);
796:
797: if (namespaces)
798: {
799: for (Iterator i = ns.currentPrefixes (); i.hasNext (); )
800: {
801: endPrefixMapping ((String) i.next ());
802: }
803: ns.pop ();
804: }
805: }
806: catch (Exception e)
807: {
808: if (e instanceof SAXException)
809: {
810: throw (SAXException) e;
811: }
812: else
813: {
814: throw new SAXException (e);
815: }
816: }
817: }
818:
819: private void startPrefixMapping (String prefix, String uri)
820: throws SAXException
821: {
822: if (seenFatalError || contentHandler == null)
823: {
824: return;
825: }
826: ns.define (prefix, uri);
827: contentHandler.startPrefixMapping (prefix, uri);
828: }
829:
830: private void endPrefixMapping (String prefix)
831: throws SAXException
832: {
833: if (seenFatalError || contentHandler == null)
834: {
835: return;
836: }
837: contentHandler.endPrefixMapping (prefix);
838: }
839:
840: private void characters (String text)
841: throws SAXException
842: {
843: if (seenFatalError || contentHandler == null || text == null)
844: {
845: return;
846: }
847: try
848: {
849: char[] ch = text.toCharArray ();
850: contentHandler.characters (ch, 0, ch.length);
851: }
852: catch (Exception e)
853: {
854: if (e instanceof SAXException)
855: {
856: throw (SAXException) e;
857: }
858: else
859: {
860: throw new SAXException (e);
861: }
862: }
863: }
864:
865: private void ignorableWhitespace (String text)
866: throws SAXException
867: {
868: if (seenFatalError || contentHandler == null || text == null)
869: {
870: return;
871: }
872: try
873: {
874: char[] ch = text.toCharArray ();
875: contentHandler.ignorableWhitespace (ch, 0, ch.length);
876: }
877: catch (Exception e)
878: {
879: if (e instanceof SAXException)
880: {
881: throw (SAXException) e;
882: }
883: else
884: {
885: throw new SAXException (e);
886: }
887: }
888: }
889:
890: private void processingInstruction (String target, String data)
891: throws SAXException
892: {
893: if (seenFatalError || contentHandler == null)
894: {
895: return;
896: }
897: try
898: {
899: if (data == null)
900: {
901: data = "";
902: }
903: contentHandler.processingInstruction (target, data);
904: }
905: catch (Exception e)
906: {
907: if (e instanceof SAXException)
908: {
909: throw (SAXException) e;
910: }
911: else
912: {
913: throw new SAXException (e);
914: }
915: }
916: }
917:
918: private void comment (String text)
919: throws SAXException
920: {
921: if (seenFatalError || lexicalHandler == null || text == null)
922: {
923: return;
924: }
925: try
926: {
927: char[] ch = text.toCharArray ();
928: lexicalHandler.comment (ch, 0, ch.length);
929: }
930: catch (Exception e)
931: {
932: if (e instanceof SAXException)
933: {
934: throw (SAXException) e;
935: }
936: else
937: {
938: throw new SAXException (e);
939: }
940: }
941: }
942:
943: private void cdataBlock (String text)
944: throws SAXException
945: {
946: if (seenFatalError || text == null)
947: {
948: return;
949: }
950: try
951: {
952: if (lexicalHandler == null)
953: {
954: characters(text);
955: }
956: else
957: {
958: lexicalHandler.startCDATA();
959: characters(text);
960: lexicalHandler.endCDATA();
961: }
962: }
963: catch (Exception e)
964: {
965: if (e instanceof SAXException)
966: {
967: throw (SAXException) e;
968: }
969: else
970: {
971: throw new SAXException (e);
972: }
973: }
974: }
975:
976: private void warning (String message,
977: int lineNumber, int columnNumber,
978: String publicId, String systemId)
979: throws SAXException
980: {
981: if (seenFatalError || errorHandler == null)
982: {
983: return;
984: }
985: try
986: {
987: Locator l = new StandaloneLocator (lineNumber, columnNumber,
988: publicId, systemId);
989: errorHandler.warning (new SAXParseException (message, l));
990: }
991: catch (Exception e)
992: {
993: if (e instanceof SAXException)
994: {
995: throw (SAXException) e;
996: }
997: else
998: {
999: throw new SAXException (e);
1000: }
1001: }
1002: }
1003:
1004: private void error (String message,
1005: int lineNumber, int columnNumber,
1006: String publicId, String systemId)
1007: throws SAXException
1008: {
1009: if (seenFatalError || errorHandler == null)
1010: {
1011: return;
1012: }
1013: try
1014: {
1015: Locator l = new StandaloneLocator (lineNumber, columnNumber,
1016: publicId, systemId);
1017: errorHandler.error (new SAXParseException (message, l));
1018: }
1019: catch (Exception e)
1020: {
1021: if (e instanceof SAXException)
1022: {
1023: throw (SAXException) e;
1024: }
1025: else
1026: {
1027: throw new SAXException (e);
1028: }
1029: }
1030: }
1031:
1032: private void fatalError (String message,
1033: int lineNumber, int columnNumber,
1034: String publicId, String systemId)
1035: throws SAXException
1036: {
1037: if (seenFatalError || errorHandler == null)
1038: {
1039: return;
1040: }
1041: try
1042: {
1043: if (!seenStartDocument)
1044: {
1045: startDocument (false);
1046: }
1047: seenFatalError = true;
1048: Locator l = new StandaloneLocator (lineNumber, columnNumber,
1049: publicId, systemId);
1050: errorHandler.fatalError (new SAXParseException (message, l));
1051: }
1052: catch (Exception e)
1053: {
1054: if (e instanceof SAXException)
1055: {
1056: throw (SAXException) e;
1057: }
1058: else
1059: {
1060: throw new SAXException (e);
1061: }
1062: }
1063: }
1064:
1065: }