View Javadoc

1   /**
2    * JSpiff
3    * -----------------
4    * Copyright (c) 2005-2006 Emil A. Lefkof III
5    *
6    * I always give it my best shot to make a program useful and solid, but
7    * remeber that there is absolutely no warranty for using this program as
8    * stated in the following terms:
9    *
10   * Licensed under the Apache License, Version 2.0 (the "License");
11   * you may not use this file except in compliance with the License.
12   * You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing, software
17   * distributed under the License is distributed on an "AS IS" BASIS,
18   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   * See the License for the specific language governing permissions and
20   * limitations under the License.
21   */
22  package com.melloware.jspiff.jaxp;
23  
24  import java.io.File;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.Reader;
28  import java.io.StringReader;
29  import java.lang.reflect.Method;
30  import java.net.MalformedURLException;
31  import java.net.URL;
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.HashMap;
35  import java.util.List;
36  import java.util.Map;
37  
38  import javax.xml.parsers.DocumentBuilder;
39  import javax.xml.parsers.DocumentBuilderFactory;
40  import javax.xml.parsers.ParserConfigurationException;
41  
42  import org.w3c.dom.Document;
43  import org.w3c.dom.Element;
44  import org.xml.sax.EntityResolver;
45  import org.xml.sax.ErrorHandler;
46  import org.xml.sax.InputSource;
47  import org.xml.sax.SAXException;
48  import org.xml.sax.SAXParseException;
49  
50  /**
51   * UJAXP
52   *
53   * @since   Feb. 20, 2000
54   * @version Jul. 10, 2003
55   * @author  ASAMI, Tomoharu (asami@relaxer.org)
56   * @author Emil A. Lefkof III <info@melloware.com>
57   */
58  public final class UJAXP {
59      public static final int FLAG_NONE = 0x00;
60      public static final int FLAG_VALIDATION = 0x01;
61      public static final int FLAG_NAMESPACE_AWARE = 0x02;
62      public static final int FLAG_WHITESPACE = 0x04;
63      public static final int FLAG_EXPAND_ENTITY_REF = 0x08;
64      public static final int FLAG_IGNORE_COMMENTS = 0x10;
65      public static final int FLAG_COALESCING = 0x20;
66  
67      private static ErrorHandler errorHandler;
68      private static EntityResolver entityResolver;
69      private static Map entityMap;
70  
71      //
72      public static Document getDocument(File file)
73                                  throws IOException, SAXException, ParserConfigurationException {
74  
75          return (getDocument(file.toURL()));
76      }
77  
78      public static Document getDocument(String uri)
79                                  throws IOException, SAXException, ParserConfigurationException {
80  
81          return (getDocument(uri, getErrorHandler()));
82      }
83  
84      public static Document getDocument(URL url)
85                                  throws IOException, SAXException, ParserConfigurationException {
86  
87          return (getDocument(url, getErrorHandler()));
88      }
89  
90      public static Document getDocument(InputStream in)
91                                  throws IOException, SAXException, ParserConfigurationException {
92  
93          return (getDocument(in, getErrorHandler()));
94      }
95  
96      public static Document getDocument(InputSource is)
97                                  throws IOException, SAXException, ParserConfigurationException {
98  
99          return (getDocument(is, getErrorHandler()));
100     }
101 
102     public static Document getDocument(Reader reader)
103                                 throws IOException, SAXException, ParserConfigurationException {
104 
105         return (getDocument(reader, getErrorHandler()));
106     }
107 
108     //
109     public static Document getDocument(File file, int flags)
110                                 throws IOException, SAXException, ParserConfigurationException {
111 
112         return (getDocument(file.toURL(), flags));
113     }
114 
115     public static Document getDocument(String uri, int flags)
116                                 throws IOException, SAXException, ParserConfigurationException {
117 
118         return (getDocument(uri, flags, getErrorHandler()));
119     }
120 
121     public static Document getDocument(URL url, int flags)
122                                 throws IOException, SAXException, ParserConfigurationException {
123 
124         return (getDocument(url, flags, getErrorHandler()));
125     }
126 
127     public static Document getDocument(InputStream in, int flags)
128                                 throws IOException, SAXException, ParserConfigurationException {
129 
130         return (getDocument(in, flags, getErrorHandler()));
131     }
132 
133     public static Document getDocument(InputSource is, int flags)
134                                 throws IOException, SAXException, ParserConfigurationException {
135 
136         return (getDocument(is, flags, getErrorHandler()));
137     }
138 
139     public static Document getDocument(Reader reader, int flags)
140                                 throws IOException, SAXException, ParserConfigurationException {
141 
142         return (getDocument(reader, flags, getErrorHandler()));
143     }
144 
145     public static Document getDocument(File file, ErrorHandler handler)
146                                 throws IOException, SAXException, ParserConfigurationException {
147 
148         return (getDocument(file.toURL(), handler));
149     }
150 
151     public static Document getDocument(String uri, ErrorHandler handler)
152                                 throws IOException, SAXException, ParserConfigurationException {
153 
154         if (handler == null) {
155             handler = getErrorHandler();
156         }
157         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
158         DocumentBuilder builder = factory.newDocumentBuilder();
159         builder.setErrorHandler(handler);
160         builder.setEntityResolver(getEntityResolver());
161         Document doc = builder.parse(adjustURI(uri));
162         return (doc);
163     }
164 
165     public static Document getDocument(URL url, ErrorHandler handler)
166                                 throws IOException, SAXException, ParserConfigurationException {
167 
168         if (handler == null) {
169             handler = getErrorHandler();
170         }
171         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
172         DocumentBuilder builder = factory.newDocumentBuilder();
173         builder.setErrorHandler(handler);
174         builder.setEntityResolver(getEntityResolver());
175         Document doc = builder.parse(url.toString());
176         return (doc);
177     }
178 
179     public static Document getDocument(InputStream in, ErrorHandler handler)
180                                 throws IOException, SAXException, ParserConfigurationException {
181 
182         if (handler == null) {
183             handler = getErrorHandler();
184         }
185         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
186         DocumentBuilder builder = factory.newDocumentBuilder();
187         builder.setErrorHandler(handler);
188         builder.setEntityResolver(getEntityResolver());
189         Document doc = builder.parse(in);
190         return (doc);
191     }
192 
193     public static Document getDocument(InputSource is, ErrorHandler handler)
194                                 throws IOException, SAXException, ParserConfigurationException {
195 
196         if (handler == null) {
197             handler = getErrorHandler();
198         }
199         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
200         DocumentBuilder builder = factory.newDocumentBuilder();
201         builder.setErrorHandler(handler);
202         builder.setEntityResolver(getEntityResolver());
203         Document doc = builder.parse(is);
204         return (doc);
205     }
206 
207     public static Document getDocument(Reader reader, ErrorHandler handler)
208                                 throws IOException, SAXException, ParserConfigurationException {
209 
210         if (handler == null) {
211             handler = getErrorHandler();
212         }
213         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
214         DocumentBuilder builder = factory.newDocumentBuilder();
215         builder.setErrorHandler(handler);
216         builder.setEntityResolver(getEntityResolver());
217         Document doc = builder.parse(new InputSource(reader));
218         return (doc);
219     }
220 
221     //
222     public static Document getDocument(File file, int flags, ErrorHandler handler)
223                                 throws IOException, SAXException, ParserConfigurationException {
224         return (getDocument(file.toURL(), flags, handler));
225     }
226 
227     public static Document getDocument(String uri, int flags, ErrorHandler handler)
228                                 throws IOException, SAXException, ParserConfigurationException {
229         if ((uri == null) || (uri.length() == 0)) {
230             throw (new IllegalArgumentException());
231         }
232         if (uri.charAt(0) == '<') {
233             return (getDocument(new StringReader(uri), flags, handler));
234         }
235         if (handler == null) {
236             handler = getErrorHandler();
237         }
238         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
239         _setup(factory, flags);
240         DocumentBuilder builder = factory.newDocumentBuilder();
241         builder.setErrorHandler(handler);
242         builder.setEntityResolver(getEntityResolver());
243         Document doc = builder.parse(adjustURI(uri));
244         return (doc);
245     }
246 
247     public static Document getDocument(URL url, int flags, ErrorHandler handler)
248                                 throws IOException, SAXException, ParserConfigurationException {
249         if (handler == null) {
250             handler = getErrorHandler();
251         }
252         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
253         _setup(factory, flags);
254         DocumentBuilder builder = factory.newDocumentBuilder();
255         builder.setErrorHandler(handler);
256         builder.setEntityResolver(getEntityResolver());
257         Document doc = builder.parse(url.toString());
258         return (doc);
259     }
260 
261     public static Document getDocument(InputStream in, int flags, ErrorHandler handler)
262                                 throws IOException, SAXException, ParserConfigurationException {
263         if (handler == null) {
264             handler = getErrorHandler();
265         }
266         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
267         _setup(factory, flags);
268         DocumentBuilder builder = factory.newDocumentBuilder();
269         builder.setErrorHandler(handler);
270         builder.setEntityResolver(getEntityResolver());
271         Document doc = builder.parse(in);
272         return (doc);
273     }
274 
275     public static Document getDocument(InputSource is, int flags, ErrorHandler handler)
276                                 throws IOException, SAXException, ParserConfigurationException {
277         if (handler == null) {
278             handler = getErrorHandler();
279         }
280         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
281         _setup(factory, flags);
282         DocumentBuilder builder = factory.newDocumentBuilder();
283         builder.setErrorHandler(handler);
284         builder.setEntityResolver(getEntityResolver());
285         Document doc = builder.parse(is);
286         return (doc);
287     }
288 
289     public static Document getDocument(Reader reader, int flags, ErrorHandler handler)
290                                 throws IOException, SAXException, ParserConfigurationException {
291         if (handler == null) {
292             handler = getErrorHandler();
293         }
294         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
295         _setup(factory, flags);
296         DocumentBuilder builder = factory.newDocumentBuilder();
297         builder.setErrorHandler(handler);
298         builder.setEntityResolver(getEntityResolver());
299         Document doc = builder.parse(new InputSource(reader));
300         return (doc);
301     }
302 
303     // For factory
304     public static Document getDocument(File file, int flags, ErrorHandler handler, EntityResolver resolver)
305                                 throws IOException, SAXException, ParserConfigurationException {
306         return (getDocument(file.toURL(), flags, handler, resolver));
307     }
308 
309     /*
310      *  private static String _makeUri(String uri, String baseUri) {     if (baseUri == null) {         return (uri);
311      *  }     if (isURL(uri)) {         return (uri);     } else if (new File(uri).isAbsolute()) {         return (uri);
312      *     } else {         if (baseUri.endsWith("/")) {             return (baseUri + uri);         } else {
313      *  return (baseUri + "/" + uri);         }     } }
314      */
315 
316     public static Document getDocument(URL url, int flags, ErrorHandler handler, EntityResolver resolver)
317                                 throws IOException, SAXException, ParserConfigurationException {
318         if (handler == null) {
319             handler = getErrorHandler();
320         }
321         if (resolver == null) {
322             resolver = getEntityResolver();
323         }
324         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
325         _setup(factory, flags);
326         DocumentBuilder builder = factory.newDocumentBuilder();
327         builder.setErrorHandler(handler);
328         builder.setEntityResolver(getEntityResolver());
329         Document doc = builder.parse(url.toString());
330         return (doc);
331     }
332 
333     public static Document getDocument(InputStream in, int flags, ErrorHandler handler, EntityResolver resolver)
334                                 throws IOException, SAXException, ParserConfigurationException {
335         if (handler == null) {
336             handler = getErrorHandler();
337         }
338         if (resolver == null) {
339             resolver = getEntityResolver();
340         }
341         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
342         _setup(factory, flags);
343         DocumentBuilder builder = factory.newDocumentBuilder();
344         builder.setErrorHandler(handler);
345         builder.setEntityResolver(getEntityResolver());
346         Document doc = builder.parse(in);
347         return (doc);
348     }
349 
350     public static Document getDocument(InputSource is, int flags, ErrorHandler handler, EntityResolver resolver)
351                                 throws IOException, SAXException, ParserConfigurationException {
352         if (handler == null) {
353             handler = getErrorHandler();
354         }
355         if (resolver == null) {
356             resolver = getEntityResolver();
357         }
358         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
359         _setup(factory, flags);
360         DocumentBuilder builder = factory.newDocumentBuilder();
361         builder.setErrorHandler(handler);
362         builder.setEntityResolver(getEntityResolver());
363         Document doc = builder.parse(is);
364         return (doc);
365     }
366 
367     public static Document getDocument(Reader reader, int flags, ErrorHandler handler, EntityResolver resolver)
368                                 throws IOException, SAXException, ParserConfigurationException {
369         if (handler == null) {
370             handler = getErrorHandler();
371         }
372         if (resolver == null) {
373             resolver = getEntityResolver();
374         }
375         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
376         _setup(factory, flags);
377         DocumentBuilder builder = factory.newDocumentBuilder();
378         builder.setErrorHandler(handler);
379         builder.setEntityResolver(getEntityResolver());
380         Document doc = builder.parse(new InputSource(reader));
381         return (doc);
382     }
383 
384     public static Document getDocument(String uri,
385                                        String baseUri,
386                                        int flags,
387                                        ErrorHandler handler,
388                                        EntityResolver resolver)
389                                 throws IOException, SAXException, ParserConfigurationException {
390         if ((uri == null) || (uri.length() == 0)) {
391             throw (new IllegalArgumentException());
392         }
393         if (uri.charAt(0) == '<') {
394             return (getDocument(new StringReader(uri), flags, handler, resolver));
395         }
396         uri = makeUri(uri, baseUri);
397         if (handler == null) {
398             handler = getErrorHandler();
399         }
400         if (resolver == null) {
401             resolver = getEntityResolver();
402         }
403         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
404         _setup(factory, flags);
405         DocumentBuilder builder = factory.newDocumentBuilder();
406         builder.setErrorHandler(handler);
407         builder.setEntityResolver(resolver);
408         Document doc = builder.parse(adjustURI(uri));
409         return (doc);
410     }
411 
412     public static EntityResolver getEntityResolver() {
413         if (entityResolver == null) {
414             entityResolver = new DefaultEntityResolver();
415         }
416         return (entityResolver);
417     }
418 
419     public static URL getEntityResource(String systemId) {
420         if (entityMap == null) {
421             return (null);
422         } else {
423             String filename = _getFilename(systemId);
424             return ((URL)entityMap.get(filename));
425         }
426     }
427 
428     public static ErrorHandler getErrorHandler() {
429         if (errorHandler == null) {
430             errorHandler = new DefaultErrorHandler();
431         }
432         return (errorHandler);
433     }
434 
435     // obsolate?
436     public static Document getValidDocument(File file)
437                                      throws IOException, SAXException, ParserConfigurationException {
438 
439         return (getValidDocument(file.toURL()));
440     }
441 
442     public static Document getValidDocument(String uri)
443                                      throws IOException, SAXException, ParserConfigurationException {
444 
445         return (getValidDocument(uri, getErrorHandler()));
446     }
447 
448     public static Document getValidDocument(URL url)
449                                      throws IOException, SAXException, ParserConfigurationException {
450 
451         return (getValidDocument(url, getErrorHandler()));
452     }
453 
454     public static Document getValidDocument(InputStream in)
455                                      throws IOException, SAXException, ParserConfigurationException {
456 
457         return (getValidDocument(in, getErrorHandler()));
458     }
459 
460     public static Document getValidDocument(InputSource is)
461                                      throws IOException, SAXException, ParserConfigurationException {
462 
463         return (getValidDocument(is, getErrorHandler()));
464     }
465 
466     public static Document getValidDocument(Reader reader)
467                                      throws IOException, SAXException, ParserConfigurationException {
468 
469         return (getValidDocument(reader, getErrorHandler()));
470     }
471 
472     public static Document getValidDocument(File file, ErrorHandler handler)
473                                      throws IOException, SAXException, ParserConfigurationException {
474 
475         return (getValidDocument(file.toURL(), handler));
476     }
477 
478     public static Document getValidDocument(String uri, ErrorHandler handler)
479                                      throws IOException, SAXException, ParserConfigurationException {
480         if ((uri == null) || (uri.length() == 0)) {
481             throw (new IllegalArgumentException());
482         }
483         if (uri.charAt(0) == '<') {
484             return (getValidDocument(new StringReader(uri), handler));
485         }
486         if (handler == null) {
487             handler = getErrorHandler();
488         }
489         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
490         factory.setValidating(true);
491         DocumentBuilder builder = factory.newDocumentBuilder();
492         builder.setErrorHandler(handler);
493         builder.setEntityResolver(getEntityResolver());
494         Document doc = builder.parse(adjustURI(uri));
495         return (doc);
496     }
497 
498     public static Document getValidDocument(URL url, ErrorHandler handler)
499                                      throws IOException, SAXException, ParserConfigurationException {
500         if (handler == null) {
501             handler = getErrorHandler();
502         }
503         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
504         factory.setValidating(true);
505         DocumentBuilder builder = factory.newDocumentBuilder();
506         builder.setErrorHandler(handler);
507         builder.setEntityResolver(getEntityResolver());
508         Document doc = builder.parse(url.toString());
509         return (doc);
510     }
511 
512     public static Document getValidDocument(InputStream in, ErrorHandler handler)
513                                      throws IOException, SAXException, ParserConfigurationException {
514         if (handler == null) {
515             handler = getErrorHandler();
516         }
517         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
518         factory.setValidating(true);
519         DocumentBuilder builder = factory.newDocumentBuilder();
520         builder.setErrorHandler(handler);
521         builder.setEntityResolver(getEntityResolver());
522         Document doc = builder.parse(in);
523         return (doc);
524     }
525 
526     public static Document getValidDocument(InputSource is, ErrorHandler handler)
527                                      throws IOException, SAXException, ParserConfigurationException {
528         if (handler == null) {
529             handler = getErrorHandler();
530         }
531         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
532         factory.setValidating(true);
533         DocumentBuilder builder = factory.newDocumentBuilder();
534         builder.setErrorHandler(handler);
535         builder.setEntityResolver(getEntityResolver());
536         Document doc = builder.parse(is);
537         return (doc);
538     }
539 
540     public static Document getValidDocument(Reader reader, ErrorHandler handler)
541                                      throws IOException, SAXException, ParserConfigurationException {
542         if (handler == null) {
543             handler = getErrorHandler();
544         }
545         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
546         factory.setValidating(true);
547         DocumentBuilder builder = factory.newDocumentBuilder();
548         builder.setErrorHandler(handler);
549         builder.setEntityResolver(getEntityResolver());
550         Document doc = builder.parse(new InputSource(reader));
551         return (doc);
552     }
553 
554     public static void setEntityResolver(EntityResolver resolver) {
555         entityResolver = resolver;
556     }
557 
558     public static void setEntityResource(String systemId, URL resource) {
559         if (entityMap == null) {
560             entityMap = new HashMap();
561         }
562         entityMap.put(systemId, resource);
563     }
564 
565     public static void setErrorHandler(ErrorHandler handler) {
566         errorHandler = handler;
567     }
568 
569     // complex
570     public static boolean isMatchDataComplex(Element element, String typeExpr) {
571         String data = URelaxer.getElementPropertyAsValue(element, "string");
572         return (isMatchDataComplex(data, typeExpr));
573     }
574 
575     public static boolean isMatchDataComplex(String data, String typeExpr) {
576         try {
577             Document doc = getDocument(new java.io.StringReader(typeExpr));
578             return (_isMatchData(data, doc.getDocumentElement()));
579         } catch (Exception e) {
580             throw (new InternalError(data + " : " + typeExpr));
581         }
582     }
583 
584     public static boolean isMatchDataComplexAttr(Element element, String attrName, String typeExpr) {
585         String data = URelaxer.getAttributePropertyAsValue(element, attrName, "string");
586         if (data == null) {
587             return (false);
588         }
589         return (isMatchDataComplex(data, typeExpr));
590     }
591 
592     public static boolean isMatchDataComplexElement(Element element, String elementName, String typeExpr) {
593         String data = URelaxer.getElementPropertyAsValue(element, elementName, "string");
594         if (data == null) {
595             return (false);
596         }
597         return (isMatchDataComplex(data, typeExpr));
598     }
599 
600     // test driver
601     public static void main(String[] args)
602                      throws Exception {
603         String className = args[0];
604         File file = new File(args[1]);
605         Class clazz = Class.forName(className);
606         Method setupMethod = clazz.getMethod("setup", new Class[] { File.class });
607         Method makeMethod = clazz.getMethod("makeDocument", new Class[0]);
608         Object object = clazz.newInstance();
609         setupMethod.invoke(object, new Object[] { file });
610         System.out.println("text:" + object);
611         Document doc = (Document)makeMethod.invoke(object, new Object[0]);
612         System.out.println("dom:" + URelaxer.doc2String4Data(doc));
613     }
614 
615     public static Document makeDocument()
616                                  throws ParserConfigurationException {
617 
618         return (makeDocument(getErrorHandler()));
619     }
620 
621     public static Document makeDocument(ErrorHandler handler)
622                                  throws ParserConfigurationException {
623 
624         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
625         DocumentBuilder builder = factory.newDocumentBuilder();
626         builder.setErrorHandler(handler);
627         builder.setEntityResolver(getEntityResolver());
628         Document doc = builder.newDocument();
629         return (doc);
630     }
631 
632     // IETF 2396
633     public static String makeUri(String uri, String baseUri) {
634         // System.out.println("uri = " + uri);
635         // System.out.println("xml:base = " + baseUri);
636         try {
637             new URL(uri);
638             return (uri);
639         } catch (MalformedURLException e) {
640             ;
641         }
642         try {
643             if (baseUri == null) {
644                 return (new File(uri).toURL().toExternalForm());
645             }
646             URL url = new URL(baseUri);
647             String protocol = url.getProtocol();
648             String host = url.getHost();
649             int port = url.getPort();
650             String path = url.getPath();
651             if (uri.startsWith("/")) {
652                 String newPath = _normalizePath(uri);
653                 URL newUrl = new URL(protocol, host, port, newPath);
654                 // System.out.println("result = " + newUrl.toExternalForm());
655                 return (newUrl.toExternalForm());
656             } else {
657                 if (path == null) {
658                     path = "/";
659                 }
660                 int index = path.lastIndexOf("/");
661                 if (index == -1) {
662                     throw (new IllegalArgumentException(baseUri));
663                 }
664                 String newPath = _normalizePath(path.substring(0, index + 1) + uri);
665                 URL newUrl = new URL(protocol, host, port, newPath);
666                 // System.out.println("result = " + newUrl.toExternalForm());
667                 return (newUrl.toExternalForm());
668             }
669         } catch (MalformedURLException e) {
670             throw (new IllegalArgumentException(baseUri));
671         }
672     }
673 
674     static boolean isURL(String uri) {
675         try {
676             new URL(uri);
677             return (true);
678         } catch (MalformedURLException e) {
679             return (false);
680         }
681     }
682 
683     static String adjustURI(String uri) {
684         try {
685             URL url = makeURL(uri);
686             return (url.toExternalForm());
687         } catch (MalformedURLException e) {
688             return (uri);
689         }
690     }
691 
692     static boolean canAccess(String uri) {
693         try {
694             URL url = makeURL(uri);
695             if ("file".equals(url.getProtocol())) {
696                 String fileName = url.getFile();
697                 return (new File(fileName).exists());
698             }
699             return (false);    // skip http uri
700         } catch (IOException e) {
701             return (false);
702         }
703     }
704 
705     static URL makeURL(String uri)
706                 throws MalformedURLException {
707         try {
708             return (new URL(uri));
709         } catch (MalformedURLException e) {
710             return (new File(uri).toURL());
711         }
712     }
713 
714     private static String _getFilename(String pathname) {
715         int index = pathname.lastIndexOf("/");
716         if (index == -1) {
717             return (pathname);
718         } else {
719             return (pathname.substring(index + 1));
720         }
721     }
722 
723     private static boolean _isMatchData(String data, Element expr) {
724         String tagName = expr.getTagName();
725         if ("value".equals(tagName)) {
726             return (_isMatchDataValue(data, expr));
727         } else if ("data".equals(tagName)) {
728             return (_isMatchDataData(data, expr));
729         } else if ("choice".equals(tagName)) {
730             return (_isMatchDataChoice(data, expr));
731         } else if ("list".equals(tagName)) {
732             return (_isMatchDataList(data, expr));
733                    /*
734                     *      } else if ("optional".equals(tagName)) {         return (_isMatchDataOptional(data, expr));     }
735                     * else if ("oneOrMore".equals(tagName)) {         return (_isMatchDataOneOrMore(data, expr));     } else if
736                     * ("zeroOrMore".equals(tagName)) {         return (_isMatchDataZeroOrMore(data, expr));
737                     */
738         } else {
739             throw (new InternalError(data + " : " + tagName));
740         }
741     }
742 
743     private static boolean _isMatchDataChoice(String data, Element choice) {
744         Element[] children = URelaxer.getElements(choice);
745         for (int i = 0; i < children.length; i++) {
746             Element child = children[i];
747             if (_isMatchData(data, child)) {
748                 return (true);
749             }
750         }
751         return (false);
752     }
753 
754     private static boolean _isMatchDataData(String data, Element dataInfo) {
755         return (true);
756     }
757 
758     private static boolean _isMatchDataList(String data, Element listInfo) {
759         Element[] children = URelaxer.getElements(listInfo);
760         String[] texts = URelaxer.getStringList(data);
761         List list = new ArrayList();
762         list.addAll(Arrays.asList(texts));
763         for (int i = 0; i < children.length; i++) {
764             Element child = children[i];
765             String tagName = child.getTagName();
766             if ("value".equals(tagName)) {
767                 if (list.size() == 0) {
768                     return (false);
769                 }
770                 String text = (String)list.get(0);
771                 if (!_isMatchDataValue(text, child)) {
772                     return (false);
773                 }
774                 list.remove(0);
775             } else if ("data".equals(tagName)) {
776                 if (list.size() == 0) {
777                     return (false);
778                 }
779                 String text = (String)list.get(0);
780                 if (!_isMatchDataData(text, child)) {
781                     return (false);
782                 }
783                 list.remove(0);
784             } else if ("choice".equals(tagName)) {
785                 if (list.size() == 0) {
786                     return (false);
787                 }
788                 String text = (String)list.get(0);
789                 if (!_isMatchDataChoice(text, child)) {
790                     return (false);
791                 }
792                 list.remove(0);
793             } else if ("list".equals(tagName)) {
794                 return (_isMatchDataList(data, child));    
795             } else if ("optional".equals(tagName)) {
796                 if (!_isMatchDataOptional(list, child)) {
797                     return (false);
798                 }
799             } else if ("oneOrMore".equals(tagName)) {
800                 if (!_isMatchDataOneOrMore(list, child)) {
801                     return (false);
802                 }
803             } else if ("zeroOrMore".equals(tagName)) {
804                 if (!_isMatchDataZeroOrMore(list, child)) {
805                     return (false);
806                 }
807             } else {
808                 throw (new InternalError(data + " : " + tagName));
809             }
810         }
811         return (true);
812     }
813 
814     private static boolean _isMatchDataOneOrMore(List list, Element oneOrMore) {
815         if (list.size() == 0) {
816             return (false);
817         }
818         return (_isMatchDataZeroOrMore(list, oneOrMore));
819     }
820 
821     private static boolean _isMatchDataOptional(List list, Element optional) {
822         Element[] children = URelaxer.getElements(optional);
823         Element expr = children[0];
824         String text = (String)list.get(0);
825         if (_isMatchDataData(text, expr)) {
826             list.remove(0);
827         }
828         return (true);
829     }
830 
831     private static boolean _isMatchDataValue(String data, Element value) {
832         String typeName = value.getAttribute("type");
833         String text = URelaxer.getElementPropertyAsString(value);
834         if ("string".equals(typeName)) {
835             return (data.equals(text));
836         } else {
837             return (data.equals(text.trim()));
838         }
839     }
840 
841     private static boolean _isMatchDataZeroOrMore(List list, Element zeroOrMore) {
842         Element[] children = URelaxer.getElements(zeroOrMore);
843         Element expr = children[0];
844         int size = list.size();
845         for (int i = 0; i < size; i++) {
846             String text = (String)list.get(0);
847             if (!_isMatchDataData(text, expr)) {
848                 return (true);
849             }
850             list.remove(0);
851         }
852         return (true);
853     }
854 
855     private static String _normalizePath(String path) {
856         return (path);    
857     }
858 
859     private static void _setup(DocumentBuilderFactory factory, int flags) {
860         factory.setValidating((flags & FLAG_VALIDATION) != 0);
861         factory.setNamespaceAware((flags & FLAG_NAMESPACE_AWARE) != 0);
862     }
863 
864     static class DefaultEntityResolver
865         implements EntityResolver {
866         public InputSource resolveEntity(String publicId, String systemId) {
867             if (!systemId.endsWith(".dtd")) {
868                 URL url = getEntityResource(systemId);
869                 if (url != null) {
870                     return (new InputSource(url.toExternalForm()));
871                 } else {
872                     return (null);
873                 }
874             }
875             if (canAccess(systemId)) {
876                 return (new InputSource(systemId));
877             } else {
878                 URL url = getEntityResource(systemId);
879                 if (url != null) {
880                     return (new InputSource(url.toExternalForm()));
881                 } else {
882                     StringReader reader = new StringReader("");
883                     return (new InputSource(reader));
884                 }
885             }
886         }
887     }
888 
889     static class DefaultErrorHandler
890         implements ErrorHandler {
891         public void error(SAXParseException e) {
892             System.err.print("error : ");
893             System.err.println(e.getMessage());
894         }
895 
896         public void fatalError(SAXParseException e) {
897             System.err.print("fatal error : ");
898             System.err.println(e.getMessage());
899         }
900 
901         public void warning(SAXParseException e) {
902             System.err.print("warning : ");
903             System.err.println(e.getMessage());
904         }
905     }
906 }