update of javajs package; adds org.apache.harmony, org.xml.sax.helpers
authorhansonr <hansonr@stolaf.edu>
Wed, 20 Jun 2018 10:40:46 +0000 (11:40 +0100)
committerhansonr <hansonr@stolaf.edu>
Wed, 20 Jun 2018 10:40:46 +0000 (11:40 +0100)
File format identified as Fasta

86 files changed:
src/jalview/bin/Jalview.java
src/javajs/api/GenericZipTools.java
src/javajs/api/JSInterface.java
src/javajs/api/js/J2SObjectInterface.java
src/javajs/util/A4.java
src/javajs/util/AU.java
src/javajs/util/AjaxURLConnection.java
src/javajs/util/BC.java
src/javajs/util/BS.java
src/javajs/util/BinaryDocument.java
src/javajs/util/CifDataParser.java
src/javajs/util/CompoundDocDirEntry.java
src/javajs/util/DF.java
src/javajs/util/JSJSONParser.java
src/javajs/util/JSONException.java
src/javajs/util/JSThread.java
src/javajs/util/M3.java
src/javajs/util/M34.java
src/javajs/util/M4.java
src/javajs/util/Measure.java
src/javajs/util/MessagePackReader.java
src/javajs/util/OC.java
src/javajs/util/P3.java
src/javajs/util/P3i.java
src/javajs/util/P4.java
src/javajs/util/PT.java
src/javajs/util/Quat.java
src/javajs/util/Rdr.java
src/javajs/util/SB.java
src/javajs/util/T3.java
src/javajs/util/T3d.java
src/javajs/util/T3i.java
src/javajs/util/T4.java
src/javajs/util/V3.java
src/javajs/util/V3d.java
src/javajs/util/ZipData.java
src/javajs/util/ZipTools.java
src/org/apache/harmony/luni/util/ExternalMessages.properties [new file with mode: 0644]
src/org/apache/harmony/luni/util/ExternalMessages.properties.js [new file with mode: 0644]
src/org/apache/harmony/luni/util/Msg.java [new file with mode: 0644]
src/org/apache/harmony/luni/util/MsgHelp.java [new file with mode: 0644]
src/org/apache/tools/bzip2/BZip2Constants.java [new file with mode: 0644]
src/org/apache/tools/bzip2/CBZip2InputStream.java [new file with mode: 0644]
src/org/apache/tools/bzip2/CBZip2InputStreamFactory.java [new file with mode: 0644]
src/org/apache/tools/bzip2/CRC.java [new file with mode: 0644]
src/org/xml/sax/AttributeList.java [new file with mode: 0644]
src/org/xml/sax/Attributes.java [new file with mode: 0644]
src/org/xml/sax/ContentHandler.java [new file with mode: 0644]
src/org/xml/sax/DTDHandler.java [new file with mode: 0644]
src/org/xml/sax/DocumentHandler.java [new file with mode: 0644]
src/org/xml/sax/EntityResolver.java [new file with mode: 0644]
src/org/xml/sax/ErrorHandler.java [new file with mode: 0644]
src/org/xml/sax/HandlerBase.java [new file with mode: 0644]
src/org/xml/sax/InputSource.java [new file with mode: 0644]
src/org/xml/sax/Locator.java [new file with mode: 0644]
src/org/xml/sax/Parser.java [new file with mode: 0644]
src/org/xml/sax/SAXException.java [new file with mode: 0644]
src/org/xml/sax/SAXNotRecognizedException.java [new file with mode: 0644]
src/org/xml/sax/SAXNotSupportedException.java [new file with mode: 0644]
src/org/xml/sax/SAXParseException.java [new file with mode: 0644]
src/org/xml/sax/XMLFilter.java [new file with mode: 0644]
src/org/xml/sax/XMLReader.java [new file with mode: 0644]
src/org/xml/sax/demo/ByteStreamDemo.java [new file with mode: 0644]
src/org/xml/sax/demo/CharacterStreamDemo.java [new file with mode: 0644]
src/org/xml/sax/demo/DemoHandler.java [new file with mode: 0644]
src/org/xml/sax/demo/EntityDemo.java [new file with mode: 0644]
src/org/xml/sax/ext/Attributes2.java [new file with mode: 0644]
src/org/xml/sax/ext/Attributes2Impl.java [new file with mode: 0644]
src/org/xml/sax/ext/DeclHandler.java [new file with mode: 0644]
src/org/xml/sax/ext/DefaultHandler2.java [new file with mode: 0644]
src/org/xml/sax/ext/EntityResolver2.java [new file with mode: 0644]
src/org/xml/sax/ext/LexicalHandler.java [new file with mode: 0644]
src/org/xml/sax/ext/Locator2.java [new file with mode: 0644]
src/org/xml/sax/ext/Locator2Impl.java [new file with mode: 0644]
src/org/xml/sax/helpers/AttributeListImpl.java [new file with mode: 0644]
src/org/xml/sax/helpers/AttributesImpl.java [new file with mode: 0644]
src/org/xml/sax/helpers/DefaultHandler.java [new file with mode: 0644]
src/org/xml/sax/helpers/LocatorImpl.java [new file with mode: 0644]
src/org/xml/sax/helpers/NamespaceSupport.java [new file with mode: 0644]
src/org/xml/sax/helpers/NewInstance.java [new file with mode: 0644]
src/org/xml/sax/helpers/ParserAdapter.java [new file with mode: 0644]
src/org/xml/sax/helpers/ParserFactory.java [new file with mode: 0644]
src/org/xml/sax/helpers/XMLFilterImpl.java [new file with mode: 0644]
src/org/xml/sax/helpers/XMLReaderAdapter.java [new file with mode: 0644]
src/org/xml/sax/helpers/XMLReaderFactory.java [new file with mode: 0644]
src/org/xml/sax/helpers/package.html [new file with mode: 0644]

index 30620a1..2007814 100755 (executable)
@@ -77,6 +77,9 @@ import groovy.util.GroovyScriptEngine;
  */
 public class Jalview
 {
+
+  // BH 6/19/2018 starting to work on JS version - just discovering issues
+
   /*
    * singleton instance of this class
    */
@@ -86,8 +89,14 @@ public class Jalview
 
   public static AlignFrame currentAlignFrame;
 
+  public static boolean isJS = /** @j2sNative true || */ // BH 2018
+          false;
+
   static
   {
+
+    if (!isJS)
+    { // BH 2018
     // grab all the rights we can the JVM
     Policy.setPolicy(new Policy()
     {
@@ -104,6 +113,8 @@ public class Jalview
       {
       }
     });
+
+    }
   }
 
   /**
@@ -188,7 +199,12 @@ public class Jalview
    */
   void doMain(String[] args)
   {
-    System.setSecurityManager(null);
+
+    if (!isJS)
+    {
+      System.setSecurityManager(null);
+    }
+
     System.out
             .println("Java version: " + System.getProperty("java.version"));
     System.out.println(System.getProperty("os.arch") + " "
index a0b0993..47a2da2 100644 (file)
@@ -15,6 +15,8 @@ public interface GenericZipTools {
 
   public InputStream newGZIPInputStream(InputStream bis) throws IOException;
 
+  public InputStream newBZip2InputStream(InputStream bis) throws IOException;
+
   public Object getZipFileDirectory(BufferedInputStream bis,
                                           String[] subFileList, int listPtr, boolean asBufferedInputStream);
 
index d824543..0f785fa 100644 (file)
@@ -19,6 +19,7 @@ public interface JSInterface {
   void setScreenDimension(int width, int height);
   boolean setStatusDragDropped(int mode, int x, int y, String fileName);
        void startHoverWatcher(boolean enable);
+       void update();
 
        // these are not general methods
 //Object getGLmolView();
index fbe126d..687f642 100644 (file)
@@ -1,7 +1,7 @@
 package javajs.api.js;
 
 /**
- * methods in JSmol JavaScript accessed in Jmol (aka J2S) 
+ * methods in JSmol JavaScript accessed in Jmol 
  */
 public interface J2SObjectInterface {
 
index df173a6..d20b6c2 100644 (file)
@@ -34,8 +34,7 @@ import javajs.util.T3;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  */
 public class A4 implements JSONEncodable, Serializable {
 
@@ -44,11 +43,6 @@ public class A4 implements JSONEncodable, Serializable {
    */
 
   /**
-        * 
-        */
-       private static final long serialVersionUID = 1L;
-
-/**
    * The x coordinate.
    */
   public float x;
index cd4ed03..f873116 100644 (file)
@@ -139,7 +139,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     *     if (Clazz.newArray$ && newLength < oldLength) return Clazz.newArray$(-1, array, 0, newLength);
+     *     if (newLength < oldLength) return Clazz.array(-1, array, 0, newLength);
      */
     {}
     Object t = newInstanceO(array, newLength);
@@ -181,7 +181,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     *     if (Clazz.newArray$ && newLength < oldLength) return Clazz.newArray$(-1, array, 0, newLength);
+     *     if (newLength < oldLength) return Clazz.array(-1, array, 0, newLength);
      */
     {}
     String[] t = new String[newLength];
@@ -220,7 +220,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     *     if (Clazz.newArray$ && newLength < oldLength) return Clazz.newArray$(-1, array, 0, newLength);
+     *     if (newLength < oldLength) return Clazz.array(-1, array, 0, newLength);
      */
     {}
     float[] t = new float[newLength];
@@ -237,7 +237,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     *     if (Clazz.newArray$ && newLength < oldLength) return Clazz.newArray$(-1, array, 0, newLength);
+     *     if (newLength < oldLength) return Clazz.array(-1, array, 0, newLength);
      */
     {}
     int[] t = new int[newLength];
@@ -265,7 +265,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     * if (Clazz.newArray$) return Clazz.newArray$(-1, array, i0, n);
+     * return Clazz.array(-1, array, i0, n);
      * 
      */
     {
@@ -282,7 +282,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     * if (Clazz.newArray$) return Clazz.newArray$(-1, array, i0, n).reverse();
+     * return Clazz.array(-1, array, i0, n).reverse();
      */
     {
     }
@@ -300,7 +300,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     *     if (Clazz.newArray$ && newLength < oldLength) return Clazz.newArray$(-1, array, 0, newLength);
+     *     if (newLength < oldLength) return Clazz.array(-1, array, 0, newLength);
      */
     {}
     short[] t = new short[newLength];
@@ -317,7 +317,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     *     if (Clazz.newArray$ && newLength < oldLength) return Clazz.newArray$(-1, array, 0, newLength);
+     *     if (newLength < oldLength) return Clazz.array(-1, array, 0, newLength);
      */
     {}
     byte[] t = new byte[newLength];
@@ -334,7 +334,7 @@ final public class AU {
     /**
      * @j2sNative
      * 
-     *     if (Clazz.newArray$ && newLength < oldLength) return Clazz.newArray$(-1, array, 0, newLength);
+     *     if (newLength < oldLength) return Clazz.array(-1, array, 0, newLength);
      */
     {}
     boolean[] t = new boolean[newLength];
index cef98c8..0b038c3 100644 (file)
@@ -6,7 +6,6 @@ import java.io.InputStream;
 import java.net.URL;
 import java.net.URLConnection;
 
-import javajs.api.ResettableStream;
 import javajs.api.js.J2SObjectInterface;
 
 /**
@@ -35,6 +34,9 @@ public class AjaxURLConnection extends URLConnection {
    * the method is "private", but in JavaScript that can still be overloaded.
    * Just set something to org.jmol.awtjs.JmolURLConnection.prototype.doAjax
    * 
+   * 
+   * @param isBinary 
+   * 
    * @return file data as a javajs.util.SB or byte[] depending upon the file
    *         type.
    * 
@@ -42,16 +44,16 @@ public class AjaxURLConnection extends URLConnection {
    */
   @SuppressWarnings("null")
   private Object doAjax(boolean isBinary) {
-    J2SObjectInterface jmol = null;
+    J2SObjectInterface j2s = null;
     /**
      * @j2sNative
      * 
-     *            jmol = J2S || Jmol;
+     *            j2s = J2S;
      * 
      */
     {
     }
-    return jmol._doAjax(url, postOut, bytesOut, isBinary);
+    return j2s._doAjax(url, postOut, bytesOut, isBinary);
   }
 
   @Override
@@ -71,48 +73,44 @@ public class AjaxURLConnection extends URLConnection {
 
        @Override
        public InputStream getInputStream() {
-               BufferedInputStream bis = getAttachedStreamData(url);
-               if (bis != null)
-                       return bis;
-               Object o = doAjax(true);
-               return (
-                               AU.isAB(o) ? Rdr.getBIS((byte[]) o) 
-                               : o instanceof SB ? Rdr.getBIS(Rdr.getBytesFromSB((SB) o)) 
-                               : o instanceof String ? Rdr.getBIS(((String) o).getBytes()) 
-                               : bis
-               );
+               BufferedInputStream is = getAttachedStreamData(url, false);
+               return (is == null ? attachStreamData(url, doAjax(true)) : is);
        }
-  @SuppressWarnings("unused")
+
        /**
-        * J2S will attach a BufferedInputStream to any URL that is 
+        * J2S will attach the data (String, SB, or byte[]) to any URL that is 
         * retrieved using a ClassLoader. This improves performance by
         * not going back to the server every time a second time, since
         * the first time in Java is usually just to see if it exists. 
         * 
-        * This stream can be re-used, but it has to be reset. Java for some 
-        * reason does not allow  a BufferedInputStream to fully reset its 
-        * inner streams. We enable that by force-casting the stream as a 
-        * javax.io stream and then applying resetStream() to that. 
-        * 
-        * 
         * @param url
-        * @return
+        * @return String, SB, or byte[]
         */
-       public static BufferedInputStream getAttachedStreamData(URL url) {
-               BufferedInputStream bis = null;
+       public static BufferedInputStream getAttachedStreamData(URL url, boolean andDelete) {
+       
+               Object data = null;
                /**
                 * @j2sNative
                 * 
-                *            bis = url._streamData;
+                *       data = url._streamData;
+                *       if (andDelete) url._streamData = null;
                 */
                {
                }
-               if (bis != null)
-                       ((ResettableStream) (Object) bis).resetStream();
-               return bis;
+               return (data == null ? null : Rdr.toBIS(data));
        }
 
-       /**
+   public static BufferedInputStream attachStreamData(URL url, Object o) {
+          /**
+           * @j2sNative
+           * 
+           *   url._streamData = o;
+           */
+          
+           return (o == null ? null : Rdr.toBIS(o));
+  }
+
+  /**
    * @return javajs.util.SB or byte[], depending upon the file type
    */
   public Object getContents() {
index df9c9f9..5722efd 100644 (file)
@@ -66,7 +66,7 @@ public class BC {
      *       if (o.fracIEEE == null)
      *         o.setFracIEEE();
      *       var m = ((x & 0x7F800000) >> 23);
-     *       return ((x & 0x80000000) == 0 ? 1 : -1) * o.shiftIEEE((x & 0x7FFFFF) | 0x800000, m - 149);
+     *       return ((x & 0x80000000) == 0 ? 1 : -1) * o.shiftIEEE$D$I((x & 0x7FFFFF) | 0x800000, m - 149);
      *  
      */
     {
@@ -96,7 +96,6 @@ public class BC {
         
       /**
        * @j2sNative
-       *       var o = javajs.util.BC;
        *       var b1, b2, b3, b4, b5;
        *       
        *       if (isBigEndian) {
@@ -115,8 +114,8 @@ public class BC {
        *       var s = ((b1 & 0x80) == 0 ? 1 : -1);
        *       var e = (((b1 & 0x7F) << 4) | (b2 >> 4)) - 1026;
        *       b2 = (b2 & 0xF) | 0x10;
-       *       return s * (o.shiftIEEE(b2, e) + o.shiftIEEE(b3, e - 8) + o.shiftIEEE(b4, e - 16)
-       *         + o.shiftIEEE(b5, e - 24));
+       *       return s * (C$.shiftIEEE$D$I(b2, e) +C$.shiftIEEE$D$I(b3, e - 8) + C$.shiftIEEE$D$I(b4, e - 16)
+       *         + C$.shiftIEEE$D$I(b5, e - 24));
        */
       {
         double d;
index 0bfa5a6..1f3aaa4 100644 (file)
@@ -79,7 +79,7 @@ import javajs.api.JSONEncodable;
  */
 public class BS implements Cloneable, JSONEncodable {
   /*
-   * BitSets are packed into arrays of "wrangeords."
+   * BitSets are packed into arrays of "words."
    * 
    * An int, which consists of 32 bits, requiring 5 address bits, is used for
    * the JavaScript port.
@@ -736,7 +736,7 @@ public class BS implements Cloneable, JSONEncodable {
      * @j2sNative
      *     if (n == this.words.length) return;
      *     if (n == this.wordsInUse) {
-     *      this.words = Clazz.newArray$(-1, this.words, 0, n);
+     *      this.words = Clazz.array(-1, this.words, 0, n);
      *      return;
      *     }
      */
@@ -818,7 +818,7 @@ public class BS implements Cloneable, JSONEncodable {
        * 
        * @j2sNative
        * 
-       *   bs.words = Clazz.newArray(-1, bitsetToCopy.words, 0, bs.wordsInUse = wordCount);
+       *   bs.words = Clazz.array(-1, bitsetToCopy.words, 0, bs.wordsInUse = wordCount);
        * 
        */
       {
@@ -907,11 +907,11 @@ public class BS implements Cloneable, JSONEncodable {
       return null;
     len -= 2;
     for (int i = len; --i >= 2;)
-      if (!PT.isDigit(ch = str.charAt(i)) && ch != ' ' && ch != '\t'
+      if (((ch = str.charAt(i)) < 48 || ch > 57) && ch != ' ' && ch != '\t'
           && ch != ':')
         return null;
     int lastN = len;
-    while (PT.isDigit(str.charAt(--lastN))) {
+    while (48 <= (ch = str.charAt(--lastN)) && ch <= 57) {
       // loop
     }
     if (++lastN == len)
@@ -947,7 +947,7 @@ public class BS implements Cloneable, JSONEncodable {
         iThis = -2;
         break;
       default:
-        if (PT.isDigit(ch)) {
+        if (48 <= ch && ch <= 57) {
           if (iThis < 0)
             iThis = 0;
           iThis = (iThis * 10) + (ch - 48);
index 7ac5a56..73ec57b 100644 (file)
@@ -262,6 +262,7 @@ public class BinaryDocument extends BC implements GenericBinaryDocument {
     return intToFloat(readInt());
   }
 
+  @SuppressWarnings("unused")
   @Override
   public double readDouble() throws IOException {
     /**
@@ -270,14 +271,17 @@ public class BinaryDocument extends BC implements GenericBinaryDocument {
      * 
      * @j2sNative
      * 
-     * this.readByteArray(this.t8, 0, 8);
-     * return this.bytesToDoubleToFloat(this.t8, 0, this.isBigEndian);
-     *  
+     * 
      */
     {
       nBytes += 8;
-      return (isBigEndian ? ioReadDouble() : Double.longBitsToDouble(readLELong()));  
+      if (true)
+        return (isBigEndian ? ioReadDouble()
+            : Double.longBitsToDouble(readLELong()));
     }
+    // this is the JavaScript-only part
+    this.readByteArray(this.t8, 0, 8);
+    return bytesToDoubleToFloat(this.t8, 0, this.isBigEndian);
   }
   
   private double ioReadDouble() throws IOException {
index 5be12fd..51e969c 100644 (file)
@@ -658,10 +658,10 @@ public class CifDataParser implements GenericCifDataParser {
   public String fixKey(String key) {
     // PRELIMINARY -- BilBao _magnetic
     // PRELIMINARY -- Jana2006
-    return (PT.rep(
+    return (
         key.startsWith("_magnetic") ? key.substring(9) 
             : key.startsWith("_jana") ? key.substring(5) 
-            : key, ".", "_").toLowerCase());
+            : key).replace('.', '_').toLowerCase();
   }
 
   //////////////////// private methods ////////////////////
index e60b874..a57f6af 100644 (file)
@@ -93,4 +93,9 @@ class CompoundDocDirEntry {
     //System.out.println(entryName + " type " + entryType);
     return true;
   }
+  
+  @Override
+  public String toString() {
+    return entryName + " " + lenStream;
+  }
 }
\ No newline at end of file
index 1d8a2f1..b5c8717 100644 (file)
@@ -73,7 +73,7 @@ public class DF {
       if (decimalDigits > formattingStrings.length)
         decimalDigits = formattingStrings.length;
       if (value == 0)
-        return formattingStrings[decimalDigits] + "E+0";
+        return formattingStrings[decimalDigits - 1] + "E+0";
       //scientific notation
       n = 0;
       double d;
@@ -87,9 +87,19 @@ public class DF {
       String s = ("" + d).toUpperCase();
       int i = s.indexOf("E");
       n = PT.parseInt(s.substring(i + 1)) + n;
-      return (i < 0 ? "" + value : formatDecimal(PT.parseFloat(s.substring(
-          0, i)), decimalDigits - 1)
-          + "E" + (n >= 0 ? "+" : "") + n);
+      String sf;
+      if (i < 0) {
+        sf = "" + value;
+      } else {
+        float f = PT.parseFloat(s.substring(0, i));
+        if (f == 10 || f == -10) {
+          //d = 9.99999997465; n = -6 --> 10.00000E-5
+          f /= 10;
+          n += (n < 0 ? 1 : -1);          
+        }
+        sf = formatDecimal(f, decimalDigits - 1);
+      }
+      return sf  + "E" + (n >= 0 ? "+" : "") + n;
     }
   
     if (decimalDigits >= formattingStrings.length)
index ce580e0..552270d 100644 (file)
@@ -4,9 +4,6 @@ import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Map;
 
-import javajs.J2SIgnoreImport;
-
-
 
 /**
  * a very simple JSON parser for JSON objects that are compatible with JavaScript
@@ -23,7 +20,6 @@ import javajs.J2SIgnoreImport;
  *  @author Bob Hanson
  *  
  */
-@J2SIgnoreImport({ HashMap.class })
 public class JSJSONParser {
 
   private String str;
@@ -59,11 +55,13 @@ public class JSJSONParser {
    * Could return Integer, Float, Boolean, String, Map<String, Object>, Lst<Object>, or null
    * 
    * @param str
+   * @param asHashTable 
    * @return a object equivalent to the JSON string str
    * 
    */
-  public Object parse(String str) {
+  public Object parse(String str, boolean asHashTable) {
     index = 0;
+    this.asHashTable = asHashTable;
     this.str = str;
     len = str.length();
     return getValue(false);
@@ -143,7 +141,7 @@ public class JSJSONParser {
     if (isKey && c == 0)
       throw new JSONException("invalid key");
 
-    String string = str.substring(i, index);
+    String string = str.substring(i, index).trim();
 
     // check for the only valid simple words: true, false, null (lower case)
     // and in this case, only for 
@@ -160,7 +158,6 @@ public class JSJSONParser {
       }
     }
     //  only numbers from here on:
-
     c = string.charAt(0);
     if (c >= '0' && c <= '9' || c == '-')
       try {
@@ -280,7 +277,7 @@ public class JSJSONParser {
     switch (getChar()) {
     case ']':
       return l;
-    case 0:
+    case '\0':
       throw new JSONException("invalid array");
     }
     returnChar();
index 157f100..58af722 100644 (file)
@@ -1,12 +1,7 @@
 package javajs.util;
 
 public class JSONException extends RuntimeException {
-    /**
-        * 
-        */
-       private static final long serialVersionUID = 1L;
-
-       public JSONException(String message) {
+    public JSONException(String message) {
         super(message);
     }
 
index c2f3c4d..be94c00 100644 (file)
@@ -200,7 +200,9 @@ public abstract class JSThread extends Thread implements JSFunction {
                 * @j2sNative
                 * 
                 *            setTimeout(
-                *              function() {java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent$java_awt_AWTEvent(Clazz.new(java.awt.event.InvocationEvent.c$$O$Runnable,[me, r]))}, 
+                *              function() {
+                *              java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent$java_awt_AWTEvent(
+                *              Clazz.new_(java.awt.event.InvocationEvent.c$$O$Runnable,[me, r]))}, 
                 *              delay);
                 * 
                 */
index 7749277..88f6f4e 100644 (file)
@@ -27,15 +27,19 @@ import java.io.Serializable;
  * 
  *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
  *         constructor and method names for the optimization of compiled
- *         JavaScript using Java2Script.
- *
+ *         JavaScript using Java2Script
  *         
  *         
  */
-@SuppressWarnings("serial")
 public class M3 extends M34 implements Serializable {
 
   /**
+   * Constructs and initializes a Matrix3f to all zeros.
+   */
+  public M3() {
+  }
+
+  /**
    * Constructs and initializes a Matrix3f from the specified 9 element array.
    * this.m00 =v[0], this.m01=v[1], etc.
    * 
index b0882dd..260a82c 100644 (file)
@@ -7,8 +7,7 @@ package javajs.util;
  * 
  *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
  *         constructor and method names for the optimization of compiled
- *         JavaScript using Java2Script.
- * and for subclassing to M3 and M4
+ *         JavaScript using Java2Script and for subclassing to M3 and M4
  * 
  */
 public abstract class M34 {
index 1f16335..58bd355 100644 (file)
@@ -23,8 +23,7 @@ package javajs.util;
  * 
  *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
  *         constructor and method names for the optimization of compiled
- *         JavaScript using Java2Script.
- *
+ *         JavaScript using Java2Script
  */
 public class M4 extends M34 {
 
@@ -63,6 +62,9 @@ public class M4 extends M34 {
    */
   public float m33 = 0;
 
+  /**
+   * all zeros
+   */
   public M4() {
   }
   /**
index 8fd799b..8b21cfe 100644 (file)
@@ -235,7 +235,6 @@ final public class Measure {
   }
   
   /**
-   * if vAC is dispensible vNorm can be vAC
    * @param pointA
    * @param pointB
    * @param pointC
index e9cdb7b..a0e6b8b 100644 (file)
@@ -1,5 +1,7 @@
 package javajs.util;
 
+import java.io.BufferedInputStream;
+import java.io.InputStream;
 import java.util.Hashtable;
 import java.util.Map;
 
@@ -91,6 +93,17 @@ public class MessagePackReader {
     doc = binaryDoc;
   }
 
+  public MessagePackReader() {
+    // for reflection
+  }
+  
+  public Map<String, Object> getMapForStream(BufferedInputStream is) throws Exception {
+    doc = new BinaryDocument().setStream(is, true);
+    Map<String, Object> map = readMap();
+    is.close();
+    return map;
+  }
+  
   @SuppressWarnings("unchecked")
   public Map<String, Object> readMap() throws Exception {
     return (Map<String, Object>) getNext(null, 0);
index 81cda57..98151d1 100644 (file)
@@ -6,7 +6,6 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 
-import javajs.J2SIgnoreImport;
 import javajs.api.BytePoster;
 import javajs.api.GenericOutputChannel;
 import javajs.api.js.J2SObjectInterface;
@@ -44,7 +43,6 @@ import javajs.api.js.J2SObjectInterface;
  *  
  */
 
-@J2SIgnoreImport({ java.io.FileOutputStream.class })
 public class OC extends OutputStream implements GenericOutputChannel {
  
   private BytePoster bytePoster; // only necessary for writing to http:// or https://
@@ -84,7 +82,7 @@ public class OC extends OutputStream implements GenericOutputChannel {
     this.fileName = fileName;
     this.os = os;
     isLocalFile = (fileName != null && !isRemote(fileName));
-    if (asWriter && !isBase64 && os != null)
+    if (asWriter && !isBase64 && os != null) 
        bw = Rdr.getBufferedWriter(os, null);
     return this;
   }
index edfebfe..1e1dfdb 100644 (file)
@@ -28,12 +28,15 @@ package javajs.util;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  * 
  */
 public class P3 extends T3 {
 
+  public P3() {
+    // ignore T3
+  }
+  
   public static P3 newP(T3 t) {
     P3 p = new P3();
     p.x = t.x;
index 381aede..8f39550 100644 (file)
@@ -29,8 +29,7 @@ package javajs.util;
  * 
  *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
  *         constructor and method names for the optimization of compiled
- *         JavaScript using Java2Script.
- *
+ *         JavaScript using Java2Script
  */
 public class P3i extends T3i {
 
index 2145696..6478602 100644 (file)
@@ -28,11 +28,14 @@ package javajs.util;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  */
 public class P4 extends T4 {
 
+  public P4() {
+    // skip T4() constructor
+  }
+  
   public static P4 new4(float x, float y, float z, float w) {
     P4 pt = new P4();
     pt.set4(x, y, z, w);
index c544967..81653cf 100644 (file)
@@ -31,7 +31,6 @@ import java.lang.reflect.Array;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import javajs.J2SIgnoreImport;
 import javajs.api.JSONEncodable;
 
 /**
@@ -41,7 +40,6 @@ import javajs.api.JSONEncodable;
  * 
  */
 
-@J2SIgnoreImport(value = { java.lang.reflect.Array.class })
 public class PT {
 
   public static int parseInt(String str) {
@@ -427,33 +425,34 @@ public class PT {
     return (ichLast < ich ? "" : str.substring(ich, ichLast + 1));
   }
 
-  public static double dVal(String s) throws NumberFormatException {
-    /**
-     * @j2sNative
-     * 
-     * if(s==null)
-     *   throw new NumberFormatException("null");
-     * var d=parseFloat(s);
-     * if(isNaN(d))
-     *  throw new NumberFormatException("Not a Number : "+s);
-     * return d 
-     * 
-     */
-    {
-      return Double.valueOf(s).doubleValue();
-    }
-  }
-
-  public static float fVal(String s) throws NumberFormatException {
-    /**
-     * @j2sNative
-     * 
-     * return this.dVal(s);
-     */
-    {
-      return Float.parseFloat(s);
-    }
-  }
+//  public static double dVal(String s) throws NumberFormatException {
+//    /**
+//     * @j2sNative
+//     * 
+//     * if(s==null)
+//     *   throw new NumberFormatException("null");
+//     * var d=parseFloat(s);
+//     * if(isNaN(d))
+//     *  throw new NumberFormatException("Not a Number : "+s);
+//     * return d 
+//     * 
+//     */
+//    {
+//      return Double.valueOf(s).doubleValue();
+//    }
+//  }
+//
+//  public static float fVal(String s) throws NumberFormatException {
+//    /**
+//     * @j2sNative
+//     * 
+//     * return this.dVal(s);
+//     */
+//    {
+//      
+//      return Float.parseFloat(s);
+//    }
+//  }
 
   public static int parseIntRange(String str, int ichMax, int[] next) {
     int cch = str.length();
@@ -567,6 +566,34 @@ public class PT {
   }
   
   /**
+   * single- or double-quoted string or up to the first space -- like HTML5
+   * not case-sensitive
+   * 
+   * @param line
+   * @param key
+   * @return attribute
+   */
+  public static String getQuotedOrUnquotedAttribute(String line, String key) {
+    if (line == null || key == null)
+      return null;
+    int pt = line.toLowerCase().indexOf(key.toLowerCase() + "=");
+    if (pt < 0 || (pt = pt + key.length() + 1) >= line.length())
+      return "";
+    char c = line.charAt(pt);
+    switch (c) {
+    case '\'':
+    case '"':
+      pt++;
+      break;
+    default:
+      c = ' ';
+      line += " ";
+    }
+    int pt1 = line.indexOf(c, pt);
+    return (pt1 < 0 ? null : line.substring(pt, pt1));
+  }
+  
+  /**
    * CSV format -- escaped quote is "" WITHIN "..."
    *
    * 
@@ -763,21 +790,21 @@ public class PT {
     return info instanceof Number || info instanceof Boolean;
   }
 
-  private static Object arrayGet(Object info, int i) {
-    /**
-     * 
-     * Note that info will be a primitive in JavaScript
-     * but a wrapped primitive in Java.
-     * 
-     * @j2sNative
-     * 
-     *            return info[i];
-     */
-    {
-      return Array.get(info, i);
-    }
-  }
-  
+//  private static Object arrayGet(Object info, int i) {
+//    /**
+//     * 
+//     * Note that info will be a primitive in JavaScript
+//     * but a wrapped primitive in Java.
+//     * 
+//     * @j2sNative
+//     * 
+//     *            return info[i];
+//     */
+//    {
+//      return Array.get(info, i);
+//    }
+//  }
+//  
   @SuppressWarnings("unchecked")
   public static String toJSON(String infoType, Object info) {
     if (info == null)
@@ -855,7 +882,7 @@ public class PT {
         for (int i = 0; i < n; i++) {
           if (i > 0)
             sb.appendC(',');
-          sb.append(toJSON(null, arrayGet(info, i)));
+          sb.append(toJSON(null, Array.get(info, i)));
         }
         sb.append("]");
         break;
@@ -876,7 +903,7 @@ public class PT {
     /**
      * @j2sNative
      * 
-     * return (x.constructor == Array || x.__BYTESIZE ? null : x.toString());
+     * return (x.constructor == Array || x.BYTES_PER_ELEMENT ? null : x.toString());
      * 
      */
     {
index 5777308..d4a7bf9 100644 (file)
@@ -524,7 +524,7 @@ public class Quat {
    * @return 0 <= angle <= 180 in degrees
    */
   public float getTheta() {
-    return (float) (Math.acos(Math.abs(q0)) * (2 * 180 / Math.PI));
+    return (float) (Math.acos(Math.abs(q0)) * 2 * 180 / Math.PI);
   }
 
   public float getThetaRadians() {
index c357581..995a629 100644 (file)
@@ -43,7 +43,6 @@ import java.util.Map;
 import javajs.api.Interface;
 
 
-import javajs.J2SIgnoreImport;
 import javajs.api.GenericCifDataParser;
 import javajs.api.GenericLineReader;
 import javajs.api.GenericZipTools;
@@ -62,9 +61,28 @@ import javajs.api.GenericZipTools;
  * 
  * 
  */
-@J2SIgnoreImport(BufferedWriter.class)
 public class Rdr implements GenericLineReader {
 
+  public static class StreamReader extends BufferedReader {
+
+    private BufferedInputStream stream;
+
+    public StreamReader(BufferedInputStream bis, String charSet) throws UnsupportedEncodingException {
+      super(new InputStreamReader(bis, (charSet == null ? "UTF-8" : charSet)));
+      stream = bis;
+    }
+    
+    public BufferedInputStream getStream() {
+      try {
+        stream.reset();
+      } catch (IOException e) {
+        // ignore
+      }
+      return stream;
+    }
+
+  }
+
   BufferedReader reader;
 
   public Rdr(BufferedReader reader) {
@@ -89,7 +107,7 @@ public class Rdr implements GenericLineReader {
    * Read a UTF-8 byte array fully, converting it to a String.
    * Called by Jmol's XMLReaders
    * 
-   * @param bis
+   * @param bytes
    * @return a UTF-8 string
    */
   public static String bytesToUTF8String(byte[] bytes) {
@@ -126,7 +144,7 @@ public class Rdr implements GenericLineReader {
       throws IOException {
     // could also just make sure we have a buffered input stream here.
     if (getUTFEncodingForStream(bis) == Encoding.NONE)
-      return new BufferedReader(new InputStreamReader(bis, (charSet == null ? "UTF-8" : charSet)));
+      return new StreamReader(bis, (charSet == null ? "UTF-8" : charSet));
     byte[] bytes = getLimitedStreamBytes(bis, -1);
     bis.close();
     return getBR(charSet == null ? fixUTF(bytes) : new String(bytes, charSet));
@@ -136,7 +154,7 @@ public class Rdr implements GenericLineReader {
    * This method is specifically for strings that are marked for UTF 8 or 16.
    * 
    * @param bytes
-   * @return
+   * @return UTF-decoded bytes
    */
        public static String fixUTF(byte[] bytes) {
                Encoding encoding = getUTFEncoding(bytes);
@@ -181,14 +199,14 @@ public class Rdr implements GenericLineReader {
   
 
   private static Encoding getUTFEncodingForStream(BufferedInputStream is) throws IOException {
-    /**
-     * @j2sNative
-     * 
-     *  is.resetStream();
-     * 
-     */
-    {
-    }
+//    /**
+//     * @j2sNative
+//     * 
+//     *  is.resetStream();
+//     * 
+//     */
+//    {
+//    }
     byte[] abMagic = new byte[4];
     abMagic[3] = 1;
     try{
@@ -217,10 +235,19 @@ public class Rdr implements GenericLineReader {
         && (bytes[7] & 0xFF) == 0xE1);
   }
 
+  public static boolean isBZip2S(InputStream is) {
+    return isBZip2B(getMagic(is, 3));
+  }
+
   public static boolean isGzipS(InputStream is) {
     return isGzipB(getMagic(is, 2));
   }
 
+  public static boolean isBZip2B(byte[] bytes) {    
+    return (bytes != null && bytes.length >= 3  // BZh
+        && (bytes[0] & 0xFF) == 0x42 && (bytes[1] & 0xFF) == 0x5A  && (bytes[2] & 0xFF) == 0x68);
+}
+
   public static boolean isGzipB(byte[] bytes) {    
       return (bytes != null && bytes.length >= 2 
           && (bytes[0] & 0xFF) == 0x1F && (bytes[1] & 0xFF) == 0x8B);
@@ -236,12 +263,16 @@ public class Rdr implements GenericLineReader {
   }
 
   public static boolean isMessagePackS(InputStream is) {
-    return isMessagePackB(getMagic(is, 1));
+    return isMessagePackB(getMagic(is, 2));
   }
 
   public static boolean isMessagePackB(byte[] bytes) {
-    // look for 'map' start
-    return (bytes != null && bytes.length >= 1 && (bytes[0] & 0xFF) == 0xDE);
+    // look for 'map' start, but PNG files start with 0x89, which is
+    // the MessagePack start for a 9-member map, so in that case we have
+    // to check that the next byte is not "P" as in <89>PNG
+    int b;
+    
+    return (bytes != null && bytes.length >= 1 && (((b = bytes[0] & 0xFF)) == 0xDE || (b & 0xE0) == 0x80 && bytes[1] != 0x50));
   }
 
   public static boolean isPngZipStream(InputStream is) {
@@ -253,6 +284,11 @@ public class Rdr implements GenericLineReader {
     return (bytes[50] == 0 && bytes[51] == 0x50 && bytes[52] == 0x4E && bytes[53] == 0x47 && bytes[54] == 0x4A);
   }
 
+  /**
+   * Check for a ZIP input stream - starting with "PK<03><04>"
+   * @param is
+   * @return true if a ZIP stream
+   */
   public static boolean isZipS(InputStream is) {
     return isZipB(getMagic(is, 4));
   }
@@ -266,15 +302,15 @@ public class Rdr implements GenericLineReader {
   }
 
   public static byte[] getMagic(InputStream is, int n) {
-    byte[] abMagic = new byte[n];    
-    /**
-     * @j2sNative
-     * 
-     * is.resetStream();
-     * 
-     */
-    {
-    }
+    byte[] abMagic = new byte[n];
+//    /**
+//     * @j2sNative
+//     * 
+//     * is.resetStream();
+//     * 
+//     */
+//    {
+//    }
     try {
       is.mark(n + 1);
       is.read(abMagic, 0, n);
@@ -314,6 +350,14 @@ public class Rdr implements GenericLineReader {
     return new BufferedReader(new StringReader(string));
   }
 
+  
+       public static BufferedInputStream toBIS(Object o) {
+               return (AU.isAB(o) ? getBIS((byte[]) o)
+                               : o instanceof SB ? getBIS(Rdr.getBytesFromSB((SB) o))
+                                               : o instanceof String ? getBIS(((String) o).getBytes()) : null);
+       }
+
+
   /**
    * Drill down into a GZIP stack until no more layers.
    * @param jzt 
@@ -329,6 +373,14 @@ public class Rdr implements GenericLineReader {
     return bis;
   }
 
+  public static BufferedInputStream getUnzippedInputStreamBZip2(GenericZipTools jzt,
+                                                                BufferedInputStream bis) throws IOException  {
+    while (isBZip2S(bis))
+      bis = new BufferedInputStream(jzt.newBZip2InputStream(bis));
+    return bis;
+  }
+
+
   /**
    * Allow for base64-encoding check.
    * 
@@ -544,7 +596,9 @@ public class Rdr implements GenericLineReader {
 
        public static BufferedWriter getBufferedWriter(OutputStream os, String charSetName) {
                OutputStreamWriter osw = (OutputStreamWriter) Interface.getInstanceWithParams("java.io.OutputStreamWriter", 
-                               new Class<?>[] { java.io.OutputStream.class, String.class }, new Object[] {os, charSetName});
+                               new Class<?>[] { java.io.OutputStream.class, String.class }, 
+                               new Object[] { os, charSetName == null ? "UTF-8" : charSetName }
+               );
                /**
                 * @j2sNative
                 * return osw.getBufferedWriter();
index 578acf4..aed71f3 100644 (file)
@@ -3,8 +3,6 @@ package javajs.util;
 
 import java.nio.charset.Charset;
 
-import javajs.J2SIgnoreImport;
-
 /**
  * Interesting thing here is that JavaScript is 3x faster than Java in handling strings.
  * 
@@ -14,7 +12,6 @@ import javajs.J2SIgnoreImport;
  * 
  */
 
-@J2SIgnoreImport({java.lang.StringBuilder.class, java.nio.charset.Charset.class})
 public class SB {
   
   private java.lang.StringBuilder sb;
@@ -310,8 +307,8 @@ public class SB {
   }
 
   /**
-   * simple byte conversion properly implementing UTF-8. 
-   * Used for base64 conversion and allows for offset
+   * simple byte conversion properly implementing UTF-8. * Used for base64
+   * conversion and allows for offset
    * 
    * @param off
    * @param len
index bac7404..6cd5108 100644 (file)
@@ -16,6 +16,8 @@
 */
 package javajs.util;
 
+import java.io.Serializable;
+
 import javajs.api.JSONEncodable;
 
 /**
@@ -28,13 +30,15 @@ import javajs.api.JSONEncodable;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  */
-public abstract class T3 implements JSONEncodable {
+public abstract class T3 implements JSONEncodable, Serializable {
 
   public float x, y, z;
 
+  public T3() {
+  }
+
   /**
    * Sets the value of this tuple to the specified xyz coordinates.
    * 
@@ -296,7 +300,7 @@ public abstract class T3 implements JSONEncodable {
     return (int) (bits ^ (bits >> 32));
   }
 
-  static int floatToIntBits(float x) {
+  public static int floatToIntBits(float x) {
     return (x == 0 ? 0 : Float.floatToIntBits(x));
   }
 
index 549b3df..08d02d7 100644 (file)
@@ -16,6 +16,8 @@
 */
 package javajs.util;
 
+import java.io.Serializable;
+
 /**
  * A generic 3 element tuple that is represented by double precision floating
  * point x,y and z coordinates.
@@ -26,10 +28,9 @@ package javajs.util;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  */
-public abstract class T3d {
+public abstract class T3d implements Serializable {
   /**
    * The x coordinate.
    */
index fc9fd96..7fbd3bb 100644 (file)
@@ -16,6 +16,8 @@
 */
 package javajs.util;
 
+import java.io.Serializable;
+
 /**
  * A 3-element tuple represented by signed integer x,y,z coordinates.
  * 
@@ -26,10 +28,9 @@ package javajs.util;
  * 
  *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
  *         constructor and method names for the optimization of compiled
- *         JavaScript using Java2Script.
- *
+ *         JavaScript using Java2Script
  */
-public abstract class T3i {
+public abstract class T3i implements Serializable {
 
   /**
    * The x coordinate.
index 535dd08..21b2741 100644 (file)
@@ -26,8 +26,7 @@ package javajs.util;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  */
 public abstract class T4 extends T3 {
 
@@ -37,6 +36,13 @@ public abstract class T4 extends T3 {
   public float w;
 
   /**
+   * Constructs and initializes a Tuple4f to (0,0,0,0).
+   * 
+   */
+  public T4() {
+  }
+
+  /**
    * Sets the value of this tuple to the specified xyzw coordinates.
    * 
    * @param x
index edc8451..51325d2 100644 (file)
@@ -28,11 +28,13 @@ package javajs.util;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  */
 public class V3 extends T3 {
 
+  public V3() {
+  }
+  
   public static V3 newV(T3 t) {
     return V3.new3(t.x, t.y, t.z);
   }
index 78b5a82..9060575 100644 (file)
@@ -30,8 +30,7 @@ package javajs.util;
  * 
  * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012
  * for unique constructor and method names
- * for the optimization of compiled JavaScript using Java2Script.
- *
+ * for the optimization of compiled JavaScript using Java2Script
  */
 public class V3d extends T3d {
 
index 03a903b..f20715f 100644 (file)
@@ -3,9 +3,6 @@
  * $Date$
  * $Revision$
  *
- * Some portions of this file have been modified by Robert Hanson hansonr.at.stolaf.edu 2012-2017
- * for use in SwingJS via transpilation into JavaScript using Java2Script.
- *
  * Copyright (C) 2006  The Jmol Development Team
  *
  * Contact: jmol-developers@lists.sf.net
index 6714236..a4082ec 100644 (file)
@@ -32,12 +32,6 @@ import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-
-import javajs.J2SIgnoreImport;
-import javajs.api.GenericZipInputStream;
-import javajs.api.GenericZipTools;
-import javajs.api.ZInputStream;
-
 import java.util.Map;
 import java.util.zip.CRC32;
 import java.util.zip.GZIPInputStream;
@@ -45,12 +39,18 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
+import javajs.api.GenericZipInputStream;
+import javajs.api.GenericZipTools;
+import javajs.api.Interface;
+import javajs.api.ZInputStream;
+
+import org.apache.tools.bzip2.CBZip2InputStreamFactory;
+
 
 /**
  * Note the JSmol/HTML5 must use its own version of java.util.zip.ZipOutputStream.
  * 
  */
-@J2SIgnoreImport({ java.util.zip.ZipOutputStream.class })
 public class ZipTools implements GenericZipTools {
 
   public ZipTools() {
@@ -62,6 +62,7 @@ public class ZipTools implements GenericZipTools {
     return newZIS(is);
   }
 
+  @SuppressWarnings("resource")
   private static ZInputStream newZIS(InputStream is) {
     return (is instanceof ZInputStream ? (ZInputStream) is
         : is instanceof BufferedInputStream ? new GenericZipInputStream(is)
@@ -286,6 +287,11 @@ public class ZipTools implements GenericZipTools {
   }
 
   @Override
+  public InputStream newBZip2InputStream(InputStream is) throws IOException {
+    return new BufferedInputStream(((CBZip2InputStreamFactory) Interface.getInterface("org.apache.tools.bzip2.CBZip2InputStreamFactory")).getStream(is));
+  }
+
+  @Override
   public BufferedInputStream getUnGzippedInputStream(byte[] bytes) {
     try {
       return Rdr.getUnzippedInputStream(this, Rdr.getBIS(bytes));
@@ -306,16 +312,16 @@ public class ZipTools implements GenericZipTools {
 
   @Override
   public Object getZipOutputStream(Object bos) {
-    /**
-     * @j2sNative
-     * 
-     *            return javajs.api.Interface.getInterface(
-     *            "java.util.zip.ZipOutputStream").setZOS(bos);
-     * 
-     */
-    {
+//    /**
+//     * @j2sNative
+//     * 
+//     *            return javajs.api.Interface.getInterface(
+//     *            "java.util.zip.ZipOutputStream").setZOS(bos);
+//     * 
+//     */
+//    {
       return new ZipOutputStream((OutputStream) bos);
-    }
+//    }
   }
 
   @Override
@@ -353,9 +359,9 @@ public class ZipTools implements GenericZipTools {
       bdata.clear();
       bdata.put("_ERROR_", e.getMessage());
     }
-       }
+  }
 
-       @Override
+  @Override
   public String cacheZipContents(BufferedInputStream bis,
                                         String fileName,
                                         Map<String, Object> cache, 
@@ -419,9 +425,9 @@ public class ZipTools implements GenericZipTools {
       return null;
     System.out.println("ZipTools cached " + n + " bytes from " + fileName);
     return listing.toString();
-       }
+  }
 
-       private static byte[] getPngImageBytes(BufferedInputStream bis) {
+  private static byte[] getPngImageBytes(BufferedInputStream bis) {
     try {
       if (Rdr.isPngZipStream(bis)) {
         int pt_count[] = new int[2];
diff --git a/src/org/apache/harmony/luni/util/ExternalMessages.properties b/src/org/apache/harmony/luni/util/ExternalMessages.properties
new file mode 100644 (file)
index 0000000..54227b8
--- /dev/null
@@ -0,0 +1,311 @@
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+# External Messages for EN locale
+K0006=Negative index specified
+K0007=attempt to write after finish
+K0008=Cannot read version
+K0009=Missing version string\: {0}
+K000a=Entry is not named
+K000b=Invalid attribute {0}
+K000c=cannot resolve subclasses
+K000d=Unknown attribute
+K000e=Cannot add attributes to empty string
+K0014=Unquoted {0} in suffix\: {1}
+K0015=Unexpected {0} in fraction\: {1}
+K0016=Unexpected {0} in {1}
+K0017=Missing pattern before {0} in {1}
+K0018=Missing exponent format {0}
+K0019=Unterminated quote {0}
+K001a=Missing grouping format {0}
+K001b=Invalid exponent format {0}
+K001c=Invalid pattern char {0} in {1}
+K001d=Invalid argument number
+K001e=Missing element format
+K001f=Unknown element format
+K0020=Unknown format
+K002b=Unknown pattern character - '{0}'
+K002c=Access denied {0}
+K002e=Offset out of bounds
+K002f=Arguments out of bounds
+K0032=Address null or destination port out of range
+K0033=Unknown socket type
+K0034=Packet address mismatch with connected address
+K0035=Zero or negative buffer size
+K0036=Invalid negative timeout
+K0037=Connection already established
+K0038=No host name provided
+K0039=Attempted to join a non-multicast group
+K003a=Attempted to leave a non-multicast group
+K003c=TimeToLive out of bounds
+K003d=Socket is closed
+K003e=SOCKS connection failed\: {0}
+K003f=Unable to connect to SOCKS server\: {0}
+K0040=Invalid SOCKS client.
+K0041=Socket implementation does not support SOCKS.
+K0042=Socket implementation factory already set
+K0044=The factory has already been set
+K0045=Attempted to set a negative SoLinger
+K0046=Local port declared out of range
+K0047=buffer is null
+K0048=Invalid action specified\: {0}
+K0049=MinPort is greater than MaxPort
+K004a=Invalid port number specified
+K004b=Attempt to set factory more than once.
+K004c=Package is sealed
+K004d=Does not support writing to the input stream
+K004e=Duplicate Factory
+K004f=rounding necessary
+K0050=wrong rounding mode
+K0051=scale value < than zero
+K0052=Array index out of range\: {0}
+K0053=Package {0} already defined.
+K0055=String index out of range\: {0}
+K0056=Already destroyed
+K0057=Has threads
+K0058=size must be > 0
+K0059=Stream is closed
+K005a=Mark has been invalidated.
+K005b=BufferedReader is closed
+K005c=Invalid Mark.
+K005d=Writer is closed.
+K005e=size must be >\= 0
+K005f=Does not support writing to the output stream
+K0060=CharArrayReader is closed.
+K0062=Second byte at {0} does not match UTF8 Specification
+K0063=Third byte at {0} does not match UTF8 Specification
+K0064=Second or third byte at {0} does not match UTF8 Specification
+K0065=Input at {0} does not match UTF8 Specification
+K0066=Entry already exists: {0}
+K0068=String is too long
+K0069=File cannot compare to non File
+K006a=time must be positive
+K006b=Prefix must be at least 3 characters
+K006c=FileDescriptor is null
+K006d=actions invalid
+K006e=path is null
+K006f=invalid permission\: {0}
+K0070=InputStreamReader is closed.
+K0071=Error fetching SUID\: {0}
+K0072={0} computing SHA-1 / SUID
+K0073=OutputStreamWriter is closed.
+K0074=Not connected
+K0075=InputStream is closed
+K0076=Pipe broken
+K0077=Crc mismatch
+K0078=Pipe is closed
+K0079=Already connected
+K007a=Pipe already connected
+K007b=Pipe Not Connected
+K007e=Pushback buffer full
+K007f=Mark/Reset not supported
+K0080=Reader is closed
+K0081=Mode must be one of "r" or "rw"
+K0083=StringReader is closed.
+K0084=can only instantiate one BootstrapClassLoader
+K0086=Referenced reflect object is no longer valid
+K0087=Referenced reflect object is no longer valid\: {0}
+K0088=Incorrect end of BER tag
+K0089=Unknown type\: {0}
+K008a=Read {0} bytes trying to read {1} bytes from {2}
+K008b=Position\: {0}
+K008c=Invalid Base64 char\:{0}
+K008d=This protocol does not support input
+K008e=Does not support output
+K008f=This method does not support writing\: {0}
+K0090=can't open OutputStream after reading from an inputStream
+K0091=Cannot access request header fields after connection is set
+K0092=Cannot set method after connection is made
+K0093=Too many redirects
+K0094=Unable to change directories
+K0095=Could not establish data connection
+K0096=Unable to retrieve file\: {0}
+K0097=Unable to connect to server\: {0}
+K0098=Unable to log into server\: {0}
+K0099=Unable to configure data port
+K009a=Unable to store file
+K009b=Unable to set transfer type
+K00a2=Parsing policy file\: {0}, expected quoted {1}, found unquoted\: {2}
+K00a3=Parsing policy file\: {0}, found unexpected\: {1}
+K00a4=Content-Length underflow
+K00a5=Invalid parameter - {0}
+K00a8=Parsing policy file\: {0}, invalid codesource URL\: {1}
+K00ab=No active entry
+K00ae=Size mismatch
+K00af=Invalid proxy port\: {0}
+K00b0=Proxy port out of range
+K00b1=Invalid port number
+K00b2=Content-Length exceeded
+K00b3=Unknown protocol\: {0}
+K00b6=No entries
+K00b7=File is closed
+K00c1=Illegal character
+K00cd=Failure to connect to SOCKS server.
+K00ce=Unable to connect to identd to verify user.
+K00cf=Failure - user ids do not match.
+K00d0=Success
+K00d1=Read null attempting to read class descriptor for an object
+K00d2=Wrong format\: 0x{0}
+K00d3=Read an exception
+K00d4={2} - {0} not compatible with {1}
+K00d5=Invalid typecode\: {0}
+K00d7=Wrong base type in\: {0}
+K00d8=Protocol not found\: {0}
+K00d9=Callback object cannot be null
+K00da=Incompatible class (SUID)\: {0} but expected {1}
+K00dc=IllegalAccessException
+K00e3=Could not create specified security manager\: {0}
+K00e4=Key usage is critical and cannot be used for digital signature purposes.
+K00e5=month\: {0}
+K00e6=day of month\: {0}
+K00e7=day of week\: {0}
+K00e8=time\: {0}
+K00e9=DST offset\: {0}
+K00ea=era\: {0}
+K00eb={0} failed verification of {1}
+K00ec={0} has invalid digest for {1} in {2}
+K00ed={0} is not an interface
+K00ee={0} is not visible from class loader
+K00ef={0} appears more than once
+K00f0=non-public interfaces must be in the same package
+K00f1=not a proxy instance
+K00f2=the methods named {0} must have the same return type
+K00f3=Timer was cancelled
+K00f5=Illegal delay to start the TimerTask
+K00f6=TimerTask is scheduled already
+K00f7=TimerTask is cancelled
+K00f8=day of week in month\: {0}
+K00f9=min or max digit count too large
+K00fa=min digits greater than max digits
+K00fb=min or max digits negative
+K00fc=Jar entry not specified
+K00fd=Invalid keystore
+K00fe=Incorrect password
+K0185=The alias already exists for a key entry.
+K018f=Can't convert to BMPString \: {0}
+K0190=No data to decode
+K0191=Invalid size, must be a multiple of 64 from 512 to 1024
+K0193=An identity with this name already exists in this scope
+K0194=An identity in the scope has the same public key
+K0195=The existing public key and the one contained in the certificate do not match.
+K0196=Certificate is missing
+K0199=Count out of range
+K01a0=End of stream condition
+K01a4=Already shutting down
+K01a5=Illegal shutdown hook\: {0}
+K01a6=Invalid filter
+K01a7=Name too long: {0}
+K01b3=Incorrect number of arguments
+K01b4=Cannot convert {0} to {1}
+K01b6=Cannot find \!/
+K01c1=File is a Directory
+K01c2=Cannot create\: {0}
+K01c3=Unable to open\: {0}
+K01c4=Invalid zip file\: {0}
+K01c6=No Main-Class specified in manifest\: {0}
+K01d1=Signers of '{0}' do not match signers of other classes in package
+K01d2={1} - protected system package '{0}'
+K01ec=key size must be a multiple of 8 bits
+K01ed=key size must be at least 512 bits
+K01fe=Incomplete % sequence at\: {0}
+K01ff=Invalid % sequence ({0}) at\: {1}
+K0220=UTFDataFormatException
+K0222=No Manifest found in jar file\: {0}
+K0300=Unsupported encoding
+K0301=Not signed data
+K0302=Relative path
+K0303=Scheme-specific part expected
+K0304=Authority expected
+K0305=Illegal character in scheme
+K0306={0} in schemeSpecificPart
+K0307={0} in authority
+K0308={0} in path
+K0309={0} in query
+K030a={0} in fragment
+K030c=Expected host
+K030d=Illegal character in userinfo
+K030e=Expected a closing square bracket for ipv6 address
+K030f=Malformed ipv6 address
+K0310=Illegal character in host name
+K0311=Malformed ipv4 address
+K0312=URI is not absolute
+K0313=Incomplete % sequence
+K0314=Invalid % sequence ({0})
+K0315=Socket is already bound
+K0316=SocketAddress {0} not supported
+K0317=Host is unresolved\: {0}
+K0318=SocketAddress is null
+K0319=Exception in thread "{0}"\ 
+K031a=URI is not absolute\: {0}
+K031b=URI is not hierarchical\: {0}
+K031c=Expected file scheme in URI\: {0}
+K031d=Expected non-empty path in URI\: {0}
+K031e=Found {0} component in URI\: {1}
+K031f=Socket is not bound
+K0320=Socket is not connected
+K0321=Socket input is shutdown
+K0322=Not a supported ISO 4217 Currency Code\: {0}
+K0323=Not a supported ISO 3166 Country locale\: {0}
+K0324=Needs dictionary
+K0325=Port out of range\: {0}
+K0326={0} at index {1}\: {2}
+K0327={0}\: {1}
+K0328=Certificate not yet valid
+K0329=Certificate expired
+K0330=interface name is null
+K0331=address is null
+K0332=Invalid IP Address is neither 4 or 16 bytes\: {0}
+K0333=Urgent data not supported
+K0334=Cannot set network interface with null
+K0335=No addresses associated with Interface
+K0337=null type not allowed
+K0338=Address not associated with an interface - not set
+K0339=Invalid IP Address is neither 4 or 16 bytes
+K0340={0} incompatible with {1}
+K0342=Scheme expected
+K0344=Not a valid {0}, subclass should override readResolve()
+K0346=Unmatched braces in the pattern
+K0347=seek position is negative
+K0348=Format specifier '{0}'
+K0349=Conversion is '{0}'
+K034a=The flags are {0}
+K034b=url and proxy can not be null
+K034c=proxy should not be null
+K034d=method has not been implemented yet
+K034e=Build rules empty
+K0351=format is null
+KA000=Line too long
+KA001=Argument must not be null
+KA002=Unshared read of back reference
+KA003=different mode already set
+KA004=Enums may not be cloned
+KA005={0} is not an enum type
+KA006={0} is not a constant in the enum type {1}
+KA007=field is null
+KA008={0} is an illegal radix
+KA009=CharsetName is illegal
+KA00a=File is null
+KA00b=InputStream is null
+KA00c=Readable is null
+KA00d=ReadableByteChannel is null
+KA00e=Radix {0} is less than Character.MIN_RADIX or greater than Character.MAX_RADIX
+KA00f=Socket output is shutdown
+KA010=Cannot read back reference to unshared object
+KA011=Malformed reply from SOCKS server
+KA012=No such file or directory
+KA013=Number of bytes to skip cannot be negative
+KA014=Invalit UUID string
+KA015=Incompatible class (base name)\: {0} but expected {1}
+
diff --git a/src/org/apache/harmony/luni/util/ExternalMessages.properties.js b/src/org/apache/harmony/luni/util/ExternalMessages.properties.js
new file mode 100644 (file)
index 0000000..cf6a86e
--- /dev/null
@@ -0,0 +1 @@
+java.util.ResourceBundle.registerBundle("org.apache.harmony.luni.util.ExternalMessages", "K0006=Negative index specified\r\nK0007=attempt to write after finish\r\nK0008=Cannot read version\r\nK0009=Missing version string\\: {0}\r\nK000a=Entry is not named\r\nK000b=Invalid attribute {0}\r\nK000c=cannot resolve subclasses\r\nK000d=Unknown attribute\r\nK000e=Cannot add attributes to empty string\r\nK0014=Unquoted {0} in suffix\\: {1}\r\nK0015=Unexpected {0} in fraction\\: {1}\r\nK0016=Unexpected {0} in {1}\r\nK0017=Missing pattern before {0} in {1}\r\nK0018=Missing exponent format {0}\r\nK0019=Unterminated quote {0}\r\nK001a=Missing grouping format {0}\r\nK001b=Invalid exponent format {0}\r\nK001c=Invalid pattern char {0} in {1}\r\nK001d=Invalid argument number\r\nK001e=Missing element format\r\nK001f=Unknown element format\r\nK0020=Unknown format\r\nK002b=Unknown pattern character - \'{0}\'\r\nK002c=Access denied {0}\r\nK002e=Offset out of bounds\r\nK002f=Arguments out of bounds\r\nK0032=Address null or destination port out of range\r\nK0033=Unknown socket type\r\nK0034=Packet address mismatch with connected address\r\nK0035=Zero or negative buffer size\r\nK0036=Invalid negative timeout\r\nK0037=Connection already established\r\nK0038=No host name provided\r\nK0039=Attempted to join a non-multicast group\r\nK003a=Attempted to leave a non-multicast group\r\nK003c=TimeToLive out of bounds\r\nK003d=Socket is closed\r\nK003e=SOCKS connection failed\\: {0}\r\nK003f=Unable to connect to SOCKS server\\: {0}\r\nK0040=Invalid SOCKS client.\r\nK0041=Socket implementation does not support SOCKS.\r\nK0042=Socket implementation factory already set\r\nK0044=The factory has already been set\r\nK0045=Attempted to set a negative SoLinger\r\nK0046=Local port declared out of range\r\nK0047=buffer is null\r\nK0048=Invalid action specified\\: {0}\r\nK0049=MinPort is greater than MaxPort\r\nK004a=Invalid port number specified\r\nK004b=Attempt to set factory more than once.\r\nK004c=Package is sealed\r\nK004d=Does not support writing to the input stream\r\nK004e=Duplicate Factory\r\nK004f=rounding necessary\r\nK0050=wrong rounding mode\r\nK0051=scale value < than zero\r\nK0052=Array index out of range\\: {0}\r\nK0053=Package {0} already defined.\r\nK0055=String index out of range\\: {0}\r\nK0056=Already destroyed\r\nK0057=Has threads\r\nK0058=size must be > 0\r\nK0059=Stream is closed\r\nK005a=Mark has been invalidated.\r\nK005b=BufferedReader is closed\r\nK005c=Invalid Mark.\r\nK005d=Writer is closed.\r\nK005e=size must be >\\= 0\r\nK005f=Does not support writing to the output stream\r\nK0060=CharArrayReader is closed.\r\nK0062=Second byte at {0} does not match UTF8 Specification\r\nK0063=Third byte at {0} does not match UTF8 Specification\r\nK0064=Second or third byte at {0} does not match UTF8 Specification\r\nK0065=Input at {0} does not match UTF8 Specification\r\nK0066=Entry already exists: {0}\r\nK0068=String is too long\r\nK0069=File cannot compare to non File\r\nK006a=time must be positive\r\nK006b=Prefix must be at least 3 characters\r\nK006c=FileDescriptor is null\r\nK006d=actions invalid\r\nK006e=path is null\r\nK006f=invalid permission\\: {0}\r\nK0070=InputStreamReader is closed.\r\nK0071=Error fetching SUID\\: {0}\r\nK0072={0} computing SHA-1 / SUID\r\nK0073=OutputStreamWriter is closed.\r\nK0074=Not connected\r\nK0075=InputStream is closed\r\nK0076=Pipe broken\r\nK0077=Crc mismatch\r\nK0078=Pipe is closed\r\nK0079=Already connected\r\nK007a=Pipe already connected\r\nK007b=Pipe Not Connected\r\nK007e=Pushback buffer full\r\nK007f=Mark/Reset not supported\r\nK0080=Reader is closed\r\nK0081=Mode must be one of \"r\" or \"rw\"\r\nK0083=StringReader is closed.\r\nK0084=can only instantiate one BootstrapClassLoader\r\nK0086=Referenced reflect object is no longer valid\r\nK0087=Referenced reflect object is no longer valid\\: {0}\r\nK0088=Incorrect end of BER tag\r\nK0089=Unknown type\\: {0}\r\nK008a=Read {0} bytes trying to read {1} bytes from {2}\r\nK008b=Position\\: {0}\r\nK008c=Invalid Base64 char\\:{0}\r\nK008d=This protocol does not support input\r\nK008e=Does not support output\r\nK008f=This method does not support writing\\: {0}\r\nK0090=can\'t open OutputStream after reading from an inputStream\r\nK0091=Cannot access request header fields after connection is set\r\nK0092=Cannot set method after connection is made\r\nK0093=Too many redirects\r\nK0094=Unable to change directories\r\nK0095=Could not establish data connection\r\nK0096=Unable to retrieve file\\: {0}\r\nK0097=Unable to connect to server\\: {0}\r\nK0098=Unable to log into server\\: {0}\r\nK0099=Unable to configure data port\r\nK009a=Unable to store file\r\nK009b=Unable to set transfer type\r\nK00a2=Parsing policy file\\: {0}, expected quoted {1}, found unquoted\\: {2}\r\nK00a3=Parsing policy file\\: {0}, found unexpected\\: {1}\r\nK00a4=Content-Length underflow\r\nK00a5=Invalid parameter - {0}\r\nK00a8=Parsing policy file\\: {0}, invalid codesource URL\\: {1}\r\nK00ab=No active entry\r\nK00ae=Size mismatch\r\nK00af=Invalid proxy port\\: {0}\r\nK00b0=Proxy port out of range\r\nK00b1=Invalid port number\r\nK00b2=Content-Length exceeded\r\nK00b3=Unknown protocol\\: {0}\r\nK00b6=No entries\r\nK00b7=File is closed\r\nK00c1=Illegal character\r\nK00cd=Failure to connect to SOCKS server.\r\nK00ce=Unable to connect to identd to verify user.\r\nK00cf=Failure - user ids do not match.\r\nK00d0=Success\r\nK00d1=Read null attempting to read class descriptor for an object\r\nK00d2=Wrong format\\: 0x{0}\r\nK00d3=Read an exception\r\nK00d4={2} - {0} not compatible with {1}\r\nK00d5=Invalid typecode\\: {0}\r\nK00d7=Wrong base type in\\: {0}\r\nK00d8=Protocol not found\\: {0}\r\nK00d9=Callback object cannot be null\r\nK00da=Incompatible class (SUID)\\: {0} but expected {1}\r\nK00dc=IllegalAccessException\r\nK00e3=Could not create specified security manager\\: {0}\r\nK00e4=Key usage is critical and cannot be used for digital signature purposes.\r\nK00e5=month\\: {0}\r\nK00e6=day of month\\: {0}\r\nK00e7=day of week\\: {0}\r\nK00e8=time\\: {0}\r\nK00e9=DST offset\\: {0}\r\nK00ea=era\\: {0}\r\nK00eb={0} failed verification of {1}\r\nK00ec={0} has invalid digest for {1} in {2}\r\nK00ed={0} is not an interface\r\nK00ee={0} is not visible from class loader\r\nK00ef={0} appears more than once\r\nK00f0=non-public interfaces must be in the same package\r\nK00f1=not a proxy instance\r\nK00f2=the methods named {0} must have the same return type\r\nK00f3=Timer was cancelled\r\nK00f5=Illegal delay to start the TimerTask\r\nK00f6=TimerTask is scheduled already\r\nK00f7=TimerTask is cancelled\r\nK00f8=day of week in month\\: {0}\r\nK00f9=min or max digit count too large\r\nK00fa=min digits greater than max digits\r\nK00fb=min or max digits negative\r\nK00fc=Jar entry not specified\r\nK00fd=Invalid keystore\r\nK00fe=Incorrect password\r\nK0185=The alias already exists for a key entry.\r\nK018f=Can\'t convert to BMPString \\: {0}\r\nK0190=No data to decode\r\nK0191=Invalid size, must be a multiple of 64 from 512 to 1024\r\nK0193=An identity with this name already exists in this scope\r\nK0194=An identity in the scope has the same public key\r\nK0195=The existing public key and the one contained in the certificate do not match.\r\nK0196=Certificate is missing\r\nK0199=Count out of range\r\nK01a0=End of stream condition\r\nK01a4=Already shutting down\r\nK01a5=Illegal shutdown hook\\: {0}\r\nK01a6=Invalid filter\r\nK01a7=Name too long: {0}\r\nK01b3=Incorrect number of arguments\r\nK01b4=Cannot convert {0} to {1}\r\nK01b6=Cannot find \\!/\r\nK01c1=File is a Directory\r\nK01c2=Cannot create\\: {0}\r\nK01c3=Unable to open\\: {0}\r\nK01c4=Invalid zip file\\: {0}\r\nK01c6=No Main-Class specified in manifest\\: {0}\r\nK01d1=Signers of \'{0}\' do not match signers of other classes in package\r\nK01d2={1} - protected system package \'{0}\'\r\nK01ec=key size must be a multiple of 8 bits\r\nK01ed=key size must be at least 512 bits\r\nK01fe=Incomplete % sequence at\\: {0}\r\nK01ff=Invalid % sequence ({0}) at\\: {1}\r\nK0220=UTFDataFormatException\r\nK0222=No Manifest found in jar file\\: {0}\r\nK0300=Unsupported encoding\r\nK0301=Not signed data\r\nK0302=Relative path\r\nK0303=Scheme-specific part expected\r\nK0304=Authority expected\r\nK0305=Illegal character in scheme\r\nK0306={0} in schemeSpecificPart\r\nK0307={0} in authority\r\nK0308={0} in path\r\nK0309={0} in query\r\nK030a={0} in fragment\r\nK030c=Expected host\r\nK030d=Illegal character in userinfo\r\nK030e=Expected a closing square bracket for ipv6 address\r\nK030f=Malformed ipv6 address\r\nK0310=Illegal character in host name\r\nK0311=Malformed ipv4 address\r\nK0312=URI is not absolute\r\nK0313=Incomplete % sequence\r\nK0314=Invalid % sequence ({0})\r\nK0315=Socket is already bound\r\nK0316=SocketAddress {0} not supported\r\nK0317=Host is unresolved\\: {0}\r\nK0318=SocketAddress is null\r\nK0319=Exception in thread \"{0}\"\\ \r\nK031a=URI is not absolute\\: {0}\r\nK031b=URI is not hierarchical\\: {0}\r\nK031c=Expected file scheme in URI\\: {0}\r\nK031d=Expected non-empty path in URI\\: {0}\r\nK031e=Found {0} component in URI\\: {1}\r\nK031f=Socket is not bound\r\nK0320=Socket is not connected\r\nK0321=Socket input is shutdown\r\nK0322=Not a supported ISO 4217 Currency Code\\: {0}\r\nK0323=Not a supported ISO 3166 Country locale\\: {0}\r\nK0324=Needs dictionary\r\nK0325=Port out of range\\: {0}\r\nK0326={0} at index {1}\\: {2}\r\nK0327={0}\\: {1}\r\nK0328=Certificate not yet valid\r\nK0329=Certificate expired\r\nK0330=interface name is null\r\nK0331=address is null\r\nK0332=Invalid IP Address is neither 4 or 16 bytes\\: {0}\r\nK0333=Urgent data not supported\r\nK0334=Cannot set network interface with null\r\nK0335=No addresses associated with Interface\r\nK0337=null type not allowed\r\nK0338=Address not associated with an interface - not set\r\nK0339=Invalid IP Address is neither 4 or 16 bytes\r\nK0340={0} incompatible with {1}\r\nK0342=Scheme expected\r\nK0344=Not a valid {0}, subclass should override readResolve()\r\nK0346=Unmatched braces in the pattern\r\nK0347=seek position is negative\r\nK0348=Format specifier \'{0}\'\r\nK0349=Conversion is \'{0}\'\r\nK034a=The flags are {0}\r\nK034b=url and proxy can not be null\r\nK034c=proxy should not be null\r\nK034d=method has not been implemented yet\r\nK034e=Build rules empty\r\nK0351=format is null\r\nKA000=Line too long\r\nKA001=Argument must not be null\r\nKA002=Unshared read of back reference\r\nKA003=different mode already set\r\nKA004=Enums may not be cloned\r\nKA005={0} is not an enum type\r\nKA006={0} is not a constant in the enum type {1}\r\nKA007=field is null\r\nKA008={0} is an illegal radix\r\nKA009=CharsetName is illegal\r\nKA00a=File is null\r\nKA00b=InputStream is null\r\nKA00c=Readable is null\r\nKA00d=ReadableByteChannel is null\r\nKA00e=Radix {0} is less than Character.MIN_RADIX or greater than Character.MAX_RADIX\r\nKA00f=Socket output is shutdown\r\nKA010=Cannot read back reference to unshared object\r\nKA011=Malformed reply from SOCKS server\r\nKA012=No such file or directory\r\nKA013=Number of bytes to skip cannot be negative\r\nKA014=Invalit UUID string\r\nKA015=Incompatible class (base name)\\: {0} but expected {1}\r\n\r\n");
\ No newline at end of file
diff --git a/src/org/apache/harmony/luni/util/Msg.java b/src/org/apache/harmony/luni/util/Msg.java
new file mode 100644 (file)
index 0000000..d90ee77
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.util;
+
+/**
+ * This class retrieves strings from a resource bundle and returns them,
+ * formatting them with MessageFormat when required.
+ * <p>
+ * It is used by the system classes to provide national language support, by
+ * looking up messages in the <code>
+ *    org.apache.harmony.luni.util.ExternalMessages
+ * </code>
+ * resource bundle. Note that if this file is not available, or an invalid key
+ * is looked up, or resource bundle support is not available, the key itself
+ * will be returned as the associated message. This means that the <em>KEY</em>
+ * should a reasonable human-readable (english) string.
+ * 
+ */
+public class Msg {
+
+       final static String msgs = "K0006=Negative index specified\r\nK0007=attempt to write after finish\r\nK0008=Cannot read version\r\nK0009=Missing version string\\: {0}\r\nK000a=Entry is not named\r\nK000b=Invalid attribute {0}\r\nK000c=cannot resolve subclasses\r\nK000d=Unknown attribute\r\nK000e=Cannot add attributes to empty string\r\nK0014=Unquoted {0} in suffix\\: {1}\r\nK0015=Unexpected {0} in fraction\\: {1}\r\nK0016=Unexpected {0} in {1}\r\nK0017=Missing pattern before {0} in {1}\r\nK0018=Missing exponent format {0}\r\nK0019=Unterminated quote {0}\r\nK001a=Missing grouping format {0}\r\nK001b=Invalid exponent format {0}\r\nK001c=Invalid pattern char {0} in {1}\r\nK001d=Invalid argument number\r\nK001e=Missing element format\r\nK001f=Unknown element format\r\nK0020=Unknown format\r\nK002b=Unknown pattern character - \'{0}\'\r\nK002c=Access denied {0}\r\nK002e=Offset out of bounds\r\nK002f=Arguments out of bounds\r\nK0032=Address null or destination port out of range\r\nK0033=Unknown socket type\r\nK0034=Packet address mismatch with connected address\r\nK0035=Zero or negative buffer size\r\nK0036=Invalid negative timeout\r\nK0037=Connection already established\r\nK0038=No host name provided\r\nK0039=Attempted to join a non-multicast group\r\nK003a=Attempted to leave a non-multicast group\r\nK003c=TimeToLive out of bounds\r\nK003d=Socket is closed\r\nK003e=SOCKS connection failed\\: {0}\r\nK003f=Unable to connect to SOCKS server\\: {0}\r\nK0040=Invalid SOCKS client.\r\nK0041=Socket implementation does not support SOCKS.\r\nK0042=Socket implementation factory already set\r\nK0044=The factory has already been set\r\nK0045=Attempted to set a negative SoLinger\r\nK0046=Local port declared out of range\r\nK0047=buffer is null\r\nK0048=Invalid action specified\\: {0}\r\nK0049=MinPort is greater than MaxPort\r\nK004a=Invalid port number specified\r\nK004b=Attempt to set factory more than once.\r\nK004c=Package is sealed\r\nK004d=Does not support writing to the input stream\r\nK004e=Duplicate Factory\r\nK004f=rounding necessary\r\nK0050=wrong rounding mode\r\nK0051=scale value < than zero\r\nK0052=Array index out of range\\: {0}\r\nK0053=Package {0} already defined.\r\nK0055=String index out of range\\: {0}\r\nK0056=Already destroyed\r\nK0057=Has threads\r\nK0058=size must be > 0\r\nK0059=Stream is closed\r\nK005a=Mark has been invalidated.\r\nK005b=BufferedReader is closed\r\nK005c=Invalid Mark.\r\nK005d=Writer is closed.\r\nK005e=size must be >\\= 0\r\nK005f=Does not support writing to the output stream\r\nK0060=CharArrayReader is closed.\r\nK0062=Second byte at {0} does not match UTF8 Specification\r\nK0063=Third byte at {0} does not match UTF8 Specification\r\nK0064=Second or third byte at {0} does not match UTF8 Specification\r\nK0065=Input at {0} does not match UTF8 Specification\r\nK0066=Entry already exists: {0}\r\nK0068=String is too long\r\nK0069=File cannot compare to non File\r\nK006a=time must be positive\r\nK006b=Prefix must be at least 3 characters\r\nK006c=FileDescriptor is null\r\nK006d=actions invalid\r\nK006e=path is null\r\nK006f=invalid permission\\: {0}\r\nK0070=InputStreamReader is closed.\r\nK0071=Error fetching SUID\\: {0}\r\nK0072={0} computing SHA-1 / SUID\r\nK0073=OutputStreamWriter is closed.\r\nK0074=Not connected\r\nK0075=InputStream is closed\r\nK0076=Pipe broken\r\nK0077=Crc mismatch\r\nK0078=Pipe is closed\r\nK0079=Already connected\r\nK007a=Pipe already connected\r\nK007b=Pipe Not Connected\r\nK007e=Pushback buffer full\r\nK007f=Mark/Reset not supported\r\nK0080=Reader is closed\r\nK0081=Mode must be one of \"r\" or \"rw\"\r\nK0083=StringReader is closed.\r\nK0084=can only instantiate one BootstrapClassLoader\r\nK0086=Referenced reflect object is no longer valid\r\nK0087=Referenced reflect object is no longer valid\\: {0}\r\nK0088=Incorrect end of BER tag\r\nK0089=Unknown type\\: {0}\r\nK008a=Read {0} bytes trying to read {1} bytes from {2}\r\nK008b=Position\\: {0}\r\nK008c=Invalid Base64 char\\:{0}\r\nK008d=This protocol does not support input\r\nK008e=Does not support output\r\nK008f=This method does not support writing\\: {0}\r\nK0090=can\'t open OutputStream after reading from an inputStream\r\nK0091=Cannot access request header fields after connection is set\r\nK0092=Cannot set method after connection is made\r\nK0093=Too many redirects\r\nK0094=Unable to change directories\r\nK0095=Could not establish data connection\r\nK0096=Unable to retrieve file\\: {0}\r\nK0097=Unable to connect to server\\: {0}\r\nK0098=Unable to log into server\\: {0}\r\nK0099=Unable to configure data port\r\nK009a=Unable to store file\r\nK009b=Unable to set transfer type\r\nK00a2=Parsing policy file\\: {0}, expected quoted {1}, found unquoted\\: {2}\r\nK00a3=Parsing policy file\\: {0}, found unexpected\\: {1}\r\nK00a4=Content-Length underflow\r\nK00a5=Invalid parameter - {0}\r\nK00a8=Parsing policy file\\: {0}, invalid codesource URL\\: {1}\r\nK00ab=No active entry\r\nK00ae=Size mismatch\r\nK00af=Invalid proxy port\\: {0}\r\nK00b0=Proxy port out of range\r\nK00b1=Invalid port number\r\nK00b2=Content-Length exceeded\r\nK00b3=Unknown protocol\\: {0}\r\nK00b6=No entries\r\nK00b7=File is closed\r\nK00c1=Illegal character\r\nK00cd=Failure to connect to SOCKS server.\r\nK00ce=Unable to connect to identd to verify user.\r\nK00cf=Failure - user ids do not match.\r\nK00d0=Success\r\nK00d1=Read null attempting to read class descriptor for an object\r\nK00d2=Wrong format\\: 0x{0}\r\nK00d3=Read an exception\r\nK00d4={2} - {0} not compatible with {1}\r\nK00d5=Invalid typecode\\: {0}\r\nK00d7=Wrong base type in\\: {0}\r\nK00d8=Protocol not found\\: {0}\r\nK00d9=Callback object cannot be null\r\nK00da=Incompatible class (SUID)\\: {0} but expected {1}\r\nK00dc=IllegalAccessException\r\nK00e3=Could not create specified security manager\\: {0}\r\nK00e4=Key usage is critical and cannot be used for digital signature purposes.\r\nK00e5=month\\: {0}\r\nK00e6=day of month\\: {0}\r\nK00e7=day of week\\: {0}\r\nK00e8=time\\: {0}\r\nK00e9=DST offset\\: {0}\r\nK00ea=era\\: {0}\r\nK00eb={0} failed verification of {1}\r\nK00ec={0} has invalid digest for {1} in {2}\r\nK00ed={0} is not an interface\r\nK00ee={0} is not visible from class loader\r\nK00ef={0} appears more than once\r\nK00f0=non-public interfaces must be in the same package\r\nK00f1=not a proxy instance\r\nK00f2=the methods named {0} must have the same return type\r\nK00f3=Timer was cancelled\r\nK00f5=Illegal delay to start the TimerTask\r\nK00f6=TimerTask is scheduled already\r\nK00f7=TimerTask is cancelled\r\nK00f8=day of week in month\\: {0}\r\nK00f9=min or max digit count too large\r\nK00fa=min digits greater than max digits\r\nK00fb=min or max digits negative\r\nK00fc=Jar entry not specified\r\nK00fd=Invalid keystore\r\nK00fe=Incorrect password\r\nK0185=The alias already exists for a key entry.\r\nK018f=Can\'t convert to BMPString \\: {0}\r\nK0190=No data to decode\r\nK0191=Invalid size, must be a multiple of 64 from 512 to 1024\r\nK0193=An identity with this name already exists in this scope\r\nK0194=An identity in the scope has the same public key\r\nK0195=The existing public key and the one contained in the certificate do not match.\r\nK0196=Certificate is missing\r\nK0199=Count out of range\r\nK01a0=End of stream condition\r\nK01a4=Already shutting down\r\nK01a5=Illegal shutdown hook\\: {0}\r\nK01a6=Invalid filter\r\nK01a7=Name too long: {0}\r\nK01b3=Incorrect number of arguments\r\nK01b4=Cannot convert {0} to {1}\r\nK01b6=Cannot find \\!/\r\nK01c1=File is a Directory\r\nK01c2=Cannot create\\: {0}\r\nK01c3=Unable to open\\: {0}\r\nK01c4=Invalid zip file\\: {0}\r\nK01c6=No Main-Class specified in manifest\\: {0}\r\nK01d1=Signers of \'{0}\' do not match signers of other classes in package\r\nK01d2={1} - protected system package \'{0}\'\r\nK01ec=key size must be a multiple of 8 bits\r\nK01ed=key size must be at least 512 bits\r\nK01fe=Incomplete % sequence at\\: {0}\r\nK01ff=Invalid % sequence ({0}) at\\: {1}\r\nK0220=UTFDataFormatException\r\nK0222=No Manifest found in jar file\\: {0}\r\nK0300=Unsupported encoding\r\nK0301=Not signed data\r\nK0302=Relative path\r\nK0303=Scheme-specific part expected\r\nK0304=Authority expected\r\nK0305=Illegal character in scheme\r\nK0306={0} in schemeSpecificPart\r\nK0307={0} in authority\r\nK0308={0} in path\r\nK0309={0} in query\r\nK030a={0} in fragment\r\nK030c=Expected host\r\nK030d=Illegal character in userinfo\r\nK030e=Expected a closing square bracket for ipv6 address\r\nK030f=Malformed ipv6 address\r\nK0310=Illegal character in host name\r\nK0311=Malformed ipv4 address\r\nK0312=URI is not absolute\r\nK0313=Incomplete % sequence\r\nK0314=Invalid % sequence ({0})\r\nK0315=Socket is already bound\r\nK0316=SocketAddress {0} not supported\r\nK0317=Host is unresolved\\: {0}\r\nK0318=SocketAddress is null\r\nK0319=Exception in thread \"{0}\"\\ \r\nK031a=URI is not absolute\\: {0}\r\nK031b=URI is not hierarchical\\: {0}\r\nK031c=Expected file scheme in URI\\: {0}\r\nK031d=Expected non-empty path in URI\\: {0}\r\nK031e=Found {0} component in URI\\: {1}\r\nK031f=Socket is not bound\r\nK0320=Socket is not connected\r\nK0321=Socket input is shutdown\r\nK0322=Not a supported ISO 4217 Currency Code\\: {0}\r\nK0323=Not a supported ISO 3166 Country locale\\: {0}\r\nK0324=Needs dictionary\r\nK0325=Port out of range\\: {0}\r\nK0326={0} at index {1}\\: {2}\r\nK0327={0}\\: {1}\r\nK0328=Certificate not yet valid\r\nK0329=Certificate expired\r\nK0330=interface name is null\r\nK0331=address is null\r\nK0332=Invalid IP Address is neither 4 or 16 bytes\\: {0}\r\nK0333=Urgent data not supported\r\nK0334=Cannot set network interface with null\r\nK0335=No addresses associated with Interface\r\nK0337=null type not allowed\r\nK0338=Address not associated with an interface - not set\r\nK0339=Invalid IP Address is neither 4 or 16 bytes\r\nK0340={0} incompatible with {1}\r\nK0342=Scheme expected\r\nK0344=Not a valid {0}, subclass should override readResolve()\r\nK0346=Unmatched braces in the pattern\r\nK0347=seek position is negative\r\nK0348=Format specifier \'{0}\'\r\nK0349=Conversion is \'{0}\'\r\nK034a=The flags are {0}\r\nK034b=url and proxy can not be null\r\nK034c=proxy should not be null\r\nK034d=method has not been implemented yet\r\nK034e=Build rules empty\r\nK0351=format is null\r\nKA000=Line too long\r\nKA001=Argument must not be null\r\nKA002=Unshared read of back reference\r\nKA003=different mode already set\r\nKA004=Enums may not be cloned\r\nKA005={0} is not an enum type\r\nKA006={0} is not a constant in the enum type {1}\r\nKA007=field is null\r\nKA008={0} is an illegal radix\r\nKA009=CharsetName is illegal\r\nKA00a=File is null\r\nKA00b=InputStream is null\r\nKA00c=Readable is null\r\nKA00d=ReadableByteChannel is null\r\nKA00e=Radix {0} is less than Character.MIN_RADIX or greater than Character.MAX_RADIX\r\nKA00f=Socket output is shutdown\r\nKA010=Cannot read back reference to unshared object\r\nKA011=Malformed reply from SOCKS server\r\nKA012=No such file or directory\r\nKA013=Number of bytes to skip cannot be negative\r\nKA014=Invalit UUID string\r\nKA015=Incompatible class (base name)\\: {0} but expected {1}\r\n\r\n";
+
+       // ResourceBundle holding the system messages.
+//     static private ResourceBundle bundle = null;
+
+//     /**
+//      * @j2sIgnore
+//      */
+//     static {
+//             // Attempt to load the messages.
+//             try {
+//                     bundle = MsgHelp.setLocale(Locale.getDefault(),
+//                                     "org.apache.harmony.luni.util.ExternalMessages");
+//             } catch (Throwable e) {
+//                     e.printStackTrace();
+//             }
+//     }
+
+       /**
+        * Retrieves a message which has no arguments.
+        * 
+        * @param msg
+        *            String the key to look up.
+        * @return String the message for that key in the system message bundle.
+        */
+       static public String getString(String msg) {
+               return getMsg(msg);
+//             if (bundle == null)
+//                     return msg;
+//             try {
+//                     return bundle.getString(msg);
+//             } catch (MissingResourceException e) {
+//                     return msg;
+//             }
+       }
+
+       /**
+        * Retrieves a message which takes 1 argument.
+        * 
+        * @param msg
+        *            String the key to look up.
+        * @param arg
+        *            Object the object to insert in the formatted output.
+        * @return String the message for that key in the system message bundle.
+        */
+       static public String getString(String msg, Object arg) {
+               return getString(msg, new Object[] { arg });
+       }
+
+       /**
+        * Retrieves a message which takes 1 integer argument.
+        * 
+        * @param msg
+        *            String the key to look up.
+        * @param arg
+        *            int the integer to insert in the formatted output.
+        * @return String the message for that key in the system message bundle.
+        */
+       static public String getString(String msg, int arg) {
+               return getString(msg, new Object[] { Integer.toString(arg) });
+       }
+
+       /**
+        * Retrieves a message which takes 1 character argument.
+        * 
+        * @param msg
+        *            String the key to look up.
+        * @param arg
+        *            char the character to insert in the formatted output.
+        * @return String the message for that key in the system message bundle.
+        */
+       static public String getString(String msg, char arg) {
+               return getString(msg, new Object[] { String.valueOf(arg) });
+       }
+
+       /**
+        * Retrieves a message which takes 2 arguments.
+        * 
+        * @param msg
+        *            String the key to look up.
+        * @param arg1
+        *            Object an object to insert in the formatted output.
+        * @param arg2
+        *            Object another object to insert in the formatted output.
+        * @return String the message for that key in the system message bundle.
+        */
+       static public String getString(String msg, Object arg1, Object arg2) {
+               return getString(msg, new Object[] { arg1, arg2 });
+       }
+
+       /**
+        * Retrieves a message which takes several arguments.
+        * 
+        * @param msg
+        *            String the key to look up.
+        * @param args
+        *            Object[] the objects to insert in the formatted output.
+        * @return String the message for that key in the system message bundle.
+        */
+       static public String getString(String msg, Object[] args) {
+               String format = getMsg(msg);
+//             
+//
+//             if (bundle != null) {
+//                     try {
+//                             format = bundle.getString(msg);
+//                     } catch (MissingResourceException e) {
+//                     }
+//             }
+//
+               return format(format, args);
+       }
+
+       /**
+        * SwingJS minimal support for harmony error messages
+        * 
+        * @param msg
+        * @return
+        */
+       private static String getMsg(String msg) {
+               int pt = msgs.indexOf(msg);
+               return (pt < 0 ? msg : msg.substring(pt + 6, msg.indexOf("\r", pt)));
+       }
+       
+       // from MsgHelp.java
+       
+       /**
+        * Generates a formatted text string given a source string containing
+        * "argument markers" of the form "{argNum}" where each argNum must be in
+        * the range 0..9. The result is generated by inserting the toString of each
+        * argument into the position indicated in the string.
+        * <p>
+        * To insert the "{" character into the output, use a single backslash
+        * character to escape it (i.e. "\{"). The "}" character does not need to be
+        * escaped.
+        * 
+        * @param format
+        *            String the format to use when printing.
+        * @param args
+        *            Object[] the arguments to use.
+        * @return String the formatted message.
+        */
+       public static String format(String format, Object[] args) {
+               StringBuilder answer = new StringBuilder(format.length()
+                               + (args.length * 20));
+               String[] argStrings = new String[args.length];
+               for (int i = 0; i < args.length; ++i) {
+                       if (args[i] == null)
+                               argStrings[i] = "<null>";
+                       else
+                               argStrings[i] = args[i].toString();
+               }
+               int lastI = 0;
+               for (int i = format.indexOf('{', 0); i >= 0; i = format.indexOf('{',
+                               lastI)) {
+                       if (i != 0 && format.charAt(i - 1) == '\\') {
+                               // It's escaped, just print and loop.
+                               if (i != 1)
+                                       answer.append(format.substring(lastI, i - 1));
+                               answer.append('{');
+                               lastI = i + 1;
+                       } else {
+                               // It's a format character.
+                               if (i > format.length() - 3) {
+                                       // Bad format, just print and loop.
+                                       answer.append(format.substring(lastI, format.length()));
+                                       lastI = format.length();
+                               } else {
+//                                     int argnum = (byte) Character.digit(format.charAt(i + 1),
+//                                                     10);
+                                       int argnum = (byte) (format.charAt(i + 1) - '0');
+                                       if (argnum < 0 || format.charAt(i + 2) != '}') {
+                                               // Bad format, just print and loop.
+                                               answer.append(format.substring(lastI, i + 1));
+                                               lastI = i + 1;
+                                       } else {
+                                               // Got a good one!
+                                               answer.append(format.substring(lastI, i));
+                                               if (argnum >= argStrings.length)
+                                                       answer.append("<missing argument>");
+                                               else
+                                                       answer.append(argStrings[argnum]);
+                                               lastI = i + 3;
+                                       }
+                               }
+                       }
+               }
+               if (lastI < format.length())
+                       answer.append(format.substring(lastI, format.length()));
+               return answer.toString();
+       }
+
+}
diff --git a/src/org/apache/harmony/luni/util/MsgHelp.java b/src/org/apache/harmony/luni/util/MsgHelp.java
new file mode 100644 (file)
index 0000000..592d8b3
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.util;
+
+/**
+ * This class contains helper methods for loading resource bundles and
+ * formatting external message strings.
+ * 
+ */
+
+public final class MsgHelp {
+
+       /**
+        * Generates a formatted text string given a source string containing
+        * "argument markers" of the form "{argNum}" where each argNum must be in
+        * the range 0..9. The result is generated by inserting the toString of each
+        * argument into the position indicated in the string.
+        * <p>
+        * To insert the "{" character into the output, use a single backslash
+        * character to escape it (i.e. "\{"). The "}" character does not need to be
+        * escaped.
+        * 
+        * @param format
+        *            String the format to use when printing.
+        * @param args
+        *            Object[] the arguments to use.
+        * @return String the formatted message.
+        */
+       public static String format(String format, Object[] args) {
+               StringBuilder answer = new StringBuilder(format.length()
+                               + (args.length * 20));
+               String[] argStrings = new String[args.length];
+               for (int i = 0; i < args.length; ++i) {
+                       if (args[i] == null)
+                               argStrings[i] = "<null>";
+                       else
+                               argStrings[i] = args[i].toString();
+               }
+               int lastI = 0;
+               for (int i = format.indexOf('{', 0); i >= 0; i = format.indexOf('{',
+                               lastI)) {
+                       if (i != 0 && format.charAt(i - 1) == '\\') {
+                               // It's escaped, just print and loop.
+                               if (i != 1)
+                                       answer.append(format.substring(lastI, i - 1));
+                               answer.append('{');
+                               lastI = i + 1;
+                       } else {
+                               // It's a format character.
+                               if (i > format.length() - 3) {
+                                       // Bad format, just print and loop.
+                                       answer.append(format.substring(lastI, format.length()));
+                                       lastI = format.length();
+                               } else {
+//                                     int argnum = (byte) Character.digit(format.charAt(i + 1),
+//                                                     10);
+                                       int argnum = (byte) (format.charAt(i + 1) - '0');
+                                       if (argnum < 0 || format.charAt(i + 2) != '}') {
+                                               // Bad format, just print and loop.
+                                               answer.append(format.substring(lastI, i + 1));
+                                               lastI = i + 1;
+                                       } else {
+                                               // Got a good one!
+                                               answer.append(format.substring(lastI, i));
+                                               if (argnum >= argStrings.length)
+                                                       answer.append("<missing argument>");
+                                               else
+                                                       answer.append(argStrings[argnum]);
+                                               lastI = i + 3;
+                                       }
+                               }
+                       }
+               }
+               if (lastI < format.length())
+                       answer.append(format.substring(lastI, format.length()));
+               return answer.toString();
+       }
+
+//     /**
+//      * Changes the locale of the messages.
+//      * 
+//      * @param locale
+//      *            Locale the locale to change to.
+//      */
+//     static public ResourceBundle setLocale(final Locale locale,
+//                     final String resource) {
+//             /*
+//             try {
+//                     final ClassLoader loader = VM.bootCallerClassLoader();
+//                     return (ResourceBundle) AccessController
+//                                     .doPrivileged(new PrivilegedAction<Object>() {
+//                                             public Object run() {
+//                                                     return ResourceBundle.getBundle(resource, locale,
+//                                                                     loader != null ? loader : ClassLoader.getSystemClassLoader());
+//                                             }
+//                                     });
+//             } catch (MissingResourceException e) {
+//             }
+//             */
+//             /**
+//              * @j2sNative
+//              * 
+//              * Class.forName("java.util.ResourceBundle");
+//              */
+//             {}
+//             return ResourceBundle.getBundle(resource);
+//             //return null;
+//     }
+}
diff --git a/src/org/apache/tools/bzip2/BZip2Constants.java b/src/org/apache/tools/bzip2/BZip2Constants.java
new file mode 100644 (file)
index 0000000..3a511a7
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.apache.tools.bzip2;
+
+/**
+ * Base class for both the compress and decompress classes.
+ * Holds common arrays, and static data.
+ * <p>
+ * This interface is public for historical purposes.
+ * You should have no need to use it.
+ * </p>
+ */
+public interface BZip2Constants {
+
+    int baseBlockSize = 100000;
+    int MAX_ALPHA_SIZE = 258;
+    int MAX_CODE_LEN = 23;
+    int RUNA = 0;
+    int RUNB = 1;
+    int N_GROUPS = 6;
+    int G_SIZE = 50;
+    int N_ITERS = 4;
+    int MAX_SELECTORS = (2 + (900000 / G_SIZE));
+    int NUM_OVERSHOOT_BYTES = 20;
+
+    /**
+     * This array really shouldn't be here.
+     * Again, for historical purposes it is.
+     *
+     * <p>FIXME: This array should be in a private or package private
+     * location, since it could be modified by malicious code.</p>
+     */
+    int[] rNums = {
+        619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
+        985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
+        733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
+        419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
+        878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
+        862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
+        150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
+        170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
+        73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
+        909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
+        641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
+        161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
+        382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
+        98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
+        227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
+        469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
+        184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
+        715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
+        951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
+        652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
+        645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
+        609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
+        653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
+        411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
+        170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
+        857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
+        669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
+        944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
+        344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
+        897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
+        433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
+        686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
+        946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
+        978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
+        680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
+        707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
+        297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
+        134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
+        343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
+        140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
+        170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
+        369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
+        804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
+        896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
+        661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
+        768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
+        61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
+        372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
+        780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
+        920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
+        645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
+        936, 638
+    };
+}
diff --git a/src/org/apache/tools/bzip2/CBZip2InputStream.java b/src/org/apache/tools/bzip2/CBZip2InputStream.java
new file mode 100644 (file)
index 0000000..fc25a31
--- /dev/null
@@ -0,0 +1,1063 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+package org.apache.tools.bzip2;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An input stream that decompresses from the BZip2 format (without the file
+ * header chars) to be read as any other stream.
+ *
+ * <p>The decompression requires large amounts of memory. Thus you
+ * should call the {@link #close() close()} method as soon as
+ * possible, to force <tt>CBZip2InputStream</tt> to release the
+ * allocated memory.  See {@link CBZip2OutputStream
+ * CBZip2OutputStream} for information about memory usage.</p>
+ *
+ * <p><tt>CBZip2InputStream</tt> reads bytes from the compressed
+ * source stream via the single byte {@link java.io.InputStream#read()
+ * read()} method exclusively. Thus you should consider to use a
+ * buffered source stream.</p>
+ * 
+ * <p>Instances of this class are not threadsafe.</p>
+ */
+public class CBZip2InputStream extends InputStream implements BZip2Constants {
+
+    /**
+     * Index of the last char in the block, so the block size == last + 1.
+     */
+    private int  last;
+
+    /**
+     * Index in zptr[] of original string after sorting.
+     */
+    private int  origPtr;
+
+    /**
+     * always: in the range 0 .. 9.
+     * The current block size is 100000 * this number.
+     */
+    private int blockSize100k;
+
+    private boolean blockRandomised;
+
+    private int bsBuff;
+    private int bsLive;
+    private final CRC crc = new CRC();
+
+    private int nInUse;
+
+    private InputStream in;
+    private final boolean decompressConcatenated;
+
+    private int currentChar = -1;
+
+    private static final int EOF                  = 0;
+    private static final int START_BLOCK_STATE = 1;
+    private static final int RAND_PART_A_STATE = 2;
+    private static final int RAND_PART_B_STATE = 3;
+    private static final int RAND_PART_C_STATE = 4;
+    private static final int NO_RAND_PART_A_STATE = 5;
+    private static final int NO_RAND_PART_B_STATE = 6;
+    private static final int NO_RAND_PART_C_STATE = 7;
+
+    private int currentState = START_BLOCK_STATE;
+
+    private int storedBlockCRC, storedCombinedCRC;
+    private int computedBlockCRC, computedCombinedCRC;
+
+    // Variables used by setup* methods exclusively
+
+    private int su_count;
+    private int su_ch2;
+    private int su_chPrev;
+    private int su_i2;
+    private int su_j2;
+    private int su_rNToGo;
+    private int su_rTPos;
+    private int su_tPos;
+    private char su_z;
+
+    /**
+     * All memory intensive stuff.
+     * This field is initialized by initBlock().
+     */
+    private CBZip2InputStream.Data data;
+
+    /**
+     * Constructs a new CBZip2InputStream which decompresses bytes read from
+     * the specified stream. This doesn't suppprt decompressing
+     * concatenated .bz2 files.
+     *
+     * <p>Although BZip2 headers are marked with the magic
+     * <tt>"Bz"</tt> this constructor expects the next byte in the
+     * stream to be the first one after the magic.  Thus callers have
+     * to skip the first two bytes. Otherwise this constructor will
+     * throw an exception. </p>
+     * @param in 
+     *
+     * @throws IOException
+     *  if the stream content is malformed or an I/O error occurs.
+     * @throws NullPointerException
+     *  if <tt>in == null</tt>
+     */
+    public CBZip2InputStream(final InputStream in) throws IOException {
+        this(in, false);
+    }
+
+    /**
+     * Constructs a new CBZip2InputStream which decompresses bytes
+     * read from the specified stream.
+     *
+     * <p>Although BZip2 headers are marked with the magic
+     * <tt>"Bz"</tt> this constructor expects the next byte in the
+     * stream to be the first one after the magic.  Thus callers have
+     * to skip the first two bytes. Otherwise this constructor will
+     * throw an exception. </p>
+     *
+     * @param in the InputStream from which this object should be created
+     * @param decompressConcatenated
+     *                     if true, decompress until the end of the input;
+     *                     if false, stop after the first .bz2 stream and
+     *                     leave the input position to point to the next
+     *                     byte after the .bz2 stream
+     *
+     * @throws IOException
+     *             if the stream content is malformed or an I/O error occurs.
+     * @throws NullPointerException
+     *             if <tt>in == null</tt>
+     */
+    public CBZip2InputStream(final InputStream in,
+                             final boolean decompressConcatenated)
+            throws IOException {
+        super();
+
+        this.in = in;
+        this.decompressConcatenated = decompressConcatenated;
+
+        init(true);
+        initBlock();
+        setupBlock();
+    }
+
+  /** {@inheritDoc} */
+  @Override
+  public int read() throws IOException {
+    if (this.in == null)
+      throw new IOException("stream closed");
+    return read0();
+  }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.io.InputStream#read(byte[], int, int)
+     */
+    @Override
+    public int read(final byte[] dest, final int offs, final int len)
+        throws IOException {
+        if (offs < 0) {
+            throw new IndexOutOfBoundsException("offs(" + offs + ") < 0.");
+        }
+        if (len < 0) {
+            throw new IndexOutOfBoundsException("len(" + len + ") < 0.");
+        }
+        if (offs + len > dest.length) {
+            throw new IndexOutOfBoundsException("offs(" + offs + ") + len("
+                                                + len + ") > dest.length("
+                                                + dest.length + ").");
+        }
+        if (this.in == null) {
+            throw new IOException("stream closed");
+        }
+
+        final int hi = offs + len;
+        int destOffs = offs;
+        for (int b; (destOffs < hi) && ((b = read0()) >= 0);) {
+            dest[destOffs++] = (byte) b;
+        }
+
+        return (destOffs == offs) ? -1 : (destOffs - offs);
+    }
+
+    private void makeMaps() {
+        final boolean[] inUse   = this.data.inUse;
+        final byte[] seqToUnseq = this.data.seqToUnseq;
+
+        int nInUseShadow = 0;
+
+        for (int i = 0; i < 256; i++) {
+            if (inUse[i]) {
+                seqToUnseq[nInUseShadow++] = (byte) i;
+            }
+        }
+
+        this.nInUse = nInUseShadow;
+    }
+
+    private int read0() throws IOException {
+        final int retChar = this.currentChar;
+
+        switch (this.currentState) {
+        case EOF:
+            return -1;
+
+        case START_BLOCK_STATE:
+            throw new IllegalStateException();
+
+        case RAND_PART_A_STATE:
+            throw new IllegalStateException();
+
+        case RAND_PART_B_STATE:
+            setupRandPartB();
+            break;
+
+        case RAND_PART_C_STATE:
+            setupRandPartC();
+            break;
+
+        case NO_RAND_PART_A_STATE:
+            throw new IllegalStateException();
+
+        case NO_RAND_PART_B_STATE:
+            setupNoRandPartB();
+            break;
+
+        case NO_RAND_PART_C_STATE:
+            setupNoRandPartC();
+            break;
+
+        default:
+            throw new IllegalStateException();
+        }
+
+        return retChar;
+    }
+
+    private boolean init(boolean isFirstStream) throws IOException {
+        if (null == in) {
+            throw new IOException("No InputStream");
+        }
+        
+        if (isFirstStream) {
+            if (in.available() == 0) {
+                throw new IOException("Empty InputStream");
+            }
+        } else {
+            int magic0 = read();
+            if (magic0 == -1) {
+                return false;
+            }
+            int magic1 = read();
+            if (magic0 != 'B' || magic1 != 'Z') {
+                throw new IOException("Garbage after a valid BZip2 stream");
+            }
+        }
+
+        int magic2 = read();
+        if (magic2 != 'h') {
+            throw new IOException(isFirstStream
+                    ? "Stream is not in the BZip2 format"
+                    : "Garbage after a valid BZip2 stream");
+        }
+
+        int blockSize = read();
+        if ((blockSize < '1') || (blockSize > '9')) {
+            throw new IOException("Stream is not BZip2 formatted: illegal "
+                                  + "blocksize " + (char) blockSize);
+        }
+
+        this.blockSize100k = blockSize - '0';
+
+        this.bsLive = 0;
+        this.computedCombinedCRC = 0;
+
+        return true;
+    }
+
+  private void initBlock() throws IOException {
+    char magic0;
+    char magic1;
+    char magic2;
+    char magic3;
+    char magic4;
+    char magic5;
+
+    while (true) {
+      // Get the block magic bytes.
+      magic0 = bsGetUByte();
+      magic1 = bsGetUByte();
+      magic2 = bsGetUByte();
+      magic3 = bsGetUByte();
+      magic4 = bsGetUByte();
+      magic5 = bsGetUByte();
+
+      // If isn't end of stream magic, break out of the loop.
+      if (magic0 != 0x17 || magic1 != 0x72 || magic2 != 0x45 || magic3 != 0x38
+          || magic4 != 0x50 || magic5 != 0x90) {
+        break;
+      }
+
+      // End of stream was reached. Check the combined CRC and
+      // advance to the next .bz2 stream if decoding concatenated
+      // streams.
+      if (complete()) {
+        return;
+      }
+    }
+
+    if (magic0 != 0x31 || // '1'
+        magic1 != 0x41 || // ')'
+        magic2 != 0x59 || // 'Y'
+        magic3 != 0x26 || // '&'
+        magic4 != 0x53 || // 'S'
+        magic5 != 0x59 // 'Y'
+    ) {
+      this.currentState = EOF;
+      throw new IOException("bad block header");
+    }
+    this.storedBlockCRC = bsGetInt();
+    this.blockRandomised = bsR(1) == 1;
+
+    /**
+     * Allocate data here instead in constructor, so we do not allocate it if
+     * the input file is empty.
+     */
+    if (this.data == null) {
+      this.data = new Data(this.blockSize100k);
+    }
+
+    // currBlockNo++;
+    getAndMoveToFrontDecode();
+
+    this.crc.initialiseCRC();
+    this.currentState = START_BLOCK_STATE;
+  }
+
+    private void endBlock() throws IOException {
+        this.computedBlockCRC = this.crc.getFinalCRC();
+
+        // A bad CRC is considered a fatal error.
+        if (this.storedBlockCRC != this.computedBlockCRC) {
+            // make next blocks readable without error
+            // (repair feature, not yet documented, not tested)
+            this.computedCombinedCRC
+                = (this.storedCombinedCRC << 1)
+                | (this.storedCombinedCRC >>> 31);
+            this.computedCombinedCRC ^= this.storedBlockCRC;
+
+            reportCRCError();
+        }
+
+        this.computedCombinedCRC
+            = (this.computedCombinedCRC << 1)
+            | (this.computedCombinedCRC >>> 31);
+        this.computedCombinedCRC ^= this.computedBlockCRC;
+    }
+
+    private boolean complete() throws IOException {
+        this.storedCombinedCRC = bsGetInt();
+        this.currentState = EOF;
+        this.data = null;
+
+        if (this.storedCombinedCRC != this.computedCombinedCRC) {
+            reportCRCError();
+        }
+
+        // Look for the next .bz2 stream if decompressing
+        // concatenated files.
+        return !decompressConcatenated || !init(false);
+    }
+
+    @Override
+    public void close() throws IOException {
+        InputStream inShadow = this.in;
+        if (inShadow != null) {
+            try {
+                if (inShadow != System.in) {
+                    inShadow.close();
+                }
+            } finally {
+                this.data = null;
+                this.in = null;
+            }
+        }
+    }
+
+    private int bsR(final int n) throws IOException {
+        int bsLiveShadow = this.bsLive;
+        int bsBuffShadow = this.bsBuff;
+
+        if (bsLiveShadow < n) {
+            final InputStream inShadow = this.in;
+            do {
+                int thech = read();//inShadow.read();
+
+                if (thech < 0) {
+                    throw new IOException("unexpected end of stream");
+                }
+
+                bsBuffShadow = (bsBuffShadow << 8) | thech;
+                bsLiveShadow += 8;
+            } while (bsLiveShadow < n);
+
+            this.bsBuff = bsBuffShadow;
+        }
+
+        this.bsLive = bsLiveShadow - n;
+        return (bsBuffShadow >> (bsLiveShadow - n)) & ((1 << n) - 1);
+    }
+
+    private boolean bsGetBit() throws IOException {
+        int bsLiveShadow = this.bsLive;
+        int bsBuffShadow = this.bsBuff;
+
+        if (bsLiveShadow < 1) {
+            int thech = read();
+
+            if (thech < 0) {
+                throw new IOException("unexpected end of stream");
+            }
+
+            bsBuffShadow = (bsBuffShadow << 8) | thech;
+            bsLiveShadow += 8;
+            this.bsBuff = bsBuffShadow;
+        }
+
+        this.bsLive = bsLiveShadow - 1;
+        return ((bsBuffShadow >> (bsLiveShadow - 1)) & 1) != 0;
+    }
+
+    private char bsGetUByte() throws IOException {
+        return (char) bsR(8);
+    }
+
+    private int bsGetInt() throws IOException {
+        return (((((bsR(8) << 8) | bsR(8)) << 8) | bsR(8)) << 8) | bsR(8);
+    }
+
+    /**
+     * Called by createHuffmanDecodingTables() exclusively.
+     * @param limit 
+     * @param base 
+     * @param perm 
+     * @param length 
+     * @param minLen 
+     * @param maxLen 
+     * @param alphaSize 
+     */
+    private static void hbCreateDecodeTables(final int[] limit,
+                                             final int[] base,
+                                             final int[] perm,
+                                             final char[] length,
+                                             final int minLen,
+                                             final int maxLen,
+                                             final int alphaSize) {
+        for (int i = minLen, pp = 0; i <= maxLen; i++) {
+            for (int j = 0; j < alphaSize; j++) {
+                if (length[j] == i) {
+                    perm[pp++] = j;
+                }
+            }
+        }
+
+        for (int i = MAX_CODE_LEN; --i > 0;) {
+            base[i] = 0;
+            limit[i] = 0;
+        }
+
+        for (int i = 0; i < alphaSize; i++) {
+            base[length[i] + 1]++;
+        }
+
+        for (int i = 1, b = base[0]; i < MAX_CODE_LEN; i++) {
+            b += base[i];
+            base[i] = b;
+        }
+
+        for (int i = minLen, vec = 0, b = base[i]; i <= maxLen; i++) {
+            final int nb = base[i + 1];
+            vec += nb - b;
+            b = nb;
+            limit[i] = vec - 1;
+            vec <<= 1;
+        }
+
+        for (int i = minLen + 1; i <= maxLen; i++) {
+            base[i] = ((limit[i - 1] + 1) << 1) - base[i];
+        }
+    }
+
+    private void recvDecodingTables() throws IOException {
+        final Data dataShadow     = this.data;
+        final boolean[] inUse     = dataShadow.inUse;
+        final byte[] pos          = dataShadow.recvDecodingTables_pos;
+        final byte[] selector     = dataShadow.selector;
+        final byte[] selectorMtf  = dataShadow.selectorMtf;
+
+        int inUse16 = 0;
+
+        /* Receive the mapping table */
+        for (int i = 0; i < 16; i++) {
+            if (bsGetBit()) {
+                inUse16 |= 1 << i;
+            }
+        }
+
+        for (int i = 256; --i >= 0;) {
+            inUse[i] = false;
+        }
+
+        for (int i = 0; i < 16; i++) {
+            if ((inUse16 & (1 << i)) != 0) {
+                final int i16 = i << 4;
+                for (int j = 0; j < 16; j++) {
+                    if (bsGetBit()) {
+                        inUse[i16 + j] = true;
+                    }
+                }
+            }
+        }
+
+        makeMaps();
+        final int alphaSize = this.nInUse + 2;
+
+        /* Now the selectors */
+        final int nGroups = bsR(3);
+        final int nSelectors = bsR(15);
+
+        for (int i = 0; i < nSelectors; i++) {
+            int j = 0;
+            while (bsGetBit()) {
+                j++;
+            }
+            selectorMtf[i] = (byte) j;
+        }
+
+        /* Undo the MTF values for the selectors. */
+        for (int v = nGroups; --v >= 0;) {
+            pos[v] = (byte) v;
+        }
+
+        for (int i = 0; i < nSelectors; i++) {
+            int v = selectorMtf[i] & 0xff;
+            final byte tmp = pos[v];
+            while (v > 0) {
+                // nearly all times v is zero, 4 in most other cases
+                pos[v] = pos[v - 1];
+                v--;
+            }
+            pos[0] = tmp;
+            selector[i] = tmp;
+        }
+
+        final char[][] len  = dataShadow.temp_charArray2d;
+
+        /* Now the coding tables */
+        for (int t = 0; t < nGroups; t++) {
+            int curr = bsR(5);
+            final char[] len_t = len[t];
+            for (int i = 0; i < alphaSize; i++) {
+                while (bsGetBit()) {
+                    curr += bsGetBit() ? -1 : 1;
+                }
+                len_t[i] = (char) curr;
+            }
+        }
+
+        // finally create the Huffman tables
+        createHuffmanDecodingTables(alphaSize, nGroups);
+    }
+
+    /**
+     * Called by recvDecodingTables() exclusively.
+     * @param alphaSize 
+     * @param nGroups 
+     */
+    private void createHuffmanDecodingTables(final int alphaSize,
+                                             final int nGroups) {
+        final Data dataShadow = this.data;
+        final char[][] len  = dataShadow.temp_charArray2d;
+        final int[] minLens = dataShadow.minLens;
+        final int[][] limit = dataShadow.limit;
+        final int[][] base  = dataShadow.base;
+        final int[][] perm  = dataShadow.perm;
+
+        for (int t = 0; t < nGroups; t++) {
+            int minLen = 32;
+            int maxLen = 0;
+            final char[] len_t = len[t];
+            for (int i = alphaSize; --i >= 0;) {
+                final char lent = len_t[i];
+                if (lent > maxLen) {
+                    maxLen = lent;
+                }
+                if (lent < minLen) {
+                    minLen = lent;
+                }
+            }
+            hbCreateDecodeTables(limit[t], base[t], perm[t], len[t], minLen,
+                                 maxLen, alphaSize);
+            minLens[t] = minLen;
+        }
+    }
+
+  private void getAndMoveToFrontDecode() throws IOException {
+    this.origPtr = bsR(24);
+    recvDecodingTables();
+
+    final InputStream inShadow = this.in;
+    final Data dataShadow = this.data;
+    final byte[] ll8 = dataShadow.ll8;
+    final int[] unzftab = dataShadow.unzftab;
+    final byte[] selector = dataShadow.selector;
+    final byte[] seqToUnseq = dataShadow.seqToUnseq;
+    final char[] yy = dataShadow.getAndMoveToFrontDecode_yy;
+    final int[] minLens = dataShadow.minLens;
+    final int[][] limit = dataShadow.limit;
+    final int[][] base = dataShadow.base;
+    final int[][] perm = dataShadow.perm;
+    final int limitLast = this.blockSize100k * 100000;
+
+    /*
+      Setting up the unzftab entries here is not strictly
+      necessary, but it does save having to do it later
+      in a separate pass, and so saves a block's worth of
+      cache misses.
+    */
+    for (int i = 256; --i >= 0;) {
+      yy[i] = (char) i;
+      unzftab[i] = 0;
+    }
+
+    int groupNo = 0;
+    int groupPos = G_SIZE - 1;
+    final int eob = this.nInUse + 1;
+    int nextSym = getAndMoveToFrontDecode0(0);
+    int bsBuffShadow = this.bsBuff;
+    int bsLiveShadow = this.bsLive;
+    int lastShadow = -1;
+    int zt = selector[groupNo] & 0xff;
+    int[] base_zt = base[zt];
+    int[] limit_zt = limit[zt];
+    int[] perm_zt = perm[zt];
+    int minLens_zt = minLens[zt];
+
+    while (nextSym != eob) {
+      if ((nextSym == RUNA) || (nextSym == RUNB)) {
+        int s = -1;
+
+        for (int n = 1; true; n <<= 1) {
+          if (nextSym == RUNA) {
+            s += n;
+          } else if (nextSym == RUNB) {
+            s += n << 1;
+          } else {
+            break;
+          }
+
+          if (groupPos == 0) {
+            groupPos = G_SIZE - 1;
+            zt = selector[++groupNo] & 0xff;
+            base_zt = base[zt];
+            limit_zt = limit[zt];
+            perm_zt = perm[zt];
+            minLens_zt = minLens[zt];
+          } else {
+            groupPos--;
+          }
+
+          int zn = minLens_zt;
+
+          // Inlined:
+          // int zvec = bsR(zn);
+          while (bsLiveShadow < zn) {
+            final int thech = read();//inShadow.read();
+            if (thech < 0)
+              throw new IOException("unexpected end of stream");
+
+            bsBuffShadow = (bsBuffShadow << 8) | thech;
+            bsLiveShadow += 8;
+            continue;
+          }
+          int zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1);
+          bsLiveShadow -= zn;
+
+          while (zvec > limit_zt[zn]) {
+            zn++;
+            while (bsLiveShadow < 1) {
+              final int thech = read();//inShadow.read();
+              if (thech < 0)
+                throw new IOException("unexpected end of stream");
+              bsBuffShadow = (bsBuffShadow << 8) | thech;
+              bsLiveShadow += 8;
+              continue;
+            }
+            bsLiveShadow--;
+            zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1);
+          }
+          nextSym = perm_zt[zvec - base_zt[zn]];
+        }
+
+        final byte ch = seqToUnseq[yy[0]];
+        unzftab[ch & 0xff] += s + 1;
+
+        while (s-- >= 0) {
+          ll8[++lastShadow] = ch;
+        }
+
+        if (lastShadow >= limitLast) {
+          throw new IOException("block overrun");
+        }
+      } else {
+        if (++lastShadow >= limitLast) {
+          throw new IOException("block overrun");
+        }
+
+        final char tmp = yy[nextSym - 1];
+        unzftab[seqToUnseq[tmp] & 0xff]++;
+        ll8[lastShadow] = seqToUnseq[tmp];
+
+        /*
+          This loop is hammered during decompression,
+          hence avoid native method call overhead of
+          System.arraycopy for very small ranges to copy.
+        */
+        if (nextSym <= 16) {
+          for (int j = nextSym - 1; j > 0;) {
+            yy[j] = yy[--j];
+          }
+        } else {
+          System.arraycopy(yy, 0, yy, 1, nextSym - 1);
+        }
+
+        yy[0] = tmp;
+
+        if (groupPos == 0) {
+          groupPos = G_SIZE - 1;
+          zt = selector[++groupNo] & 0xff;
+          base_zt = base[zt];
+          limit_zt = limit[zt];
+          perm_zt = perm[zt];
+          minLens_zt = minLens[zt];
+        } else {
+          groupPos--;
+        }
+
+        int zn = minLens_zt;
+
+        // Inlined:
+        // int zvec = bsR(zn);
+        while (bsLiveShadow < zn) {
+          final int thech = read();//inShadow.read();
+          if (thech < 0)
+            throw new IOException("unexpected end of stream");
+          bsBuffShadow = (bsBuffShadow << 8) | thech;
+          bsLiveShadow += 8;
+          continue;
+        }
+        int zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1);
+        bsLiveShadow -= zn;
+
+        while (zvec > limit_zt[zn]) {
+          zn++;
+          while (bsLiveShadow < 1) {
+            final int thech = read();//inShadow.read();
+            if (thech <0) 
+              throw new IOException("unexpected end of stream");
+              bsBuffShadow = (bsBuffShadow << 8) | thech;
+              bsLiveShadow += 8;
+              continue;
+          }
+          bsLiveShadow--;
+          zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1);
+        }
+        nextSym = perm_zt[zvec - base_zt[zn]];
+      }
+    }
+
+    this.last = lastShadow;
+    this.bsLive = bsLiveShadow;
+    this.bsBuff = bsBuffShadow;
+  }
+
+  private int getAndMoveToFrontDecode0(final int groupNo) throws IOException {
+    final InputStream inShadow = this.in;
+    final Data dataShadow = this.data;
+    final int zt = dataShadow.selector[groupNo] & 0xff;
+    final int[] limit_zt = dataShadow.limit[zt];
+    int zn = dataShadow.minLens[zt];
+    int zvec = bsR(zn);
+    int bsLiveShadow = this.bsLive;
+    int bsBuffShadow = this.bsBuff;
+
+    while (zvec > limit_zt[zn]) {
+      zn++;
+      while (bsLiveShadow < 1) {
+        final int thech = read();//inShadow.read();
+
+        if (thech < 0)
+          throw new IOException("unexpected end of stream");
+
+        bsBuffShadow = (bsBuffShadow << 8) | thech;
+        bsLiveShadow += 8;
+        continue;
+      }
+      bsLiveShadow--;
+      zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1);
+    }
+
+    this.bsLive = bsLiveShadow;
+    this.bsBuff = bsBuffShadow;
+
+    return dataShadow.perm[zt][zvec - dataShadow.base[zt][zn]];
+  }
+
+    private void setupBlock() throws IOException {
+        if (this.data == null) {
+            return;
+        }
+
+        final int[] cftab = this.data.cftab;
+        final int[] tt    = this.data.initTT(this.last + 1);
+        final byte[] ll8  = this.data.ll8;
+        cftab[0] = 0;
+        System.arraycopy(this.data.unzftab, 0, cftab, 1, 256);
+
+        for (int i = 1, c = cftab[0]; i <= 256; i++) {
+            c += cftab[i];
+            cftab[i] = c;
+        }
+
+        for (int i = 0, lastShadow = this.last; i <= lastShadow; i++) {
+            tt[cftab[ll8[i] & 0xff]++] = i;
+        }
+
+        if ((this.origPtr < 0) || (this.origPtr >= tt.length)) {
+            throw new IOException("stream corrupted");
+        }
+
+        this.su_tPos = tt[this.origPtr];
+        this.su_count = 0;
+        this.su_i2 = 0;
+        this.su_ch2 = 256;   /* not a char and not EOF */
+
+        if (this.blockRandomised) {
+            this.su_rNToGo = 0;
+            this.su_rTPos = 0;
+            setupRandPartA();
+        } else {
+            setupNoRandPartA();
+        }
+    }
+
+    private void setupRandPartA() throws IOException {
+        if (this.su_i2 <= this.last) {
+            this.su_chPrev = this.su_ch2;
+            int su_ch2Shadow = this.data.ll8[this.su_tPos] & 0xff;
+            this.su_tPos = this.data.tt[this.su_tPos];
+            if (this.su_rNToGo == 0) {
+                this.su_rNToGo = BZip2Constants.rNums[this.su_rTPos] - 1;
+                if (++this.su_rTPos == 512) {
+                    this.su_rTPos = 0;
+                }
+            } else {
+                this.su_rNToGo--;
+            }
+            this.su_ch2 = su_ch2Shadow ^= (this.su_rNToGo == 1) ? 1 : 0;
+            this.su_i2++;
+            this.currentChar = su_ch2Shadow;
+            this.currentState = RAND_PART_B_STATE;
+            this.crc.updateCRC(su_ch2Shadow);
+        } else {
+            endBlock();
+            initBlock();
+            setupBlock();
+        }
+    }
+
+    private void setupNoRandPartA() throws IOException {
+        if (this.su_i2 <= this.last) {
+            this.su_chPrev = this.su_ch2;
+            int su_ch2Shadow = this.data.ll8[this.su_tPos] & 0xff;
+            this.su_ch2 = su_ch2Shadow;
+            this.su_tPos = this.data.tt[this.su_tPos];
+            this.su_i2++;
+            this.currentChar = su_ch2Shadow;
+            this.currentState = NO_RAND_PART_B_STATE;
+            this.crc.updateCRC(su_ch2Shadow);
+        } else {
+            this.currentState = NO_RAND_PART_A_STATE;
+            endBlock();
+            initBlock();
+            setupBlock();
+        }
+    }
+
+    private void setupRandPartB() throws IOException {
+        if (this.su_ch2 != this.su_chPrev) {
+            this.currentState = RAND_PART_A_STATE;
+            this.su_count = 1;
+            setupRandPartA();
+        } else if (++this.su_count >= 4) {
+            this.su_z = (char) (this.data.ll8[this.su_tPos] & 0xff);
+            this.su_tPos = this.data.tt[this.su_tPos];
+            if (this.su_rNToGo == 0) {
+                this.su_rNToGo = BZip2Constants.rNums[this.su_rTPos] - 1;
+                if (++this.su_rTPos == 512) {
+                    this.su_rTPos = 0;
+                }
+            } else {
+                this.su_rNToGo--;
+            }
+            this.su_j2 = 0;
+            this.currentState = RAND_PART_C_STATE;
+            if (this.su_rNToGo == 1) {
+                this.su_z ^= 1;
+            }
+            setupRandPartC();
+        } else {
+            this.currentState = RAND_PART_A_STATE;
+            setupRandPartA();
+        }
+    }
+
+    private void setupRandPartC() throws IOException {
+        if (this.su_j2 < this.su_z) {
+            this.currentChar = this.su_ch2;
+            this.crc.updateCRC(this.su_ch2);
+            this.su_j2++;
+        } else {
+            this.currentState = RAND_PART_A_STATE;
+            this.su_i2++;
+            this.su_count = 0;
+            setupRandPartA();
+        }
+    }
+
+    private void setupNoRandPartB() throws IOException {
+        if (this.su_ch2 != this.su_chPrev) {
+            this.su_count = 1;
+            setupNoRandPartA();
+        } else if (++this.su_count >= 4) {
+            this.su_z = (char) (this.data.ll8[this.su_tPos] & 0xff);
+            this.su_tPos = this.data.tt[this.su_tPos];
+            this.su_j2 = 0;
+            setupNoRandPartC();
+        } else {
+            setupNoRandPartA();
+        }
+    }
+
+    private void setupNoRandPartC() throws IOException {
+        if (this.su_j2 < this.su_z) {
+            int su_ch2Shadow = this.su_ch2;
+            this.currentChar = su_ch2Shadow;
+            this.crc.updateCRC(su_ch2Shadow);
+            this.su_j2++;
+            this.currentState = NO_RAND_PART_C_STATE;
+        } else {
+            this.su_i2++;
+            this.su_count = 0;
+            setupNoRandPartA();
+        }
+    }
+
+    private static final class Data extends Object {
+
+        // (with blockSize 900k)
+        final boolean[] inUse   = new boolean[256];                                   //      256 byte
+
+        final byte[] seqToUnseq   = new byte[256];                                    //      256 byte
+        final byte[] selector     = new byte[MAX_SELECTORS];                          //    18002 byte
+        final byte[] selectorMtf  = new byte[MAX_SELECTORS];                          //    18002 byte
+
+        /**
+         * Freq table collected to save a pass over the data during
+         * decompression.
+         */
+        final int[] unzftab = new int[256];                                           //     1024 byte
+
+        final int[][] limit = new int[N_GROUPS][MAX_ALPHA_SIZE];                      //     6192 byte
+        final int[][] base  = new int[N_GROUPS][MAX_ALPHA_SIZE];                      //     6192 byte
+        final int[][] perm  = new int[N_GROUPS][MAX_ALPHA_SIZE];                      //     6192 byte
+        final int[] minLens = new int[N_GROUPS];                                      //       24 byte
+
+        final int[]     cftab     = new int[257];                                     //     1028 byte
+        final char[]    getAndMoveToFrontDecode_yy = new char[256];                   //      512 byte
+        final char[][]  temp_charArray2d  = new char[N_GROUPS][MAX_ALPHA_SIZE];       //     3096 byte
+        final byte[] recvDecodingTables_pos = new byte[N_GROUPS];                     //        6 byte
+        //---------------
+        //    60798 byte
+
+        int[] tt;                                                                     //  3600000 byte
+        byte[] ll8;                                                                   //   900000 byte
+        //---------------
+        //  4560782 byte
+        //===============
+
+        Data(int blockSize100k) {
+            super();
+
+            this.ll8 = new byte[blockSize100k * BZip2Constants.baseBlockSize];
+        }
+
+        /**
+         * Initializes the {@link #tt} array.
+         *
+         * This method is called when the required length of the array
+         * is known.  I don't initialize it at construction time to
+         * avoid unnecessary memory allocation when compressing small
+         * files.
+         * @param length 
+         * @return int array
+         */
+        final int[] initTT(int length) {
+            int[] ttShadow = this.tt;
+
+            // tt.length should always be >= length, but theoretically
+            // it can happen, if the compressor mixed small and large
+            // blocks.  Normally only the last block will be smaller
+            // than others.
+            if ((ttShadow == null) || (ttShadow.length < length)) {
+                this.tt = ttShadow = new int[length];
+            }
+
+            return ttShadow;
+        }
+
+    }
+
+    @SuppressWarnings("unused")
+    private static void reportCRCError() throws IOException {
+        // The clean way would be to throw an exception.
+        //throw new IOException("crc error");
+
+        // Just print a message, like the previous versions of this class did
+        System.err.println("BZip2 CRC error");
+    }
+
+}
+
diff --git a/src/org/apache/tools/bzip2/CBZip2InputStreamFactory.java b/src/org/apache/tools/bzip2/CBZip2InputStreamFactory.java
new file mode 100644 (file)
index 0000000..23923a3
--- /dev/null
@@ -0,0 +1,21 @@
+package org.apache.tools.bzip2;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class CBZip2InputStreamFactory {
+  
+  /**
+   * jsjava addition for reflection
+   * 
+   * @param is
+   * @return BZip2 input stream
+   * @throws IOException 
+   */
+  public CBZip2InputStream getStream(InputStream is) throws IOException {
+    is.read(new byte[2], 0, 2);
+    return new CBZip2InputStream(is);
+  }
+
+}
+
diff --git a/src/org/apache/tools/bzip2/CRC.java b/src/org/apache/tools/bzip2/CRC.java
new file mode 100644 (file)
index 0000000..0102c8e
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.apache.tools.bzip2;
+
+/**
+ * A simple class the hold and calculate the CRC for sanity checking
+ * of the data.
+ *
+ */
+final class CRC {
+    static final int crc32Table[] = {
+        0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+        0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+        0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+        0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+        0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+        0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+        0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+        0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+        0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+        0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+        0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+        0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+        0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+        0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+        0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+        0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+        0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+        0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+        0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+        0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+        0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+        0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+        0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+        0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+        0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+        0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+        0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+        0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+        0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+        0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+        0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+        0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+        0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+        0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+        0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+        0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+        0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+        0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+        0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+        0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+        0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+        0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+        0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+        0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+        0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+        0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+        0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+        0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+        0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+        0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+        0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+        0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+        0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+        0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+        0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+        0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+        0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+        0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+        0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+        0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+        0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+        0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+        0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+        0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+    };
+
+    CRC() {
+        initialiseCRC();
+    }
+
+    void initialiseCRC() {
+        globalCrc = 0xffffffff;
+    }
+
+    int getFinalCRC() {
+        return ~globalCrc;
+    }
+
+    int getGlobalCRC() {
+        return globalCrc;
+    }
+
+    void setGlobalCRC(int newCrc) {
+        globalCrc = newCrc;
+    }
+
+    void updateCRC(int inCh) {
+        int temp = (globalCrc >> 24) ^ inCh;
+        if (temp < 0) {
+            temp = 256 + temp;
+        }
+        globalCrc = (globalCrc << 8) ^ CRC.crc32Table[temp];
+    }
+
+    void updateCRC(int inCh, int repeat) {
+        int globalCrcShadow = this.globalCrc;
+        while (repeat-- > 0) {
+            int temp = (globalCrcShadow >> 24) ^ inCh;
+            globalCrcShadow = (globalCrcShadow << 8) ^ crc32Table[(temp >= 0)
+                                                      ? temp
+                                                      : (temp + 256)];
+        }
+        this.globalCrc = globalCrcShadow;
+    }
+
+    int globalCrc;
+}
+
diff --git a/src/org/xml/sax/AttributeList.java b/src/org/xml/sax/AttributeList.java
new file mode 100644 (file)
index 0000000..9285eac
--- /dev/null
@@ -0,0 +1,193 @@
+// SAX Attribute List Interface.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: AttributeList.java,v 1.7 2004/04/26 17:34:34 dmegginson Exp $
+
+package org.xml.sax;
+
+/**
+ * Interface for an element's attribute specifications.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is the original SAX1 interface for reporting an element's
+ * attributes.  Unlike the new {@link org.xml.sax.Attributes Attributes}
+ * interface, it does not support Namespace-related information.</p>
+ *
+ * <p>When an attribute list is supplied as part of a
+ * {@link org.xml.sax.DocumentHandler#startElement startElement}
+ * event, the list will return valid results only during the
+ * scope of the event; once the event handler returns control
+ * to the parser, the attribute list is invalid.  To save a
+ * persistent copy of the attribute list, use the SAX1
+ * {@link org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
+ * helper class.</p>
+ *
+ * <p>An attribute list includes only attributes that have been
+ * specified or defaulted: #IMPLIED attributes will not be included.</p>
+ *
+ * <p>There are two ways for the SAX application to obtain information
+ * from the AttributeList.  First, it can iterate through the entire
+ * list:</p>
+ *
+ * <pre>
+ * public void startElement (String name, AttributeList atts) {
+ *   for (int i = 0; i < atts.getLength(); i++) {
+ *     String name = atts.getName(i);
+ *     String type = atts.getType(i);
+ *     String value = atts.getValue(i);
+ *     [...]
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>(Note that the result of getLength() will be zero if there
+ * are no attributes.)
+ *
+ * <p>As an alternative, the application can request the value or
+ * type of specific attributes:</p>
+ *
+ * <pre>
+ * public void startElement (String name, AttributeList atts) {
+ *   String identifier = atts.getValue("id");
+ *   String label = atts.getValue("label");
+ *   [...]
+ * }
+ * </pre>
+ *
+ * @deprecated This interface has been replaced by the SAX2
+ *             {@link org.xml.sax.Attributes Attributes}
+ *             interface, which includes Namespace support.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.DocumentHandler#startElement startElement
+ * @see org.xml.sax.helpers.AttributeListImpl AttributeListImpl
+ */
+public interface AttributeList {
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Iteration methods.
+    ////////////////////////////////////////////////////////////////////
+    
+
+    /**
+     * Return the number of attributes in this list.
+     *
+     * <p>The SAX parser may provide attributes in any
+     * arbitrary order, regardless of the order in which they were
+     * declared or specified.  The number of attributes may be
+     * zero.</p>
+     *
+     * @return The number of attributes in the list.  
+     */
+    public abstract int getLength ();
+    
+    
+    /**
+     * Return the name of an attribute in this list (by position).
+     *
+     * <p>The names must be unique: the SAX parser shall not include the
+     * same attribute twice.  Attributes without values (those declared
+     * #IMPLIED without a value specified in the start tag) will be
+     * omitted from the list.</p>
+     *
+     * <p>If the attribute name has a namespace prefix, the prefix
+     * will still be attached.</p>
+     *
+     * @param i The index of the attribute in the list (starting at 0).
+     * @return The name of the indexed attribute, or null
+     *         if the index is out of range.
+     * @see #getLength 
+     */
+    public abstract String getName (int i);
+    
+    
+    /**
+     * Return the type of an attribute in the list (by position).
+     *
+     * <p>The attribute type is one of the strings "CDATA", "ID",
+     * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES",
+     * or "NOTATION" (always in upper case).</p>
+     *
+     * <p>If the parser has not read a declaration for the attribute,
+     * or if the parser does not report attribute types, then it must
+     * return the value "CDATA" as stated in the XML 1.0 Recommentation
+     * (clause 3.3.3, "Attribute-Value Normalization").</p>
+     *
+     * <p>For an enumerated attribute that is not a notation, the
+     * parser will report the type as "NMTOKEN".</p>
+     *
+     * @param i The index of the attribute in the list (starting at 0).
+     * @return The attribute type as a string, or
+     *         null if the index is out of range.
+     * @see #getLength 
+     * @see #getType(java.lang.String)
+     */
+    public abstract String getType (int i);
+    
+    
+    /**
+     * Return the value of an attribute in the list (by position).
+     *
+     * <p>If the attribute value is a list of tokens (IDREFS,
+     * ENTITIES, or NMTOKENS), the tokens will be concatenated
+     * into a single string separated by whitespace.</p>
+     *
+     * @param i The index of the attribute in the list (starting at 0).
+     * @return The attribute value as a string, or
+     *         null if the index is out of range.
+     * @see #getLength
+     * @see #getValue(java.lang.String)
+     */
+    public abstract String getValue (int i);
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Lookup methods.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Return the type of an attribute in the list (by name).
+     *
+     * <p>The return value is the same as the return value for
+     * getType(int).</p>
+     *
+     * <p>If the attribute name has a namespace prefix in the document,
+     * the application must include the prefix here.</p>
+     *
+     * @param name The name of the attribute.
+     * @return The attribute type as a string, or null if no
+     *         such attribute exists.
+     * @see #getType(int)
+     */
+    public abstract String getType (String name);
+    
+    
+    /**
+     * Return the value of an attribute in the list (by name).
+     *
+     * <p>The return value is the same as the return value for
+     * getValue(int).</p>
+     *
+     * <p>If the attribute name has a namespace prefix in the document,
+     * the application must include the prefix here.</p>
+     *
+     * @param name the name of the attribute to return
+     * @return The attribute value as a string, or null if
+     *         no such attribute exists.
+     * @see #getValue(int)
+     */
+    public abstract String getValue (String name);
+    
+}
+
+// end of AttributeList.java
diff --git a/src/org/xml/sax/Attributes.java b/src/org/xml/sax/Attributes.java
new file mode 100644 (file)
index 0000000..b25432d
--- /dev/null
@@ -0,0 +1,257 @@
+// Attributes.java - attribute list with Namespace support
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: Attributes.java,v 1.13 2004/03/18 12:28:05 dmegginson Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Interface for a list of XML attributes.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This interface allows access to a list of attributes in
+ * three different ways:</p>
+ *
+ * <ol>
+ * <li>by attribute index;</li>
+ * <li>by Namespace-qualified name; or</li>
+ * <li>by qualified (prefixed) name.</li>
+ * </ol>
+ *
+ * <p>The list will not contain attributes that were declared
+ * #IMPLIED but not specified in the start tag.  It will also not
+ * contain attributes used as Namespace declarations (xmlns*) unless
+ * the <code>http://xml.org/sax/features/namespace-prefixes</code> 
+ * feature is set to <var>true</var> (it is <var>false</var> by 
+ * default).
+ * Because SAX2 conforms to the original "Namespaces in XML"
+ * recommendation, it normally does not
+ * give namespace declaration attributes a namespace URI.
+ * </p>
+ *
+ * <p>Some SAX2 parsers may support using an optional feature flag
+ * (<code>http://xml.org/sax/features/xmlns-uris</code>) to request
+ * that those attributes be given URIs, conforming to a later
+ * backwards-incompatible revision of that recommendation.  (The
+ * attribute's "local name" will be the prefix, or "xmlns" when
+ * defining a default element namespace.)  For portability, handler
+ * code should always resolve that conflict, rather than requiring
+ * parsers that can change the setting of that feature flag.  </p>
+ *
+ * <p>If the namespace-prefixes feature (see above) is
+ * <var>false</var>, access by qualified name may not be available; if
+ * the <code>http://xml.org/sax/features/namespaces</code> feature is
+ * <var>false</var>, access by Namespace-qualified names may not be
+ * available.</p>
+ *
+ * <p>This interface replaces the now-deprecated SAX1 {@link
+ * org.xml.sax.AttributeList AttributeList} interface, which does not 
+ * contain Namespace support.  In addition to Namespace support, it 
+ * adds the <var>getIndex</var> methods (below).</p>
+ *
+ * <p>The order of attributes in the list is unspecified, and will
+ * vary from implementation to implementation.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.helpers.AttributesImpl
+ * @see org.xml.sax.ext.DeclHandler#attributeDecl
+ */
+public interface Attributes
+{
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Indexed access.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Return the number of attributes in the list.
+     *
+     * <p>Once you know the number of attributes, you can iterate
+     * through the list.</p>
+     *
+     * @return The number of attributes in the list.
+     * @see #getURI(int)
+     * @see #getLocalName(int)
+     * @see #getQName(int)
+     * @see #getType(int)
+     * @see #getValue(int)
+     */
+    public abstract int getLength ();
+
+
+    /**
+     * Look up an attribute's Namespace URI by index.
+     *
+     * @param index The attribute index (zero-based).
+     * @return The Namespace URI, or the empty string if none
+     *         is available, or null if the index is out of
+     *         range.
+     * @see #getLength
+     */
+    public abstract String getURI (int index);
+
+
+    /**
+     * Look up an attribute's local name by index.
+     *
+     * @param index The attribute index (zero-based).
+     * @return The local name, or the empty string if Namespace
+     *         processing is not being performed, or null
+     *         if the index is out of range.
+     * @see #getLength
+     */
+    public abstract String getLocalName (int index);
+
+
+    /**
+     * Look up an attribute's XML qualified (prefixed) name by index.
+     *
+     * @param index The attribute index (zero-based).
+     * @return The XML qualified name, or the empty string
+     *         if none is available, or null if the index
+     *         is out of range.
+     * @see #getLength
+     */
+    public abstract String getQName (int index);
+
+
+    /**
+     * Look up an attribute's type by index.
+     *
+     * <p>The attribute type is one of the strings "CDATA", "ID",
+     * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES",
+     * or "NOTATION" (always in upper case).</p>
+     *
+     * <p>If the parser has not read a declaration for the attribute,
+     * or if the parser does not report attribute types, then it must
+     * return the value "CDATA" as stated in the XML 1.0 Recommendation
+     * (clause 3.3.3, "Attribute-Value Normalization").</p>
+     *
+     * <p>For an enumerated attribute that is not a notation, the
+     * parser will report the type as "NMTOKEN".</p>
+     *
+     * @param index The attribute index (zero-based).
+     * @return The attribute's type as a string, or null if the
+     *         index is out of range.
+     * @see #getLength
+     */
+    public abstract String getType (int index);
+
+
+    /**
+     * Look up an attribute's value by index.
+     *
+     * <p>If the attribute value is a list of tokens (IDREFS,
+     * ENTITIES, or NMTOKENS), the tokens will be concatenated
+     * into a single string with each token separated by a
+     * single space.</p>
+     *
+     * @param index The attribute index (zero-based).
+     * @return The attribute's value as a string, or null if the
+     *         index is out of range.
+     * @see #getLength
+     */
+    public abstract String getValue (int index);
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Name-based query.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Look up the index of an attribute by Namespace name.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return The index of the attribute, or -1 if it does not
+     *         appear in the list.
+     */
+    public int getIndex (String uri, String localName);
+
+
+    /**
+     * Look up the index of an attribute by XML qualified (prefixed) name.
+     *
+     * @param qName The qualified (prefixed) name.
+     * @return The index of the attribute, or -1 if it does not
+     *         appear in the list.
+     */
+    public int getIndex (String qName);
+
+
+    /**
+     * Look up an attribute's type by Namespace name.
+     *
+     * <p>See {@link #getType(int) getType(int)} for a description
+     * of the possible types.</p>
+     *
+     * @param uri The Namespace URI, or the empty String if the
+     *        name has no Namespace URI.
+     * @param localName The local name of the attribute.
+     * @return The attribute type as a string, or null if the
+     *         attribute is not in the list or if Namespace
+     *         processing is not being performed.
+     */
+    public abstract String getType (String uri, String localName);
+
+
+    /**
+     * Look up an attribute's type by XML qualified (prefixed) name.
+     *
+     * <p>See {@link #getType(int) getType(int)} for a description
+     * of the possible types.</p>
+     *
+     * @param qName The XML qualified name.
+     * @return The attribute type as a string, or null if the
+     *         attribute is not in the list or if qualified names
+     *         are not available.
+     */
+    public abstract String getType (String qName);
+
+
+    /**
+     * Look up an attribute's value by Namespace name.
+     *
+     * <p>See {@link #getValue(int) getValue(int)} for a description
+     * of the possible values.</p>
+     *
+     * @param uri The Namespace URI, or the empty String if the
+     *        name has no Namespace URI.
+     * @param localName The local name of the attribute.
+     * @return The attribute value as a string, or null if the
+     *         attribute is not in the list.
+     */
+    public abstract String getValue (String uri, String localName);
+
+
+    /**
+     * Look up an attribute's value by XML qualified (prefixed) name.
+     *
+     * <p>See {@link #getValue(int) getValue(int)} for a description
+     * of the possible values.</p>
+     *
+     * @param qName The XML qualified name.
+     * @return The attribute value as a string, or null if the
+     *         attribute is not in the list or if qualified names
+     *         are not available.
+     */
+    public abstract String getValue (String qName);
+
+}
+
+// end of Attributes.java
diff --git a/src/org/xml/sax/ContentHandler.java b/src/org/xml/sax/ContentHandler.java
new file mode 100644 (file)
index 0000000..3d95c5f
--- /dev/null
@@ -0,0 +1,419 @@
+// ContentHandler.java - handle main document content.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: ContentHandler.java,v 1.13 2004/04/26 17:50:49 dmegginson Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Receive notification of the logical content of a document.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is the main interface that most SAX applications
+ * implement: if the application needs to be informed of basic parsing 
+ * events, it implements this interface and registers an instance with 
+ * the SAX parser using the {@link org.xml.sax.XMLReader#setContentHandler 
+ * setContentHandler} method.  The parser uses the instance to report 
+ * basic document-related events like the start and end of elements 
+ * and character data.</p>
+ *
+ * <p>The order of events in this interface is very important, and
+ * mirrors the order of information in the document itself.  For
+ * example, all of an element's content (character data, processing
+ * instructions, and/or subelements) will appear, in order, between
+ * the startElement event and the corresponding endElement event.</p>
+ *
+ * <p>This interface is similar to the now-deprecated SAX 1.0
+ * DocumentHandler interface, but it adds support for Namespaces
+ * and for reporting skipped entities (in non-validating XML
+ * processors).</p>
+ *
+ * <p>Implementors should note that there is also a 
+ * <code>ContentHandler</code> class in the <code>java.net</code>
+ * package; that means that it's probably a bad idea to do</p>
+ *
+ * <pre>import java.net.*;
+ * import org.xml.sax.*;
+ * </pre>
+ *
+ * <p>In fact, "import ...*" is usually a sign of sloppy programming
+ * anyway, so the user should consider this a feature rather than a
+ * bug.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1+ (sax2r3pre1)
+ * @see org.xml.sax.XMLReader
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public interface ContentHandler
+{
+
+    /**
+     * Receive an object for locating the origin of SAX document events.
+     *
+     * <p>SAX parsers are strongly encouraged (though not absolutely
+     * required) to supply a locator: if it does so, it must supply
+     * the locator to the application by invoking this method before
+     * invoking any of the other methods in the ContentHandler
+     * interface.</p>
+     *
+     * <p>The locator allows the application to determine the end
+     * position of any document-related event, even if the parser is
+     * not reporting an error.  Typically, the application will
+     * use this information for reporting its own errors (such as
+     * character content that does not match an application's
+     * business rules).  The information returned by the locator
+     * is probably not sufficient for use with a search engine.</p>
+     *
+     * <p>Note that the locator will return correct information only
+     * during the invocation SAX event callbacks after
+     * {@link #startDocument startDocument} returns and before
+     * {@link #endDocument endDocument} is called.  The
+     * application should not attempt to use it at any other time.</p>
+     *
+     * @param locator an object that can return the location of
+     *                any SAX document event
+     * @see org.xml.sax.Locator
+     */
+    public void setDocumentLocator (Locator locator);
+
+
+    /**
+     * Receive notification of the beginning of a document.
+     *
+     * <p>The SAX parser will invoke this method only once, before any
+     * other event callbacks (except for {@link #setDocumentLocator 
+     * setDocumentLocator}).</p>
+     *
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #endDocument
+     */
+    public void startDocument ()
+       throws SAXException;
+
+
+    /**
+     * Receive notification of the end of a document.
+     *
+     * <p><strong>There is an apparent contradiction between the
+     * documentation for this method and the documentation for {@link
+     * org.xml.sax.ErrorHandler#fatalError}.  Until this ambiguity is
+     * resolved in a future major release, clients should make no
+     * assumptions about whether endDocument() will or will not be
+     * invoked when the parser has reported a fatalError() or thrown
+     * an exception.</strong></p>
+     *
+     * <p>The SAX parser will invoke this method only once, and it will
+     * be the last method invoked during the parse.  The parser shall
+     * not invoke this method until it has either abandoned parsing
+     * (because of an unrecoverable error) or reached the end of
+     * input.</p>
+     *
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #startDocument
+     */
+    public void endDocument()
+       throws SAXException;
+
+
+    /**
+     * Begin the scope of a prefix-URI Namespace mapping.
+     *
+     * <p>The information from this event is not necessary for
+     * normal Namespace processing: the SAX XML reader will 
+     * automatically replace prefixes for element and attribute
+     * names when the <code>http://xml.org/sax/features/namespaces</code>
+     * feature is <var>true</var> (the default).</p>
+     *
+     * <p>There are cases, however, when applications need to
+     * use prefixes in character data or in attribute values,
+     * where they cannot safely be expanded automatically; the
+     * start/endPrefixMapping event supplies the information
+     * to the application to expand prefixes in those contexts
+     * itself, if necessary.</p>
+     *
+     * <p>Note that start/endPrefixMapping events are not
+     * guaranteed to be properly nested relative to each other:
+     * all startPrefixMapping events will occur immediately before the
+     * corresponding {@link #startElement startElement} event, 
+     * and all {@link #endPrefixMapping endPrefixMapping}
+     * events will occur immediately after the corresponding
+     * {@link #endElement endElement} event,
+     * but their order is not otherwise 
+     * guaranteed.</p>
+     *
+     * <p>There should never be start/endPrefixMapping events for the
+     * "xml" prefix, since it is predeclared and immutable.</p>
+     *
+     * @param prefix the Namespace prefix being declared.
+     * An empty string is used for the default element namespace,
+     * which has no prefix.
+     * @param uri the Namespace URI the prefix is mapped to
+     * @throws org.xml.sax.SAXException the client may throw
+     *            an exception during processing
+     * @see #endPrefixMapping
+     * @see #startElement
+     */
+    public void startPrefixMapping (String prefix, String uri)
+       throws SAXException;
+
+
+    /**
+     * End the scope of a prefix-URI mapping.
+     *
+     * <p>See {@link #startPrefixMapping startPrefixMapping} for 
+     * details.  These events will always occur immediately after the
+     * corresponding {@link #endElement endElement} event, but the order of 
+     * {@link #endPrefixMapping endPrefixMapping} events is not otherwise
+     * guaranteed.</p>
+     *
+     * @param prefix the prefix that was being mapped.
+     * This is the empty string when a default mapping scope ends.
+     * @throws org.xml.sax.SAXException the client may throw
+     *            an exception during processing
+     * @see #startPrefixMapping
+     * @see #endElement
+     */
+    public void endPrefixMapping (String prefix)
+       throws SAXException;
+
+
+    /**
+     * Receive notification of the beginning of an element.
+     *
+     * <p>The Parser will invoke this method at the beginning of every
+     * element in the XML document; there will be a corresponding
+     * {@link #endElement endElement} event for every startElement event
+     * (even when the element is empty). All of the element's content will be
+     * reported, in order, before the corresponding endElement
+     * event.</p>
+     *
+     * <p>This event allows up to three name components for each
+     * element:</p>
+     *
+     * <ol>
+     * <li>the Namespace URI;</li>
+     * <li>the local name; and</li>
+     * <li>the qualified (prefixed) name.</li>
+     * </ol>
+     *
+     * <p>Any or all of these may be provided, depending on the
+     * values of the <var>http://xml.org/sax/features/namespaces</var>
+     * and the <var>http://xml.org/sax/features/namespace-prefixes</var>
+     * properties:</p>
+     *
+     * <ul>
+     * <li>the Namespace URI and local name are required when 
+     * the namespaces property is <var>true</var> (the default), and are
+     * optional when the namespaces property is <var>false</var> (if one is
+     * specified, both must be);</li>
+     * <li>the qualified name is required when the namespace-prefixes property
+     * is <var>true</var>, and is optional when the namespace-prefixes property
+     * is <var>false</var> (the default).</li>
+     * </ul>
+     *
+     * <p>Note that the attribute list provided will contain only
+     * attributes with explicit values (specified or defaulted):
+     * #IMPLIED attributes will be omitted.  The attribute list
+     * will contain attributes used for Namespace declarations
+     * (xmlns* attributes) only if the
+     * <code>http://xml.org/sax/features/namespace-prefixes</code>
+     * property is true (it is false by default, and support for a 
+     * true value is optional).</p>
+     *
+     * <p>Like {@link #characters characters()}, attribute values may have
+     * characters that need more than one <code>char</code> value.  </p>
+     *
+     * @param uri the Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed
+     * @param localName the local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed
+     * @param qName the qualified name (with prefix), or the
+     *        empty string if qualified names are not available
+     * @param atts the attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.  The value of this object after
+     *        startElement returns is undefined
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #endElement
+     * @see org.xml.sax.Attributes
+     * @see org.xml.sax.helpers.AttributesImpl
+     */
+    public void startElement (String uri, String localName,
+                             String qName, Attributes atts)
+       throws SAXException;
+
+
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>The SAX parser will invoke this method at the end of every
+     * element in the XML document; there will be a corresponding
+     * {@link #startElement startElement} event for every endElement 
+     * event (even when the element is empty).</p>
+     *
+     * <p>For information on the names, see startElement.</p>
+     *
+     * @param uri the Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed
+     * @param localName the local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed
+     * @param qName the qualified XML name (with prefix), or the
+     *        empty string if qualified names are not available
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     */
+    public void endElement (String uri, String localName,
+                           String qName)
+       throws SAXException;
+
+
+    /**
+     * Receive notification of character data.
+     *
+     * <p>The Parser will call this method to report each chunk of
+     * character data.  SAX parsers may return all contiguous character
+     * data in a single chunk, or they may split it into several
+     * chunks; however, all of the characters in any single event
+     * must come from the same external entity so that the Locator
+     * provides useful information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * <p>Individual characters may consist of more than one Java
+     * <code>char</code> value.  There are two important cases where this
+     * happens, because characters can't be represented in just sixteen bits.
+     * In one case, characters are represented in a <em>Surrogate Pair</em>,
+     * using two special Unicode values. Such characters are in the so-called
+     * "Astral Planes", with a code point above U+FFFF.  A second case involves
+     * composite characters, such as a base character combining with one or
+     * more accent characters. </p>
+     *
+     * <p> Your code should not assume that algorithms using
+     * <code>char</code>-at-a-time idioms will be working in character
+     * units; in some cases they will split characters.  This is relevant
+     * wherever XML permits arbitrary characters, such as attribute values,
+     * processing instruction data, and comments as well as in data reported
+     * from this method.  It's also generally relevant whenever Java code
+     * manipulates internationalized text; the issue isn't unique to XML.</p>
+     *
+     * <p>Note that some parsers will report whitespace in element
+     * content using the {@link #ignorableWhitespace ignorableWhitespace}
+     * method rather than this one (validating parsers <em>must</em> 
+     * do so).</p>
+     *
+     * @param ch the characters from the XML document
+     * @param start the start position in the array
+     * @param length the number of characters to read from the array
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #ignorableWhitespace 
+     * @see org.xml.sax.Locator
+     */
+    public void characters (char ch[], int start, int length)
+       throws SAXException;
+
+
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>Validating Parsers must use this method to report each chunk
+     * of whitespace in element content (see the W3C XML 1.0
+     * recommendation, section 2.10): non-validating parsers may also
+     * use this method if they are capable of parsing and using
+     * content models.</p>
+     *
+     * <p>SAX parsers may return all contiguous whitespace in a single
+     * chunk, or they may split it into several chunks; however, all of
+     * the characters in any single event must come from the same
+     * external entity, so that the Locator provides useful
+     * information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * @param ch the characters from the XML document
+     * @param start the start position in the array
+     * @param length the number of characters to read from the array
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #characters
+     */
+    public void ignorableWhitespace (char ch[], int start, int length)
+       throws SAXException;
+
+
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>The Parser will invoke this method once for each processing
+     * instruction found: note that processing instructions may occur
+     * before or after the main document element.</p>
+     *
+     * <p>A SAX parser must never report an XML declaration (XML 1.0,
+     * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
+     * using this method.</p>
+     *
+     * <p>Like {@link #characters characters()}, processing instruction
+     * data may have characters that need more than one <code>char</code>
+     * value. </p>
+     *
+     * @param target the processing instruction target
+     * @param data the processing instruction data, or null if
+     *        none was supplied.  The data does not include any
+     *        whitespace separating it from the target
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     */
+    public void processingInstruction (String target, String data)
+       throws SAXException;
+
+
+    /**
+     * Receive notification of a skipped entity.
+     * This is not called for entity references within markup constructs
+     * such as element start tags or markup declarations.  (The XML
+     * recommendation requires reporting skipped external entities.
+     * SAX also reports internal entity expansion/non-expansion, except
+     * within markup constructs.)
+     *
+     * <p>The Parser will invoke this method each time the entity is
+     * skipped.  Non-validating processors may skip entities if they
+     * have not seen the declarations (because, for example, the
+     * entity was declared in an external DTD subset).  All processors
+     * may skip external entities, depending on the values of the
+     * <code>http://xml.org/sax/features/external-general-entities</code>
+     * and the
+     * <code>http://xml.org/sax/features/external-parameter-entities</code>
+     * properties.</p>
+     *
+     * @param name the name of the skipped entity.  If it is a 
+     *        parameter entity, the name will begin with '%', and if
+     *        it is the external DTD subset, it will be the string
+     *        "[dtd]"
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     */
+    public void skippedEntity (String name)
+       throws SAXException;
+}
+
+// end of ContentHandler.java
diff --git a/src/org/xml/sax/DTDHandler.java b/src/org/xml/sax/DTDHandler.java
new file mode 100644 (file)
index 0000000..e62222a
--- /dev/null
@@ -0,0 +1,117 @@
+// SAX DTD handler.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: DTDHandler.java,v 1.8 2002/01/30 21:13:43 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Receive notification of basic DTD-related events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX application needs information about notations and
+ * unparsed entities, then the application implements this 
+ * interface and registers an instance with the SAX parser using 
+ * the parser's setDTDHandler method.  The parser uses the 
+ * instance to report notation and unparsed entity declarations to 
+ * the application.</p>
+ *
+ * <p>Note that this interface includes only those DTD events that
+ * the XML recommendation <em>requires</em> processors to report:
+ * notation and unparsed entity declarations.</p>
+ *
+ * <p>The SAX parser may report these events in any order, regardless
+ * of the order in which the notations and unparsed entities were
+ * declared; however, all DTD events must be reported after the
+ * document handler's startDocument event, and before the first
+ * startElement event.
+ * (If the {@link org.xml.sax.ext.LexicalHandler LexicalHandler} is
+ * used, these events must also be reported before the endDTD event.)
+ * </p>
+ *
+ * <p>It is up to the application to store the information for 
+ * future use (perhaps in a hash table or object tree).
+ * If the application encounters attributes of type "NOTATION",
+ * "ENTITY", or "ENTITIES", it can use the information that it
+ * obtained through this interface to find the entity and/or
+ * notation corresponding with the attribute value.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLReader#setDTDHandler
+ */
+public interface DTDHandler {
+    
+    
+    /**
+     * Receive notification of a notation declaration event.
+     *
+     * <p>It is up to the application to record the notation for later
+     * reference, if necessary;
+     * notations may appear as attribute values and in unparsed entity
+     * declarations, and are sometime used with processing instruction
+     * target names.</p>
+     *
+     * <p>At least one of publicId and systemId must be non-null.
+     * If a system identifier is present, and it is a URL, the SAX
+     * parser must resolve it fully before passing it to the
+     * application through this event.</p>
+     *
+     * <p>There is no guarantee that the notation declaration will be
+     * reported before any unparsed entities that use it.</p>
+     *
+     * @param name The notation name.
+     * @param publicId The notation's public identifier, or null if
+     *        none was given.
+     * @param systemId The notation's system identifier, or null if
+     *        none was given.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #unparsedEntityDecl
+     * @see org.xml.sax.Attributes
+     */
+    public abstract void notationDecl (String name,
+                                      String publicId,
+                                      String systemId)
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of an unparsed entity declaration event.
+     *
+     * <p>Note that the notation name corresponds to a notation
+     * reported by the {@link #notationDecl notationDecl} event.  
+     * It is up to the application to record the entity for later 
+     * reference, if necessary;
+     * unparsed entities may appear as attribute values. 
+     * </p>
+     *
+     * <p>If the system identifier is a URL, the parser must resolve it
+     * fully before passing it to the application.</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @param name The unparsed entity's name.
+     * @param publicId The entity's public identifier, or null if none
+     *        was given.
+     * @param systemId The entity's system identifier.
+     * @param notationName The name of the associated notation.
+     * @see #notationDecl
+     * @see org.xml.sax.Attributes
+     */
+    public abstract void unparsedEntityDecl (String name,
+                                            String publicId,
+                                            String systemId,
+                                            String notationName)
+       throws SAXException;
+    
+}
+
+// end of DTDHandler.java
diff --git a/src/org/xml/sax/DocumentHandler.java b/src/org/xml/sax/DocumentHandler.java
new file mode 100644 (file)
index 0000000..d70ae74
--- /dev/null
@@ -0,0 +1,232 @@
+// SAX document handler.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: DocumentHandler.java,v 1.6 2002/01/30 21:13:43 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Receive notification of general document events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This was the main event-handling interface for SAX1; in
+ * SAX2, it has been replaced by {@link org.xml.sax.ContentHandler
+ * ContentHandler}, which provides Namespace support and reporting
+ * of skipped entities.  This interface is included in SAX2 only
+ * to support legacy SAX1 applications.</p>
+ *
+ * <p>The order of events in this interface is very important, and
+ * mirrors the order of information in the document itself.  For
+ * example, all of an element's content (character data, processing
+ * instructions, and/or subelements) will appear, in order, between
+ * the startElement event and the corresponding endElement event.</p>
+ *
+ * <p>Application writers who do not want to implement the entire
+ * interface can derive a class from HandlerBase, which implements
+ * the default functionality; parser writers can instantiate
+ * HandlerBase to obtain a default handler.  The application can find
+ * the location of any document event using the Locator interface
+ * supplied by the Parser through the setDocumentLocator method.</p>
+ *
+ * @deprecated This interface has been replaced by the SAX2
+ *             {@link org.xml.sax.ContentHandler ContentHandler}
+ *             interface, which includes Namespace support.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.Parser#setDocumentHandler
+ * @see org.xml.sax.Locator
+ * @see org.xml.sax.HandlerBase
+ */
+public interface DocumentHandler {
+    
+    
+    /**
+     * Receive an object for locating the origin of SAX document events.
+     *
+     * <p>SAX parsers are strongly encouraged (though not absolutely
+     * required) to supply a locator: if it does so, it must supply
+     * the locator to the application by invoking this method before
+     * invoking any of the other methods in the DocumentHandler
+     * interface.</p>
+     *
+     * <p>The locator allows the application to determine the end
+     * position of any document-related event, even if the parser is
+     * not reporting an error.  Typically, the application will
+     * use this information for reporting its own errors (such as
+     * character content that does not match an application's
+     * business rules).  The information returned by the locator
+     * is probably not sufficient for use with a search engine.</p>
+     *
+     * <p>Note that the locator will return correct information only
+     * during the invocation of the events in this interface.  The
+     * application should not attempt to use it at any other time.</p>
+     *
+     * @param locator An object that can return the location of
+     *                any SAX document event.
+     * @see org.xml.sax.Locator
+     */
+    public abstract void setDocumentLocator (Locator locator);
+    
+    
+    /**
+     * Receive notification of the beginning of a document.
+     *
+     * <p>The SAX parser will invoke this method only once, before any
+     * other methods in this interface or in DTDHandler (except for
+     * setDocumentLocator).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void startDocument ()
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of the end of a document.
+     *
+     * <p>The SAX parser will invoke this method only once, and it will
+     * be the last method invoked during the parse.  The parser shall
+     * not invoke this method until it has either abandoned parsing
+     * (because of an unrecoverable error) or reached the end of
+     * input.</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void endDocument ()
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of the beginning of an element.
+     *
+     * <p>The Parser will invoke this method at the beginning of every
+     * element in the XML document; there will be a corresponding
+     * endElement() event for every startElement() event (even when the
+     * element is empty). All of the element's content will be
+     * reported, in order, before the corresponding endElement()
+     * event.</p>
+     *
+     * <p>If the element name has a namespace prefix, the prefix will
+     * still be attached.  Note that the attribute list provided will
+     * contain only attributes with explicit values (specified or
+     * defaulted): #IMPLIED attributes will be omitted.</p>
+     *
+     * @param name The element type name.
+     * @param atts The attributes attached to the element, if any.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement
+     * @see org.xml.sax.AttributeList 
+     */
+    public abstract void startElement (String name, AttributeList atts)
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>The SAX parser will invoke this method at the end of every
+     * element in the XML document; there will be a corresponding
+     * startElement() event for every endElement() event (even when the
+     * element is empty).</p>
+     *
+     * <p>If the element name has a namespace prefix, the prefix will
+     * still be attached to the name.</p>
+     *
+     * @param name The element type name
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void endElement (String name)
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of character data.
+     *
+     * <p>The Parser will call this method to report each chunk of
+     * character data.  SAX parsers may return all contiguous character
+     * data in a single chunk, or they may split it into several
+     * chunks; however, all of the characters in any single event
+     * must come from the same external entity, so that the Locator
+     * provides useful information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * <p>Note that some parsers will report whitespace using the
+     * ignorableWhitespace() method rather than this one (validating
+     * parsers must do so).</p>
+     *
+     * @param ch The characters from the XML document.
+     * @param start The start position in the array.
+     * @param length The number of characters to read from the array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #ignorableWhitespace 
+     * @see org.xml.sax.Locator
+     */
+    public abstract void characters (char ch[], int start, int length)
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>Validating Parsers must use this method to report each chunk
+     * of ignorable whitespace (see the W3C XML 1.0 recommendation,
+     * section 2.10): non-validating parsers may also use this method
+     * if they are capable of parsing and using content models.</p>
+     *
+     * <p>SAX parsers may return all contiguous whitespace in a single
+     * chunk, or they may split it into several chunks; however, all of
+     * the characters in any single event must come from the same
+     * external entity, so that the Locator provides useful
+     * information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * @param ch The characters from the XML document.
+     * @param start The start position in the array.
+     * @param length The number of characters to read from the array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #characters
+     */
+    public abstract void ignorableWhitespace (char ch[], int start, int length)
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>The Parser will invoke this method once for each processing
+     * instruction found: note that processing instructions may occur
+     * before or after the main document element.</p>
+     *
+     * <p>A SAX parser should never report an XML declaration (XML 1.0,
+     * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
+     * using this method.</p>
+     *
+     * @param target The processing instruction target.
+     * @param data The processing instruction data, or null if
+     *        none was supplied.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void processingInstruction (String target, String data)
+       throws SAXException;
+    
+}
+
+// end of DocumentHandler.java
diff --git a/src/org/xml/sax/EntityResolver.java b/src/org/xml/sax/EntityResolver.java
new file mode 100644 (file)
index 0000000..65b04eb
--- /dev/null
@@ -0,0 +1,119 @@
+// SAX entity resolver.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: EntityResolver.java,v 1.10 2002/01/30 21:13:44 dbrownell Exp $
+
+package org.xml.sax;
+
+import java.io.IOException;
+
+
+/**
+ * Basic interface for resolving entities.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX application needs to implement customized handling
+ * for external entities, it must implement this interface and
+ * register an instance with the SAX driver using the
+ * {@link org.xml.sax.XMLReader#setEntityResolver setEntityResolver}
+ * method.</p>
+ *
+ * <p>The XML reader will then allow the application to intercept any
+ * external entities (including the external DTD subset and external
+ * parameter entities, if any) before including them.</p>
+ *
+ * <p>Many SAX applications will not need to implement this interface,
+ * but it will be especially useful for applications that build
+ * XML documents from databases or other specialised input sources,
+ * or for applications that use URI types other than URLs.</p>
+ *
+ * <p>The following resolver would provide the application
+ * with a special character stream for the entity with the system
+ * identifier "http://www.myhost.com/today":</p>
+ *
+ * <pre>
+ * import org.xml.sax.EntityResolver;
+ * import org.xml.sax.InputSource;
+ *
+ * public class MyResolver implements EntityResolver {
+ *   public InputSource resolveEntity (String publicId, String systemId)
+ *   {
+ *     if (systemId.equals("http://www.myhost.com/today")) {
+ *              // return a special input source
+ *       MyReader reader = new MyReader();
+ *       return new InputSource(reader);
+ *     } else {
+ *              // use the default behaviour
+ *       return null;
+ *     }
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>The application can also use this interface to redirect system
+ * identifiers to local URIs or to look up replacements in a catalog
+ * (possibly by using the public identifier).</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLReader#setEntityResolver
+ * @see org.xml.sax.InputSource
+ */
+public interface EntityResolver {
+    
+    
+    /**
+     * Allow the application to resolve external entities.
+     *
+     * <p>The parser will call this method before opening any external
+     * entity except the top-level document entity.  Such entities include
+     * the external DTD subset and external parameter entities referenced
+     * within the DTD (in either case, only if the parser reads external
+     * parameter entities), and external general entities referenced
+     * within the document element (if the parser reads external general
+     * entities).  The application may request that the parser locate
+     * the entity itself, that it use an alternative URI, or that it
+     * use data provided by the application (as a character or byte
+     * input stream).</p>
+     *
+     * <p>Application writers can use this method to redirect external
+     * system identifiers to secure and/or local URIs, to look up
+     * public identifiers in a catalogue, or to read an entity from a
+     * database or other input source (including, for example, a dialog
+     * box).  Neither XML nor SAX specifies a preferred policy for using
+     * public or system IDs to resolve resources.  However, SAX specifies
+     * how to interpret any InputSource returned by this method, and that
+     * if none is returned, then the system ID will be dereferenced as
+     * a URL.  </p>
+     *
+     * <p>If the system identifier is a URL, the SAX parser must
+     * resolve it fully before reporting it to the application.</p>
+     *
+     * @param publicId The public identifier of the external entity
+     *        being referenced, or null if none was supplied.
+     * @param systemId The system identifier of the external entity
+     *        being referenced.
+     * @return An InputSource object describing the new input source,
+     *         or null to request that the parser open a regular
+     *         URI connection to the system identifier.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException A Java-specific IO exception,
+     *            possibly the result of creating a new InputStream
+     *            or Reader for the InputSource.
+     * @see org.xml.sax.InputSource
+     */
+    public abstract InputSource resolveEntity (String publicId,
+                                              String systemId)
+       throws SAXException, IOException;
+    
+}
+
+// end of EntityResolver.java
diff --git a/src/org/xml/sax/ErrorHandler.java b/src/org/xml/sax/ErrorHandler.java
new file mode 100644 (file)
index 0000000..37d2501
--- /dev/null
@@ -0,0 +1,139 @@
+// SAX error handler.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: ErrorHandler.java,v 1.10 2004/03/08 13:01:00 dmegginson Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Basic interface for SAX error handlers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX application needs to implement customized error
+ * handling, it must implement this interface and then register an
+ * instance with the XML reader using the
+ * {@link org.xml.sax.XMLReader#setErrorHandler setErrorHandler}
+ * method.  The parser will then report all errors and warnings
+ * through this interface.</p>
+ *
+ * <p><strong>WARNING:</strong> If an application does <em>not</em>
+ * register an ErrorHandler, XML parsing errors will go unreported,
+ * except that <em>SAXParseException</em>s will be thrown for fatal errors.
+ * In order to detect validity errors, an ErrorHandler that does something
+ * with {@link #error error()} calls must be registered.</p>
+ *
+ * <p>For XML processing errors, a SAX driver must use this interface 
+ * in preference to throwing an exception: it is up to the application 
+ * to decide whether to throw an exception for different types of 
+ * errors and warnings.  Note, however, that there is no requirement that 
+ * the parser continue to report additional errors after a call to 
+ * {@link #fatalError fatalError}.  In other words, a SAX driver class 
+ * may throw an exception after reporting any fatalError.
+ * Also parsers may throw appropriate exceptions for non-XML errors.
+ * For example, {@link XMLReader#parse XMLReader.parse()} would throw
+ * an IOException for errors accessing entities or the document.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1+ (sax2r3pre1)
+ * @see org.xml.sax.XMLReader#setErrorHandler
+ * @see org.xml.sax.SAXParseException 
+ */
+public interface ErrorHandler {
+    
+    
+    /**
+     * Receive notification of a warning.
+     *
+     * <p>SAX parsers will use this method to report conditions that
+     * are not errors or fatal errors as defined by the XML
+     * recommendation.  The default behaviour is to take no
+     * action.</p>
+     *
+     * <p>The SAX parser must continue to provide normal parsing events
+     * after invoking this method: it should still be possible for the
+     * application to process the document through to the end.</p>
+     *
+     * <p>Filters may use this method to report other, non-XML warnings
+     * as well.</p>
+     *
+     * @param exception The warning information encapsulated in a
+     *                  SAX parse exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.SAXParseException 
+     */
+    public abstract void warning (SAXParseException exception)
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of a recoverable error.
+     *
+     * <p>This corresponds to the definition of "error" in section 1.2
+     * of the W3C XML 1.0 Recommendation.  For example, a validating
+     * parser would use this callback to report the violation of a
+     * validity constraint.  The default behaviour is to take no
+     * action.</p>
+     *
+     * <p>The SAX parser must continue to provide normal parsing
+     * events after invoking this method: it should still be possible
+     * for the application to process the document through to the end.
+     * If the application cannot do so, then the parser should report
+     * a fatal error even if the XML recommendation does not require
+     * it to do so.</p>
+     *
+     * <p>Filters may use this method to report other, non-XML errors
+     * as well.</p>
+     *
+     * @param exception The error information encapsulated in a
+     *                  SAX parse exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.SAXParseException 
+     */
+    public abstract void error (SAXParseException exception)
+       throws SAXException;
+    
+    
+    /**
+     * Receive notification of a non-recoverable error.
+     *
+     * <p><strong>There is an apparent contradiction between the
+     * documentation for this method and the documentation for {@link
+     * org.xml.sax.ContentHandler#endDocument}.  Until this ambiguity
+     * is resolved in a future major release, clients should make no
+     * assumptions about whether endDocument() will or will not be
+     * invoked when the parser has reported a fatalError() or thrown
+     * an exception.</strong></p>
+     *
+     * <p>This corresponds to the definition of "fatal error" in
+     * section 1.2 of the W3C XML 1.0 Recommendation.  For example, a
+     * parser would use this callback to report the violation of a
+     * well-formedness constraint.</p>
+     *
+     * <p>The application must assume that the document is unusable
+     * after the parser has invoked this method, and should continue
+     * (if at all) only for the sake of collecting additional error
+     * messages: in fact, SAX parsers are free to stop reporting any
+     * other events once this method has been invoked.</p>
+     *
+     * @param exception The error information encapsulated in a
+     *                  SAX parse exception.  
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.SAXParseException
+     */
+    public abstract void fatalError (SAXParseException exception)
+       throws SAXException;
+    
+}
+
+// end of ErrorHandler.java
diff --git a/src/org/xml/sax/HandlerBase.java b/src/org/xml/sax/HandlerBase.java
new file mode 100644 (file)
index 0000000..7c5c411
--- /dev/null
@@ -0,0 +1,383 @@
+// SAX default handler base class.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: HandlerBase.java,v 1.7 2004/04/26 17:34:34 dmegginson Exp $
+
+package org.xml.sax;
+
+/**
+ * Default base class for handlers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class implements the default behaviour for four SAX1
+ * interfaces: EntityResolver, DTDHandler, DocumentHandler,
+ * and ErrorHandler.  It is now obsolete, but is included in SAX2 to
+ * support legacy SAX1 applications.  SAX2 applications should use
+ * the {@link org.xml.sax.helpers.DefaultHandler DefaultHandler}
+ * class instead.</p>
+ *
+ * <p>Application writers can extend this class when they need to
+ * implement only part of an interface; parser writers can
+ * instantiate this class to provide default handlers when the
+ * application has not supplied its own.</p>
+ *
+ * <p>Note that the use of this class is optional.</p>
+ *
+ * @deprecated This class works with the deprecated
+ *             {@link org.xml.sax.DocumentHandler DocumentHandler}
+ *             interface.  It has been replaced by the SAX2
+ *             {@link org.xml.sax.helpers.DefaultHandler DefaultHandler}
+ *             class.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.DocumentHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public class HandlerBase
+    implements EntityResolver, DTDHandler, DocumentHandler, ErrorHandler
+{
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the EntityResolver interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Resolve an external entity.
+     *
+     * <p>Always return null, so that the parser will use the system
+     * identifier provided in the XML document.  This method implements
+     * the SAX default behaviour: application writers can override it
+     * in a subclass to do special translations such as catalog lookups
+     * or URI redirection.</p>
+     *
+     * @param publicId The public identifer, or null if none is
+     *                 available.
+     * @param systemId The system identifier provided in the XML 
+     *                 document.
+     * @return The new input source, or null to require the
+     *         default behaviour.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.EntityResolver#resolveEntity
+     */
+    @Override
+               public InputSource resolveEntity (String publicId, String systemId)
+       throws SAXException
+    {
+       return null;
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of DTDHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a notation declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to keep track of the notations
+     * declared in a document.</p>
+     *
+     * @param name The notation name.
+     * @param publicId The notation public identifier, or null if not
+     *                 available.
+     * @param systemId The notation system identifier.
+     * @see org.xml.sax.DTDHandler#notationDecl
+     */
+    @Override
+               public void notationDecl (String name, String publicId, String systemId)
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of an unparsed entity declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to keep track of the unparsed entities
+     * declared in a document.</p>
+     *
+     * @param name The entity name.
+     * @param publicId The entity public identifier, or null if not
+     *                 available.
+     * @param systemId The entity system identifier.
+     * @param notationName The name of the associated notation.
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    @Override
+               public void unparsedEntityDecl (String name, String publicId,
+                                   String systemId, String notationName)
+    {
+       // no op
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of DocumentHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive a Locator object for document events.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to store the locator for use
+     * with other document events.</p>
+     *
+     * @param locator A locator for all SAX document events.
+     * @see org.xml.sax.DocumentHandler#setDocumentLocator
+     * @see org.xml.sax.Locator
+     */
+    @Override
+               public void setDocumentLocator (Locator locator)
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the beginning of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the beginning
+     * of a document (such as allocating the root node of a tree or
+     * creating an output file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#startDocument
+     */
+    @Override
+               public void startDocument ()
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the beginning
+     * of a document (such as finalising a tree or closing an output
+     * file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#endDocument
+     */
+    @Override
+               public void endDocument ()
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the start of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the start of
+     * each element (such as allocating a new tree node or writing
+     * output to a file).</p>
+     *
+     * @param name The element type name.
+     * @param attributes The specified or defaulted attributes.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    @Override
+               public void startElement (String name, AttributeList attributes)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end of
+     * each element (such as finalising a tree node or writing
+     * output to a file).</p>
+     *
+     * @param name the element name
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#endElement
+     */
+    @Override
+               public void endElement (String name)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of character data inside an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of character data
+     * (such as adding the data to a node or buffer, or printing it to
+     * a file).</p>
+     *
+     * @param ch The characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#characters
+     */
+    @Override
+               public void characters (char ch[], int start, int length)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of ignorable
+     * whitespace (such as adding data to a node or buffer, or printing
+     * it to a file).</p>
+     *
+     * @param ch The whitespace characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#ignorableWhitespace
+     */
+    @Override
+               public void ignorableWhitespace (char ch[], int start, int length)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions for each
+     * processing instruction, such as setting status variables or
+     * invoking other methods.</p>
+     *
+     * @param target The processing instruction target.
+     * @param data The processing instruction data, or null if
+     *             none is supplied.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#processingInstruction
+     */
+    @Override
+               public void processingInstruction (String target, String data)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the ErrorHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a parser warning.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each warning, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    @Override
+               public void warning (SAXParseException e)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of a recoverable parser error.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each error, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    @Override
+               public void error (SAXParseException e)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Report a fatal XML parsing error.
+     *
+     * <p>The default implementation throws a SAXParseException.
+     * Application writers may override this method in a subclass if
+     * they need to take specific actions for each fatal error (such as
+     * collecting all of the errors into a single report): in any case,
+     * the application must stop all regular processing when this
+     * method is invoked, since the document is no longer reliable, and
+     * the parser may no longer report parsing events.</p>
+     *
+     * @param e The error information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#fatalError
+     * @see org.xml.sax.SAXParseException
+     */
+    @Override
+               public void fatalError (SAXParseException e)
+       throws SAXException
+    {
+       throw e;
+    }
+    
+}
+
+// end of HandlerBase.java
diff --git a/src/org/xml/sax/InputSource.java b/src/org/xml/sax/InputSource.java
new file mode 100644 (file)
index 0000000..663700c
--- /dev/null
@@ -0,0 +1,336 @@
+// SAX input source.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: InputSource.java,v 1.9 2002/01/30 21:13:45 dbrownell Exp $
+
+package org.xml.sax;
+
+import java.io.Reader;
+import java.io.InputStream;
+
+/**
+ * A single input source for an XML entity.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class allows a SAX application to encapsulate information
+ * about an input source in a single object, which may include
+ * a public identifier, a system identifier, a byte stream (possibly
+ * with a specified encoding), and/or a character stream.</p>
+ *
+ * <p>There are two places that the application can deliver an
+ * input source to the parser: as the argument to the Parser.parse
+ * method, or as the return value of the EntityResolver.resolveEntity
+ * method.</p>
+ *
+ * <p>The SAX parser will use the InputSource object to determine how
+ * to read XML input.  If there is a character stream available, the
+ * parser will read that stream directly, disregarding any text
+ * encoding declaration found in that stream.
+ * If there is no character stream, but there is
+ * a byte stream, the parser will use that byte stream, using the
+ * encoding specified in the InputSource or else (if no encoding is
+ * specified) autodetecting the character encoding using an algorithm
+ * such as the one in the XML specification.  If neither a character
+ * stream nor a
+ * byte stream is available, the parser will attempt to open a URI
+ * connection to the resource identified by the system
+ * identifier.</p>
+ *
+ * <p>An InputSource object belongs to the application: the SAX parser
+ * shall never modify it in any way (it may modify a copy if 
+ * necessary).  However, standard processing of both byte and
+ * character streams is to close them on as part of end-of-parse cleanup,
+ * so applications should not attempt to re-use such streams after they
+ * have been handed to a parser.  </p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource)
+ * @see org.xml.sax.EntityResolver#resolveEntity
+ * @see java.io.InputStream
+ * @see java.io.Reader
+ */
+public class InputSource {
+    
+    /**
+     * Zero-argument default constructor.
+     *
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #setCharacterStream
+     * @see #setEncoding
+     */
+    public InputSource ()
+    {
+    }
+    
+    
+    /**
+     * Create a new input source with a system identifier.
+     *
+     * <p>Applications may use setPublicId to include a 
+     * public identifier as well, or setEncoding to specify
+     * the character encoding, if known.</p>
+     *
+     * <p>If the system identifier is a URL, it must be fully
+     * resolved (it may not be a relative URL).</p>
+     *
+     * @param systemId The system identifier (URI).
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #setEncoding
+     * @see #setCharacterStream
+     */
+    public InputSource (String systemId)
+    {
+       setSystemId(systemId);
+    }
+    
+    
+    /**
+     * Create a new input source with a byte stream.
+     *
+     * <p>Application writers should use setSystemId() to provide a base 
+     * for resolving relative URIs, may use setPublicId to include a 
+     * public identifier, and may use setEncoding to specify the object's
+     * character encoding.</p>
+     *
+     * @param byteStream The raw byte stream containing the document.
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setEncoding
+     * @see #setByteStream
+     * @see #setCharacterStream
+     */
+    public InputSource (InputStream byteStream)
+    {
+       setByteStream(byteStream);
+    }
+    
+    
+    /**
+     * Create a new input source with a character stream.
+     *
+     * <p>Application writers should use setSystemId() to provide a base 
+     * for resolving relative URIs, and may use setPublicId to include a 
+     * public identifier.</p>
+     *
+     * <p>The character stream shall not include a byte order mark.</p>
+     *
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #setCharacterStream
+     */
+    public InputSource (Reader characterStream)
+    {
+       setCharacterStream(characterStream);
+    }
+    
+    
+    /**
+     * Set the public identifier for this input source.
+     * 
+     * <p>The public identifier is always optional: if the application
+     * writer includes one, it will be provided as part of the
+     * location information.</p>
+     *
+     * @param publicId The public identifier as a string.
+     * @see #getPublicId
+     * @see org.xml.sax.Locator#getPublicId
+     * @see org.xml.sax.SAXParseException#getPublicId
+     */
+    public void setPublicId (String publicId)
+    {
+       this.publicId = publicId;
+    }
+    
+    
+    /**
+     * Get the public identifier for this input source.
+     *
+     * @return The public identifier, or null if none was supplied.
+     * @see #setPublicId
+     */
+    public String getPublicId ()
+    {
+       return publicId;
+    }
+    
+    
+    /**
+     * Set the system identifier for this input source.
+     *
+     * <p>The system identifier is optional if there is a byte stream
+     * or a character stream, but it is still useful to provide one,
+     * since the application can use it to resolve relative URIs
+     * and can include it in error messages and warnings (the parser
+     * will attempt to open a connection to the URI only if
+     * there is no byte stream or character stream specified).</p>
+     *
+     * <p>If the application knows the character encoding of the
+     * object pointed to by the system identifier, it can register
+     * the encoding using the setEncoding method.</p>
+     *
+     * <p>If the system identifier is a URL, it must be fully
+     * resolved (it may not be a relative URL).</p>
+     *
+     * @param systemId The system identifier as a string.
+     * @see #setEncoding
+     * @see #getSystemId
+     * @see org.xml.sax.Locator#getSystemId
+     * @see org.xml.sax.SAXParseException#getSystemId
+     */
+    public void setSystemId (String systemId)
+    {
+       this.systemId = systemId;
+    }
+    
+    
+    /**
+     * Get the system identifier for this input source.
+     *
+     * <p>The getEncoding method will return the character encoding
+     * of the object pointed to, or null if unknown.</p>
+     *
+     * <p>If the system ID is a URL, it will be fully resolved.</p>
+     *
+     * @return The system identifier, or null if none was supplied.
+     * @see #setSystemId
+     * @see #getEncoding
+     */
+    public String getSystemId ()
+    {
+       return systemId;
+    }
+    
+    
+    /**
+     * Set the byte stream for this input source.
+     *
+     * <p>The SAX parser will ignore this if there is also a character
+     * stream specified, but it will use a byte stream in preference
+     * to opening a URI connection itself.</p>
+     *
+     * <p>If the application knows the character encoding of the
+     * byte stream, it should set it with the setEncoding method.</p>
+     *
+     * @param byteStream A byte stream containing an XML document or
+     *        other entity.
+     * @see #setEncoding
+     * @see #getByteStream
+     * @see #getEncoding
+     * @see java.io.InputStream
+     */
+    public void setByteStream (InputStream byteStream)
+    {
+       this.byteStream = byteStream;
+    }
+    
+    
+    /**
+     * Get the byte stream for this input source.
+     *
+     * <p>The getEncoding method will return the character
+     * encoding for this byte stream, or null if unknown.</p>
+     *
+     * @return The byte stream, or null if none was supplied.
+     * @see #getEncoding
+     * @see #setByteStream
+     */
+    public InputStream getByteStream ()
+    {
+       return byteStream;
+    }
+    
+    
+    /** 
+     * Set the character encoding, if known.
+     *
+     * <p>The encoding must be a string acceptable for an
+     * XML encoding declaration (see section 4.3.3 of the XML 1.0
+     * recommendation).</p>
+     *
+     * <p>This method has no effect when the application provides a
+     * character stream.</p>
+     *
+     * @param encoding A string describing the character encoding.
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #getEncoding
+     */
+    public void setEncoding (String encoding)
+    {
+       this.encoding = encoding;
+    }
+    
+    
+    /**
+     * Get the character encoding for a byte stream or URI.
+     * This value will be ignored when the application provides a
+     * character stream.
+     *
+     * @return The encoding, or null if none was supplied.
+     * @see #setByteStream
+     * @see #getSystemId
+     * @see #getByteStream
+     */
+    public String getEncoding ()
+    {
+       return encoding;
+    }
+    
+    
+    /**
+     * Set the character stream for this input source.
+     *
+     * <p>If there is a character stream specified, the SAX parser
+     * will ignore any byte stream and will not attempt to open
+     * a URI connection to the system identifier.</p>
+     *
+     * @param characterStream The character stream containing the
+     *        XML document or other entity.
+     * @see #getCharacterStream
+     * @see java.io.Reader
+     */
+    public void setCharacterStream (Reader characterStream)
+    {
+       this.characterStream = characterStream;
+    }
+    
+    
+    /**
+     * Get the character stream for this input source.
+     *
+     * @return The character stream, or null if none was supplied.
+     * @see #setCharacterStream
+     */
+    public Reader getCharacterStream ()
+    {
+       return characterStream;
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+    
+    private String publicId;
+    private String systemId;
+    private InputStream byteStream;
+    private String encoding;
+    private Reader characterStream;
+    
+}
+
+// end of InputSource.java
diff --git a/src/org/xml/sax/Locator.java b/src/org/xml/sax/Locator.java
new file mode 100644 (file)
index 0000000..f8f3484
--- /dev/null
@@ -0,0 +1,136 @@
+// SAX locator interface for document events.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: Locator.java,v 1.8 2002/01/30 21:13:47 dbrownell Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Interface for associating a SAX event with a document location.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX parser provides location information to the SAX
+ * application, it does so by implementing this interface and then
+ * passing an instance to the application using the content
+ * handler's {@link org.xml.sax.ContentHandler#setDocumentLocator
+ * setDocumentLocator} method.  The application can use the
+ * object to obtain the location of any other SAX event
+ * in the XML source document.</p>
+ *
+ * <p>Note that the results returned by the object will be valid only
+ * during the scope of each callback method: the application
+ * will receive unpredictable results if it attempts to use the
+ * locator at any other time, or after parsing completes.</p>
+ *
+ * <p>SAX parsers are not required to supply a locator, but they are
+ * very strongly encouraged to do so.  If the parser supplies a
+ * locator, it must do so before reporting any other document events.
+ * If no locator has been set by the time the application receives
+ * the {@link org.xml.sax.ContentHandler#startDocument startDocument}
+ * event, the application should assume that a locator is not 
+ * available.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.ContentHandler#setDocumentLocator 
+ */
+public interface Locator {
+    
+    
+    /**
+     * Return the public identifier for the current document event.
+     *
+     * <p>The return value is the public identifier of the document
+     * entity or of the external parsed entity in which the markup
+     * triggering the event appears.</p>
+     *
+     * @return A string containing the public identifier, or
+     *         null if none is available.
+     * @see #getSystemId
+     */
+    public abstract String getPublicId ();
+    
+    
+    /**
+     * Return the system identifier for the current document event.
+     *
+     * <p>The return value is the system identifier of the document
+     * entity or of the external parsed entity in which the markup
+     * triggering the event appears.</p>
+     *
+     * <p>If the system identifier is a URL, the parser must resolve it
+     * fully before passing it to the application.  For example, a file
+     * name must always be provided as a <em>file:...</em> URL, and other
+     * kinds of relative URI are also resolved against their bases.</p>
+     *
+     * @return A string containing the system identifier, or null
+     *         if none is available.
+     * @see #getPublicId
+     */
+    public abstract String getSystemId ();
+    
+    
+    /**
+     * Return the line number where the current document event ends.
+     * Lines are delimited by line ends, which are defined in
+     * the XML specification.
+     *
+     * <p><strong>Warning:</strong> The return value from the method
+     * is intended only as an approximation for the sake of diagnostics;
+     * it is not intended to provide sufficient information
+     * to edit the character content of the original XML document.
+     * In some cases, these "line" numbers match what would be displayed
+     * as columns, and in others they may not match the source text
+     * due to internal entity expansion.  </p>
+     *
+     * <p>The return value is an approximation of the line number
+     * in the document entity or external parsed entity where the
+     * markup triggering the event appears.</p>
+     *
+     * <p>If possible, the SAX driver should provide the line position 
+     * of the first character after the text associated with the document 
+     * event.  The first line is line 1.</p>
+     *
+     * @return The line number, or -1 if none is available.
+     * @see #getColumnNumber
+     */
+    public abstract int getLineNumber ();
+    
+    
+    /**
+     * Return the column number where the current document event ends.
+     * This is one-based number of Java <code>char</code> values since
+     * the last line end.
+     *
+     * <p><strong>Warning:</strong> The return value from the method
+     * is intended only as an approximation for the sake of diagnostics;
+     * it is not intended to provide sufficient information
+     * to edit the character content of the original XML document.
+     * For example, when lines contain combining character sequences, wide
+     * characters, surrogate pairs, or bi-directional text, the value may
+     * not correspond to the column in a text editor's display. </p>
+     *
+     * <p>The return value is an approximation of the column number
+     * in the document entity or external parsed entity where the
+     * markup triggering the event appears.</p>
+     *
+     * <p>If possible, the SAX driver should provide the line position 
+     * of the first character after the text associated with the document 
+     * event.  The first column in each line is column 1.</p>
+     *
+     * @return The column number, or -1 if none is available.
+     * @see #getLineNumber
+     */
+    public abstract int getColumnNumber ();
+    
+}
+
+// end of Locator.java
diff --git a/src/org/xml/sax/Parser.java b/src/org/xml/sax/Parser.java
new file mode 100644 (file)
index 0000000..734819d
--- /dev/null
@@ -0,0 +1,209 @@
+// SAX parser interface.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: Parser.java,v 1.6 2002/01/30 21:13:47 dbrownell Exp $
+
+package org.xml.sax;
+
+import java.io.IOException;
+import java.util.Locale;
+
+
+/**
+ * Basic interface for SAX (Simple API for XML) parsers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This was the main event supplier interface for SAX1; it has
+ * been replaced in SAX2 by {@link org.xml.sax.XMLReader XMLReader},
+ * which includes Namespace support and sophisticated configurability
+ * and extensibility.</p>
+ *
+ * <p>All SAX1 parsers must implement this basic interface: it allows
+ * applications to register handlers for different types of events
+ * and to initiate a parse from a URI, or a character stream.</p>
+ *
+ * <p>All SAX1 parsers must also implement a zero-argument constructor
+ * (though other constructors are also allowed).</p>
+ *
+ * <p>SAX1 parsers are reusable but not re-entrant: the application
+ * may reuse a parser object (possibly with a different input source)
+ * once the first parse has completed successfully, but it may not
+ * invoke the parse() methods recursively within a parse.</p>
+ *
+ * @deprecated This interface has been replaced by the SAX2
+ *             {@link org.xml.sax.XMLReader XMLReader}
+ *             interface, which includes Namespace support.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.DocumentHandler
+ * @see org.xml.sax.ErrorHandler
+ * @see org.xml.sax.HandlerBase
+ * @see org.xml.sax.InputSource
+ */
+public interface Parser 
+{
+    
+    /**
+     * Allow an application to request a locale for errors and warnings.
+     *
+     * <p>SAX parsers are not required to provide localisation for errors
+     * and warnings; if they cannot support the requested locale,
+     * however, they must throw a SAX exception.  Applications may
+     * not request a locale change in the middle of a parse.</p>
+     *
+     * @param locale A Java Locale object.
+     * @exception org.xml.sax.SAXException Throws an exception
+     *            (using the previous or default locale) if the 
+     *            requested locale is not supported.
+     * @see org.xml.sax.SAXException
+     * @see org.xml.sax.SAXParseException
+     */
+    public abstract void setLocale (Locale locale)
+       throws SAXException;
+    
+    
+    /**
+     * Allow an application to register a custom entity resolver.
+     *
+     * <p>If the application does not register an entity resolver, the
+     * SAX parser will resolve system identifiers and open connections
+     * to entities itself (this is the default behaviour implemented in
+     * HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different entity resolver
+     * in the middle of a parse, and the SAX parser must begin using
+     * the new resolver immediately.</p>
+     *
+     * @param resolver The object for resolving entities.
+     * @see EntityResolver
+     * @see HandlerBase
+     */
+    public abstract void setEntityResolver (EntityResolver resolver);
+    
+    
+    /**
+     * Allow an application to register a DTD event handler.
+     *
+     * <p>If the application does not register a DTD handler, all DTD
+     * events reported by the SAX parser will be silently
+     * ignored (this is the default behaviour implemented by
+     * HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different
+     * handler in the middle of a parse, and the SAX parser must
+     * begin using the new handler immediately.</p>
+     *
+     * @param handler The DTD handler.
+     * @see DTDHandler
+     * @see HandlerBase
+     */
+    public abstract void setDTDHandler (DTDHandler handler);
+    
+    
+    /**
+     * Allow an application to register a document event handler.
+     *
+     * <p>If the application does not register a document handler, all
+     * document events reported by the SAX parser will be silently
+     * ignored (this is the default behaviour implemented by
+     * HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The document handler.
+     * @see DocumentHandler
+     * @see HandlerBase
+     */
+    public abstract void setDocumentHandler (DocumentHandler handler);
+    
+    
+    /**
+     * Allow an application to register an error event handler.
+     *
+     * <p>If the application does not register an error event handler,
+     * all error events reported by the SAX parser will be silently
+     * ignored, except for fatalError, which will throw a SAXException
+     * (this is the default behaviour implemented by HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The error handler.
+     * @see ErrorHandler
+     * @see SAXException
+     * @see HandlerBase
+     */
+    public abstract void setErrorHandler (ErrorHandler handler);
+    
+    
+    /**
+     * Parse an XML document.
+     *
+     * <p>The application can use this method to instruct the SAX parser
+     * to begin parsing an XML document from any valid input
+     * source (a character stream, a byte stream, or a URI).</p>
+     *
+     * <p>Applications may not invoke this method while a parse is in
+     * progress (they should create a new Parser instead for each
+     * additional XML document).  Once a parse is complete, an
+     * application may reuse the same Parser object, possibly with a
+     * different input source.</p>
+     *
+     * @param source The input source for the top-level of the
+     *        XML document.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see org.xml.sax.InputSource
+     * @see #parse(java.lang.String)
+     * @see #setEntityResolver
+     * @see #setDTDHandler
+     * @see #setDocumentHandler
+     * @see #setErrorHandler
+     */
+    public abstract void parse (InputSource source)
+       throws SAXException, IOException;
+    
+    
+    /**
+     * Parse an XML document from a system identifier (URI).
+     *
+     * <p>This method is a shortcut for the common case of reading a
+     * document from a system identifier.  It is the exact
+     * equivalent of the following:</p>
+     *
+     * <pre>
+     * parse(new InputSource(systemId));
+     * </pre>
+     *
+     * <p>If the system identifier is a URL, it must be fully resolved
+     * by the application before it is passed to the parser.</p>
+     *
+     * @param systemId The system identifier (URI).
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see #parse(org.xml.sax.InputSource)
+     */
+    public abstract void parse (String systemId)
+       throws SAXException, IOException;
+    
+}
+
+// end of Parser.java
diff --git a/src/org/xml/sax/SAXException.java b/src/org/xml/sax/SAXException.java
new file mode 100644 (file)
index 0000000..70a60ce
--- /dev/null
@@ -0,0 +1,155 @@
+// SAX exception class.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: SAXException.java,v 1.7 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Encapsulate a general SAX error or warning.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class can contain basic error or warning information from
+ * either the XML parser or the application: a parser writer or
+ * application writer can subclass it to provide additional
+ * functionality.  SAX handlers may throw this exception or
+ * any exception subclassed from it.</p>
+ *
+ * <p>If the application needs to pass through other types of
+ * exceptions, it must wrap those exceptions in a SAXException
+ * or an exception derived from a SAXException.</p>
+ *
+ * <p>If the parser or application needs to include information about a
+ * specific location in an XML document, it should use the
+ * {@link org.xml.sax.SAXParseException SAXParseException} subclass.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXParseException
+ */
+public class SAXException extends Exception {
+
+
+    /**
+     * Create a new SAXException.
+     */
+    public SAXException ()
+    {
+       super();
+       this.exception = null;
+    }
+    
+    
+    /**
+     * Create a new SAXException.
+     *
+     * @param message The error or warning message.
+     */
+    public SAXException (String message) {
+       super(message);
+       this.exception = null;
+    }
+    
+    
+    /**
+     * Create a new SAXException wrapping an existing exception.
+     *
+     * <p>The existing exception will be embedded in the new
+     * one, and its message will become the default message for
+     * the SAXException.</p>
+     *
+     * @param e The exception to be wrapped in a SAXException.
+     */
+    public SAXException (Exception e)
+    {
+       super();
+       this.exception = e;
+    }
+    
+    
+    /**
+     * Create a new SAXException from an existing exception.
+     *
+     * <p>The existing exception will be embedded in the new
+     * one, but the new exception will have its own message.</p>
+     *
+     * @param message The detail message.
+     * @param e The exception to be wrapped in a SAXException.
+     */
+    public SAXException (String message, Exception e)
+    {
+       super(message);
+       this.exception = e;
+    }
+    
+    
+    /**
+     * Return a detail message for this exception.
+     *
+     * <p>If there is an embedded exception, and if the SAXException
+     * has no detail message of its own, this method will return
+     * the detail message from the embedded exception.</p>
+     *
+     * @return The error or warning message.
+     */
+    @Override
+               public String getMessage ()
+    {
+       String message = super.getMessage();
+       
+       if (message == null && exception != null) {
+           return exception.getMessage();
+       } else {
+           return message;
+       }
+    }
+    
+    
+    /**
+     * Return the embedded exception, if any.
+     *
+     * @return The embedded exception, or null if there is none.
+     */
+    public Exception getException ()
+    {
+       return exception;
+    }
+
+
+    /**
+     * Override toString to pick up any embedded exception.
+     *
+     * @return A string representation of this exception.
+     */
+    @Override
+               public String toString ()
+    {
+       if (exception != null) {
+           return exception.toString();
+       } else {
+           return super.toString();
+       }
+    }
+    
+    
+    \f
+    //////////////////////////////////////////////////////////////////////
+    // Internal state.
+    //////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * @serial The embedded exception if tunnelling, or null.
+     */    
+    private Exception exception;
+    
+}
+
+// end of SAXException.java
diff --git a/src/org/xml/sax/SAXNotRecognizedException.java b/src/org/xml/sax/SAXNotRecognizedException.java
new file mode 100644 (file)
index 0000000..0bb1ded
--- /dev/null
@@ -0,0 +1,53 @@
+// SAXNotRecognizedException.java - unrecognized feature or value.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: SAXNotRecognizedException.java,v 1.7 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Exception class for an unrecognized identifier.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>An XMLReader will throw this exception when it finds an
+ * unrecognized feature or property identifier; SAX applications and
+ * extensions may use this class for other, similar purposes.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXNotSupportedException
+ */
+public class SAXNotRecognizedException extends SAXException
+{
+
+    /**
+     * Default constructor.
+     */
+    public SAXNotRecognizedException ()
+    {
+       super();
+    }
+
+
+    /**
+     * Construct a new exception with the given message.
+     *
+     * @param message The text message of the exception.
+     */
+    public SAXNotRecognizedException (String message)
+    {
+       super(message);
+    }
+
+}
+
+// end of SAXNotRecognizedException.java
diff --git a/src/org/xml/sax/SAXNotSupportedException.java b/src/org/xml/sax/SAXNotSupportedException.java
new file mode 100644 (file)
index 0000000..9a645a9
--- /dev/null
@@ -0,0 +1,53 @@
+// SAXNotSupportedException.java - unsupported feature or value.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: SAXNotSupportedException.java,v 1.7 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Exception class for an unsupported operation.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>An XMLReader will throw this exception when it recognizes a
+ * feature or property identifier, but cannot perform the requested
+ * operation (setting a state or value).  Other SAX2 applications and
+ * extensions may use this class for similar purposes.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXNotRecognizedException 
+ */
+public class SAXNotSupportedException extends SAXException
+{
+
+    /**
+     * Construct a new exception with no message.
+     */
+    public SAXNotSupportedException ()
+    {
+       super();
+    }
+
+
+    /**
+     * Construct a new exception with the given message.
+     *
+     * @param message The text message of the exception.
+     */
+    public SAXNotSupportedException (String message)
+    {
+       super(message);
+    }
+
+}
+
+// end of SAXNotSupportedException.java
diff --git a/src/org/xml/sax/SAXParseException.java b/src/org/xml/sax/SAXParseException.java
new file mode 100644 (file)
index 0000000..1df5e14
--- /dev/null
@@ -0,0 +1,269 @@
+// SAX exception class.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: SAXParseException.java,v 1.11 2004/04/21 13:05:02 dmegginson Exp $
+
+package org.xml.sax;
+
+/**
+ * Encapsulate an XML parse error or warning.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This exception may include information for locating the error
+ * in the original XML document, as if it came from a {@link Locator}
+ * object.  Note that although the application
+ * will receive a SAXParseException as the argument to the handlers
+ * in the {@link org.xml.sax.ErrorHandler ErrorHandler} interface, 
+ * the application is not actually required to throw the exception; 
+ * instead, it can simply read the information in it and take a 
+ * different action.</p>
+ *
+ * <p>Since this exception is a subclass of {@link org.xml.sax.SAXException 
+ * SAXException}, it inherits the ability to wrap another exception.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXException
+ * @see org.xml.sax.Locator
+ * @see org.xml.sax.ErrorHandler
+ */
+public class SAXParseException extends SAXException {
+    
+    \f
+    //////////////////////////////////////////////////////////////////////
+    // Constructors.
+    //////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Create a new SAXParseException from a message and a Locator.
+     *
+     * <p>This constructor is especially useful when an application is
+     * creating its own exception from within a {@link org.xml.sax.ContentHandler
+     * ContentHandler} callback.</p>
+     *
+     * @param message The error or warning message.
+     * @param locator The locator object for the error or warning (may be
+     *        null).
+     * @see org.xml.sax.Locator
+     */
+    public SAXParseException (String message, Locator locator) {
+       super(message);
+       if (locator != null) {
+           init(locator.getPublicId(), locator.getSystemId(),
+                locator.getLineNumber(), locator.getColumnNumber());
+       } else {
+           init(null, null, -1, -1);
+       }
+    }
+    
+    
+    /**
+     * Wrap an existing exception in a SAXParseException.
+     *
+     * <p>This constructor is especially useful when an application is
+     * creating its own exception from within a {@link org.xml.sax.ContentHandler
+     * ContentHandler} callback, and needs to wrap an existing exception that is not a
+     * subclass of {@link org.xml.sax.SAXException SAXException}.</p>
+     *
+     * @param message The error or warning message, or null to
+     *                use the message from the embedded exception.
+     * @param locator The locator object for the error or warning (may be
+     *        null).
+     * @param e Any exception.
+     * @see org.xml.sax.Locator
+     */
+    public SAXParseException (String message, Locator locator,
+                             Exception e) {
+       super(message, e);
+       if (locator != null) {
+           init(locator.getPublicId(), locator.getSystemId(),
+                locator.getLineNumber(), locator.getColumnNumber());
+       } else {
+           init(null, null, -1, -1);
+       }
+    }
+    
+    
+    /**
+     * Create a new SAXParseException.
+     *
+     * <p>This constructor is most useful for parser writers.</p>
+     *
+     * <p>All parameters except the message are as if
+     * they were provided by a {@link Locator}.  For example, if the
+     * system identifier is a URL (including relative filename), the
+     * caller must resolve it fully before creating the exception.</p>
+     *
+     *
+     * @param message The error or warning message.
+     * @param publicId The public identifier of the entity that generated
+     *                 the error or warning.
+     * @param systemId The system identifier of the entity that generated
+     *                 the error or warning.
+     * @param lineNumber The line number of the end of the text that
+     *                   caused the error or warning.
+     * @param columnNumber The column number of the end of the text that
+     *                     cause the error or warning.
+     */
+    public SAXParseException (String message, String publicId, String systemId,
+                             int lineNumber, int columnNumber)
+    {
+       super(message);
+       init(publicId, systemId, lineNumber, columnNumber);
+    }
+    
+    
+    /**
+     * Create a new SAXParseException with an embedded exception.
+     *
+     * <p>This constructor is most useful for parser writers who
+     * need to wrap an exception that is not a subclass of
+     * {@link org.xml.sax.SAXException SAXException}.</p>
+     *
+     * <p>All parameters except the message and exception are as if
+     * they were provided by a {@link Locator}.  For example, if the
+     * system identifier is a URL (including relative filename), the
+     * caller must resolve it fully before creating the exception.</p>
+     *
+     * @param message The error or warning message, or null to use
+     *                the message from the embedded exception.
+     * @param publicId The public identifier of the entity that generated
+     *                 the error or warning.
+     * @param systemId The system identifier of the entity that generated
+     *                 the error or warning.
+     * @param lineNumber The line number of the end of the text that
+     *                   caused the error or warning.
+     * @param columnNumber The column number of the end of the text that
+     *                     cause the error or warning.
+     * @param e Another exception to embed in this one.
+     */
+    public SAXParseException (String message, String publicId, String systemId,
+                             int lineNumber, int columnNumber, Exception e)
+    {
+       super(message, e);
+       init(publicId, systemId, lineNumber, columnNumber);
+    }
+
+
+    /**
+     * Internal initialization method.
+     *
+     * @param publicId The public identifier of the entity which generated the exception,
+     *        or null.
+     * @param systemId The system identifier of the entity which generated the exception,
+     *        or null.
+     * @param lineNumber The line number of the error, or -1.
+     * @param columnNumber The column number of the error, or -1.
+     */
+    private void init (String publicId, String systemId,
+                      int lineNumber, int columnNumber)
+    {
+       this.publicId = publicId;
+       this.systemId = systemId;
+       this.lineNumber = lineNumber;
+       this.columnNumber = columnNumber;
+    }
+    
+    
+    /**
+     * Get the public identifier of the entity where the exception occurred.
+     *
+     * @return A string containing the public identifier, or null
+     *         if none is available.
+     * @see org.xml.sax.Locator#getPublicId
+     */
+    public String getPublicId ()
+    {
+       return this.publicId;
+    }
+    
+    
+    /**
+     * Get the system identifier of the entity where the exception occurred.
+     *
+     * <p>If the system identifier is a URL, it will have been resolved
+     * fully.</p>
+     *
+     * @return A string containing the system identifier, or null
+     *         if none is available.
+     * @see org.xml.sax.Locator#getSystemId
+     */
+    public String getSystemId ()
+    {
+       return this.systemId;
+    }
+    
+    
+    /**
+     * The line number of the end of the text where the exception occurred.
+     *
+     * <p>The first line is line 1.</p>
+     *
+     * @return An integer representing the line number, or -1
+     *         if none is available.
+     * @see org.xml.sax.Locator#getLineNumber
+     */
+    public int getLineNumber ()
+    {
+       return this.lineNumber;
+    }
+    
+    
+    /**
+     * The column number of the end of the text where the exception occurred.
+     *
+     * <p>The first column in a line is position 1.</p>
+     *
+     * @return An integer representing the column number, or -1
+     *         if none is available.
+     * @see org.xml.sax.Locator#getColumnNumber
+     */
+    public int getColumnNumber ()
+    {
+       return this.columnNumber;
+    }
+    
+    \f
+    //////////////////////////////////////////////////////////////////////
+    // Internal state.
+    //////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * @serial The public identifier, or null.
+     * @see #getPublicId
+     */    
+    private String publicId;
+
+
+    /**
+     * @serial The system identifier, or null.
+     * @see #getSystemId
+     */
+    private String systemId;
+
+
+    /**
+     * @serial The line number, or -1.
+     * @see #getLineNumber
+     */
+    private int lineNumber;
+
+
+    /**
+     * @serial The column number, or -1.
+     * @see #getColumnNumber
+     */
+    private int columnNumber;
+    
+}
+
+// end of SAXParseException.java
diff --git a/src/org/xml/sax/XMLFilter.java b/src/org/xml/sax/XMLFilter.java
new file mode 100644 (file)
index 0000000..5a399fa
--- /dev/null
@@ -0,0 +1,65 @@
+// XMLFilter.java - filter SAX2 events.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLFilter.java,v 1.6 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Interface for an XML filter.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>An XML filter is like an XML reader, except that it obtains its
+ * events from another XML reader rather than a primary source like
+ * an XML document or database.  Filters can modify a stream of
+ * events as they pass on to the final application.</p>
+ *
+ * <p>The XMLFilterImpl helper class provides a convenient base
+ * for creating SAX2 filters, by passing on all {@link org.xml.sax.EntityResolver
+ * EntityResolver}, {@link org.xml.sax.DTDHandler DTDHandler},
+ * {@link org.xml.sax.ContentHandler ContentHandler} and {@link org.xml.sax.ErrorHandler
+ * ErrorHandler} events automatically.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.helpers.XMLFilterImpl
+ */
+public interface XMLFilter extends XMLReader
+{
+
+    /**
+     * Set the parent reader.
+     *
+     * <p>This method allows the application to link the filter to
+     * a parent reader (which may be another filter).  The argument
+     * may not be null.</p>
+     *
+     * @param parent The parent reader.
+     */
+    public abstract void setParent (XMLReader parent);
+
+
+    /**
+     * Get the parent reader.
+     *
+     * <p>This method allows the application to query the parent
+     * reader (which may be another filter).  It is generally a
+     * bad idea to perform any operations on the parent reader
+     * directly: they should all pass through this filter.</p>
+     *
+     * @return The parent filter, or null if none has been set.
+     */
+    public abstract XMLReader getParent ();
+
+}
+
+// end of XMLFilter.java
diff --git a/src/org/xml/sax/XMLReader.java b/src/org/xml/sax/XMLReader.java
new file mode 100644 (file)
index 0000000..9c150a0
--- /dev/null
@@ -0,0 +1,404 @@
+// XMLReader.java - read an XML document.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLReader.java,v 1.9 2004/04/26 17:34:34 dmegginson Exp $
+
+package org.xml.sax;
+
+import java.io.IOException;
+
+
+/**
+ * Interface for reading an XML document using callbacks.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p><strong>Note:</strong> despite its name, this interface does 
+ * <em>not</em> extend the standard Java {@link java.io.Reader Reader} 
+ * interface, because reading XML is a fundamentally different activity 
+ * than reading character data.</p>
+ *
+ * <p>XMLReader is the interface that an XML parser's SAX2 driver must
+ * implement.  This interface allows an application to set and
+ * query features and properties in the parser, to register
+ * event handlers for document processing, and to initiate
+ * a document parse.</p>
+ *
+ * <p>All SAX interfaces are assumed to be synchronous: the
+ * {@link #parse parse} methods must not return until parsing
+ * is complete, and readers must wait for an event-handler callback
+ * to return before reporting the next event.</p>
+ *
+ * <p>This interface replaces the (now deprecated) SAX 1.0 {@link
+ * org.xml.sax.Parser Parser} interface.  The XMLReader interface
+ * contains two important enhancements over the old Parser
+ * interface (as well as some minor ones):</p>
+ *
+ * <ol>
+ * <li>it adds a standard way to query and set features and 
+ *  properties; and</li>
+ * <li>it adds Namespace support, which is required for many
+ *  higher-level XML standards.</li>
+ * </ol>
+ *
+ * <p>There are adapters available to convert a SAX1 Parser to
+ * a SAX2 XMLReader and vice-versa.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1+ (sax2r3pre1)
+ * @see org.xml.sax.XMLFilter
+ * @see org.xml.sax.helpers.ParserAdapter
+ * @see org.xml.sax.helpers.XMLReaderAdapter 
+ */
+public interface XMLReader
+{
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Configuration.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Look up the value of a feature flag.
+     *
+     * <p>The feature name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a feature name but
+     * temporarily be unable to return its value.
+     * Some feature values may be available only in specific
+     * contexts, such as before, during, or after a parse.
+     * Also, some feature values may not be programmatically accessible.
+     * (In the case of an adapter for SAX1 {@link Parser}, there is no
+     * implementation-independent way to expose whether the underlying
+     * parser is performing validation, expanding external entities,
+     * and so forth.) </p>
+     *
+     * <p>All XMLReaders are required to recognize the
+     * http://xml.org/sax/features/namespaces and the
+     * http://xml.org/sax/features/namespace-prefixes feature names.</p>
+     *
+     * <p>Typical usage is something like this:</p>
+     *
+     * <pre>
+     * XMLReader r = new MySAXDriver();
+     *
+     *                         // try to activate validation
+     * try {
+     *   r.setFeature("http://xml.org/sax/features/validation", true);
+     * } catch (SAXException e) {
+     *   System.err.println("Cannot activate validation."); 
+     * }
+     *
+     *                         // register event handlers
+     * r.setContentHandler(new MyContentHandler());
+     * r.setErrorHandler(new MyErrorHandler());
+     *
+     *                         // parse the first document
+     * try {
+     *   r.parse("http://www.foo.com/mydoc.xml");
+     * } catch (IOException e) {
+     *   System.err.println("I/O exception reading XML document");
+     * } catch (SAXException e) {
+     *   System.err.println("XML exception reading document.");
+     * }
+     * </pre>
+     *
+     * <p>Implementors are free (and encouraged) to invent their own features,
+     * using names built on their own URIs.</p>
+     *
+     * @param name The feature name, which is a fully-qualified URI.
+     * @return The current value of the feature (true or false).
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the feature name but 
+     *            cannot determine its value at this time.
+     * @see #setFeature
+     */
+    public boolean getFeature (String name)
+        throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Set the value of a feature flag.
+     *
+     * <p>The feature name is any fully-qualified URI.  It is
+     * possible for an XMLReader to expose a feature value but
+     * to be unable to change the current value.
+     * Some feature values may be immutable or mutable only 
+     * in specific contexts, such as before, during, or after 
+     * a parse.</p>
+     *
+     * <p>All XMLReaders are required to support setting
+     * http://xml.org/sax/features/namespaces to true and
+     * http://xml.org/sax/features/namespace-prefixes to false.</p>
+     *
+     * @param name The feature name, which is a fully-qualified URI.
+     * @param value The requested value of the feature (true or false).
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the feature name but 
+     *            cannot set the requested value.
+     * @see #getFeature
+     */
+    public void setFeature (String name, boolean value)
+       throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Look up the value of a property.
+     *
+     * <p>The property name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a property name but
+     * temporarily be unable to return its value.
+     * Some property values may be available only in specific
+     * contexts, such as before, during, or after a parse.</p>
+     *
+     * <p>XMLReaders are not required to recognize any specific
+     * property names, though an initial core set is documented for
+     * SAX2.</p>
+     *
+     * <p>Implementors are free (and encouraged) to invent their own properties,
+     * using names built on their own URIs.</p>
+     *
+     * @param name The property name, which is a fully-qualified URI.
+     * @return The current value of the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the property name but 
+     *            cannot determine its value at this time.
+     * @see #setProperty
+     */
+    public Object getProperty (String name)
+       throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Set the value of a property.
+     *
+     * <p>The property name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a property name but
+     * to be unable to change the current value.
+     * Some property values may be immutable or mutable only 
+     * in specific contexts, such as before, during, or after 
+     * a parse.</p>
+     *
+     * <p>XMLReaders are not required to recognize setting
+     * any specific property names, though a core set is defined by 
+     * SAX2.</p>
+     *
+     * <p>This method is also the standard mechanism for setting
+     * extended handlers.</p>
+     *
+     * @param name The property name, which is a fully-qualified URI.
+     * @param value The requested value for the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the property name but 
+     *            cannot set the requested value.
+     */
+    public void setProperty (String name, Object value)
+       throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Event handlers.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Allow an application to register an entity resolver.
+     *
+     * <p>If the application does not register an entity resolver,
+     * the XMLReader will perform its own default resolution.</p>
+     *
+     * <p>Applications may register a new or different resolver in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * resolver immediately.</p>
+     *
+     * @param resolver The entity resolver.
+     * @see #getEntityResolver
+     */
+    public void setEntityResolver (EntityResolver resolver);
+
+
+    /**
+     * Return the current entity resolver.
+     *
+     * @return The current entity resolver, or null if none
+     *         has been registered.
+     * @see #setEntityResolver
+     */
+    public EntityResolver getEntityResolver ();
+
+
+    /**
+     * Allow an application to register a DTD event handler.
+     *
+     * <p>If the application does not register a DTD handler, all DTD
+     * events reported by the SAX parser will be silently ignored.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The DTD handler.
+     * @see #getDTDHandler
+     */
+    public void setDTDHandler (DTDHandler handler);
+
+
+    /**
+     * Return the current DTD handler.
+     *
+     * @return The current DTD handler, or null if none
+     *         has been registered.
+     * @see #setDTDHandler
+     */
+    public DTDHandler getDTDHandler ();
+
+
+    /**
+     * Allow an application to register a content event handler.
+     *
+     * <p>If the application does not register a content handler, all
+     * content events reported by the SAX parser will be silently
+     * ignored.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The content handler.
+     * @see #getContentHandler
+     */
+    public void setContentHandler (ContentHandler handler);
+
+
+    /**
+     * Return the current content handler.
+     *
+     * @return The current content handler, or null if none
+     *         has been registered.
+     * @see #setContentHandler
+     */
+    public ContentHandler getContentHandler ();
+
+
+    /**
+     * Allow an application to register an error event handler.
+     *
+     * <p>If the application does not register an error handler, all
+     * error events reported by the SAX parser will be silently
+     * ignored; however, normal processing may not continue.  It is
+     * highly recommended that all SAX applications implement an
+     * error handler to avoid unexpected bugs.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The error handler.
+     * @see #getErrorHandler
+     */
+    public void setErrorHandler (ErrorHandler handler);
+
+
+    /**
+     * Return the current error handler.
+     *
+     * @return The current error handler, or null if none
+     *         has been registered.
+     * @see #setErrorHandler
+     */
+    public ErrorHandler getErrorHandler ();
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Parsing.
+    ////////////////////////////////////////////////////////////////////
+
+    /**
+     * Parse an XML document.
+     *
+     * <p>The application can use this method to instruct the XML
+     * reader to begin parsing an XML document from any valid input
+     * source (a character stream, a byte stream, or a URI).</p>
+     *
+     * <p>Applications may not invoke this method while a parse is in
+     * progress (they should create a new XMLReader instead for each
+     * nested XML document).  Once a parse is complete, an
+     * application may reuse the same XMLReader object, possibly with a
+     * different input source.
+     * Configuration of the XMLReader object (such as handler bindings and
+     * values established for feature flags and properties) is unchanged
+     * by completion of a parse, unless the definition of that aspect of
+     * the configuration explicitly specifies other behavior.
+     * (For example, feature flags or properties exposing
+     * characteristics of the document being parsed.)
+     * </p>
+     *
+     * <p>During the parse, the XMLReader will provide information
+     * about the XML document through the registered event
+     * handlers.</p>
+     *
+     * <p>This method is synchronous: it will not return until parsing
+     * has ended.  If a client application wants to terminate 
+     * parsing early, it should throw an exception.</p>
+     *
+     * @param input The input source for the top-level of the
+     *        XML document.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see org.xml.sax.InputSource
+     * @see #parse(java.lang.String)
+     * @see #setEntityResolver
+     * @see #setDTDHandler
+     * @see #setContentHandler
+     * @see #setErrorHandler 
+     */
+    public void parse (InputSource input)
+       throws IOException, SAXException;
+
+
+    /**
+     * Parse an XML document from a system identifier (URI).
+     *
+     * <p>This method is a shortcut for the common case of reading a
+     * document from a system identifier.  It is the exact
+     * equivalent of the following:</p>
+     *
+     * <pre>
+     * parse(new InputSource(systemId));
+     * </pre>
+     *
+     * <p>If the system identifier is a URL, it must be fully resolved
+     * by the application before it is passed to the parser.</p>
+     *
+     * @param systemId The system identifier (URI).
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see #parse(org.xml.sax.InputSource)
+     */
+    public void parse (String systemId)
+       throws IOException, SAXException;
+
+}
diff --git a/src/org/xml/sax/demo/ByteStreamDemo.java b/src/org/xml/sax/demo/ByteStreamDemo.java
new file mode 100644 (file)
index 0000000..5da34b9
--- /dev/null
@@ -0,0 +1,78 @@
+package org.xml.sax.demo;
+// SAX demonstration for parsing from a raw byte stream.
+// No warranty; no copyright -- use this as you will.
+// $Id: ByteStreamDemo.java,v 1.4 1998/05/01 20:38:19 david Exp $
+
+import org.xml.sax.Parser;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import org.xml.sax.helpers.ParserFactory;
+
+import java.io.FileInputStream;
+
+
+
+/**
+  * Demonstrate parsing from a byte stream.
+  *
+  * <p>Usage: java -Dorg.xml.sax.parser=<var>CLASSNAME</var> ByteStreamDemo
+  * <var>FILE</var></p>
+  *
+  * <p>The SAX parser will open a byte stream to the file name
+  * provided.  Note the use of the InputStreamAdapter class to allow a
+  * Java InputStream to serve as a SAX ByteStream.</p>
+  *
+  * @see DemoHandler
+  */
+public class ByteStreamDemo {
+
+
+  /**
+    * Main entry point.
+    */
+  public static void main (String args[])
+    throws Exception
+  {
+    Parser parser;
+    InputSource source;
+    DemoHandler handler;
+    FileInputStream input;
+
+                               // First, check the command-line usage.
+    if (args.length != 1) {
+      System.err.println("Usage: java -Dorg.xml.sax.parser=<classname> " +
+                        "SystemIdDemo <document>");
+      System.exit(2);
+    }
+
+                               // Allocate a SAX Parser object, using
+                               // the class name provided in the
+                               // org.xml.sax.parser property.
+    parser = ParserFactory.makeParser();
+
+                               // Allocate an event handler, and register
+                               // it with the SAX parser for all four
+                               // types of events (we could use a 
+                               // separate object for each).
+    handler = new DemoHandler();
+    parser.setEntityResolver(handler);
+    parser.setDTDHandler(handler);
+    parser.setDocumentHandler(handler);
+    parser.setErrorHandler(handler);
+
+                               // Create a Java FileInputStream from
+                               // the file: note that SAX cannot
+                               // use this directly.
+    input = new FileInputStream(args[0]);
+
+                               // Create the input source.
+    source = new InputSource(input);
+    source.setSystemId(args[0]);
+
+                               // Parse the document from the
+                               // ByteStream.
+    parser.parse(source);
+  }
+
+}
diff --git a/src/org/xml/sax/demo/CharacterStreamDemo.java b/src/org/xml/sax/demo/CharacterStreamDemo.java
new file mode 100644 (file)
index 0000000..8d97f0f
--- /dev/null
@@ -0,0 +1,88 @@
+package org.xml.sax.demo;
+// SAX demonstration for parsing from a UTF-16 character stream.
+// No warranty; no copyright -- use this as you will.
+// $Id: CharacterStreamDemo.java,v 1.3 1998/05/01 20:44:33 david Exp $
+
+import org.xml.sax.Parser;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import org.xml.sax.helpers.ParserFactory;
+
+import java.io.StringReader;
+
+
+/**
+  * Demonstrate parsing from a UTF-16 character stream.
+  *
+  * <p>Usage: java -Dorg.xml.sax.parser=<var>CLASSNAME</var>
+  * CharacterStreamDemo</p>
+  *
+  * <p>The SAX parser will read the document from a character
+  * stream connected to an internal string.</p>
+  *
+  * <p>Note that the Java implementation of SAX represents a
+  * character stream using a Reader.</p>
+  *
+  * @see DemoHandler
+  * @see org.xml.org.xml.sax.parser
+  * @see org.xml.sax.InputSource
+  * @see org.xml.sax.helpers.ParserFactory
+  * @see java.io.StringReader
+  */
+public class CharacterStreamDemo {
+
+                               // This is the document, in all its glory.
+                               // In a read-world application, this
+                               // could come from a database, a text
+                               // field, or just about anywhere.
+  final static String doc = "<?xml version=\"1.0\"?>" +
+                            "<doc>\n" +
+                            "<title>Hello</title>\n" +
+                            "<para>Hello, world!</para>\n" +
+                            "</doc>\n";
+
+  /**
+    * Main entry point for an application.
+    */
+  public static void main (String args[])
+    throws Exception
+  {
+    DemoHandler handler;
+    InputSource source;
+    Parser parser;
+    StringReader reader;
+
+                               // First, check the command-line
+                               // arguments.
+    if (args.length != 0) {
+      System.err.println("Usage: java CharTest");
+      System.exit(2);
+    }
+
+                               // Allocate a SAX Parser object, using
+                               // the class name provided in the
+                               // org.xml.sax.parser property (you could
+                               // also specify a classname here).
+    parser = ParserFactory.makeParser();
+
+                               // Allocate an event handler, and register
+                               // it with the SAX parser for all four
+                               // types of events (we could use a 
+                               // separate object for each).
+    handler = new DemoHandler();
+    parser.setEntityResolver(handler);
+    parser.setDTDHandler(handler);
+    parser.setDocumentHandler(handler);
+    parser.setErrorHandler(handler);
+
+                               // Create a Java-specific StringReader
+                               // for the internal document.
+    reader = new StringReader(doc);
+
+                               // Parse the document from the
+                               // character stream.
+    parser.parse(new InputSource(reader));
+  }
+
+}
diff --git a/src/org/xml/sax/demo/DemoHandler.java b/src/org/xml/sax/demo/DemoHandler.java
new file mode 100644 (file)
index 0000000..66c6a08
--- /dev/null
@@ -0,0 +1,325 @@
+package org.xml.sax.demo;
+
+// SAX event handler for demos.
+// No warranty; no copyright -- use this as you will.
+// $Id: DemoHandler.java,v 1.3 1998/05/01 20:45:16 david Exp $
+
+import org.xml.sax.HandlerBase;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.AttributeList;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXParseException;
+
+
+/**
+  * Event handler class for SAX demos.
+  *
+  * <p>This handler simply reports all of the events that it receives.
+  * It is useful for testing and comparing SAX implementations, and
+  * for teaching or learning about SAX.  This is also a demonstration
+  * of how one class can implement all four handler interfaces.</p>
+  *
+  * @see org.xml.sax.EntityResolver
+  * @see org.xml.sax.DTDHandler
+  * @see org.xml.sax.DocumentHandler
+  * @see org.xml.sax.ErrorHandler
+  */
+public class DemoHandler
+  implements EntityResolver, DTDHandler, DocumentHandler, ErrorHandler
+{
+
+
+\f
+  //////////////////////////////////////////////////////////////////////
+  // Implementation of org.xml.sax.EntityResolver
+  //////////////////////////////////////////////////////////////////////
+
+
+  /**
+    * Display requests for entity resolution.
+    *
+    * <p>The SAX parser will invoke this method to give the application
+    * a chance to resolve entities.  This implementation always
+    * returns null, so that the parser will resolve the entity
+    * itself.</p>
+    *
+    * @see org.xml.sax.EntityResolver#resolveEntity
+    */
+  @Override
+       public InputSource resolveEntity (String publicId, String systemId)
+  {
+    System.out.print("Resolve entity:");
+    if (publicId != null) {
+      System.out.print(" publicId=\"" + publicId + '"');
+    }
+    System.out.println(" systemId=\"" + systemId + '"');
+
+    return null;
+  }
+
+
+\f
+  //////////////////////////////////////////////////////////////////////
+  // Implementation of org.xml.sax.DTDHandler
+  //////////////////////////////////////////////////////////////////////
+
+
+  /**
+    * Display notation declarations as they are reported.
+    *
+    * @see org.xml.sax.DTDHandler#notationDecl
+    */
+  @Override
+       public void notationDecl (String name, String publicId, String systemId)
+  {
+    System.out.print("Notation declaration: " + name);
+    if (publicId != null) {
+      System.out.print(" publicId=\"" + publicId + '"');
+    }
+    if (systemId != null) {
+      System.out.print(" systemId=\"" + systemId + '"');
+    }
+    System.out.print('\n');
+  }
+
+
+  /**
+    * Display unparsed entity declarations as they are reported.
+    *
+    * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+    */
+  @Override
+       public void unparsedEntityDecl (String name,
+                                 String publicId,
+                                 String systemId,
+                                 String notationName)
+  {
+    System.out.print("Unparsed Entity Declaration: " + name);
+    if (publicId != null) {
+      System.out.print(" publicId=\"" + publicId + '"');
+    }
+    if (systemId != null) {
+      System.out.print(" systemId=\"" + systemId + '"');
+    }
+    System.out.println(" notationName=\"" + notationName + '"');
+  }
+
+
+\f
+  //////////////////////////////////////////////////////////////////////
+  // Implementation of org.xml.sax.DocumentHandler
+  //////////////////////////////////////////////////////////////////////
+
+
+  /**
+    * Print a message when the parser provides a locator.
+    *
+    * <p>Not all SAX parsers will provide a locator object.</p>
+    *
+    * @see org.xml.sax.DocumentHandler#setDocumentLocator
+    */
+  @Override
+       public void setDocumentLocator (Locator locator)
+  {
+    System.out.println("Document locator supplied.");
+  }
+
+
+  /**
+    * Print a message at the start of the document.
+    *
+    * @see org.xml.sax.DocumentHandler#startDocument
+    */
+  @Override
+       public void startDocument ()
+  {
+    System.out.println("Start document");
+  }
+
+
+  /**
+    * Print a message for the end of the document.
+    *
+    * @see org.xml.sax.DocumentHandler#endDocument
+    */
+  @Override
+       public void endDocument ()
+  {
+    System.out.println("End document");
+  }
+
+
+  /**
+    * Print a message for the start of an element.
+    *
+    * <p>Display all attributes on separate lines, indented.</p>
+    *
+    * @see org.xml.sax.DocumentHandler#startElement
+    */
+  @Override
+       public void startElement (String name, AttributeList attributes)
+  {
+    System.out.println("Start element: " + name);
+    for (int i = 0; i < attributes.getLength(); i++) {
+      System.out.println("  Attribute: " +
+                        attributes.getName(i) +
+                        ' ' +
+                        attributes.getType(i) +
+                        " \"" +
+                        attributes.getValue(i) +
+                        '"');
+    }
+  }
+
+
+  /**
+    * Print a message for the end of an element.
+    *
+    * @see org.xml.sax.DocumentHandler#endElement
+    */
+  @Override
+       public void endElement (String name)
+  {
+    System.out.println("End element: " + name);
+  }
+
+
+  /**
+    * Print a message for character data.
+    *
+    * @see org.xml.sax.DocumentHandler#characters
+    */
+  @Override
+       public void characters (char ch[], int start, int length)
+  {
+    System.out.print("Characters: ");
+    display(ch, start, length);
+  }
+
+
+  /**
+    * Print a message for ignorable whitespace.
+    *
+    * @see org.xml.sax.DocumentHandler#ignorableWhitespace
+    */
+  @Override
+       public void ignorableWhitespace (char ch[], int start, int length)
+  {
+    System.out.print("Ignorable Whitespace: ");
+    display(ch, start, length);
+  }
+
+
+  /**
+    * Print a message for a processing instruction.
+    *
+    * @see org.xml.sax.DocumentHandler#processingInstruction
+    */
+  @Override
+       public void processingInstruction (String target, String data)
+  {
+    System.out.println("Processing instruction: " + target + ' ' + data);
+  }
+
+
+\f
+  //////////////////////////////////////////////////////////////////////
+  // Implementation of org.xml.sax.ErrorHandler
+  //////////////////////////////////////////////////////////////////////
+
+
+  /**
+    * Report all warnings, and continue parsing.
+    *
+    * @see org.xml.sax.ErrorHandler#warning
+    */
+  @Override
+       public void warning (SAXParseException exception)
+  {
+    System.out.println("Warning: " +
+                      exception.getMessage() +
+                      " (" +
+                      exception.getSystemId() +
+                      ':' +
+                      exception.getLineNumber() +
+                      ',' +
+                      exception.getColumnNumber() +
+                      ')');
+  }
+
+
+  /**
+    * Report all recoverable errors, and try to continue parsing.
+    *
+    * @see org.xml.sax.ErrorHandler#error
+    */
+  @Override
+       public void error (SAXParseException exception)
+  {
+    System.out.println("Recoverable Error: " +
+                      exception.getMessage() +
+                      " (" +
+                      exception.getSystemId() +
+                      ':' +
+                      exception.getLineNumber() +
+                      ',' +
+                      exception.getColumnNumber() +
+                      ')');
+  }
+
+
+  /**
+    * Report all fatal errors, and try to continue parsing.
+    *
+    * <p>Note: results are no longer reliable once a fatal error has
+    * been reported.</p>
+    *
+    * @see org.xml.sax.ErrorHandler#fatalError
+    */
+  @Override
+       public void fatalError (SAXParseException exception)
+  {
+    System.out.println("Fatal Error: " +
+                      exception.getMessage() +
+                      " (" +
+                      exception.getSystemId() +
+                      ':' +
+                      exception.getLineNumber() +
+                      ',' +
+                      exception.getColumnNumber() +
+                      ')');
+  }
+
+
+\f
+  //////////////////////////////////////////////////////////////////////
+  // Utility routines.
+  //////////////////////////////////////////////////////////////////////
+
+
+  /**
+    * Display text, escaping some characters.
+    */
+  private static void display (char ch[], int start, int length)
+  {
+    for (int i = start; i < start + length; i++) {
+      switch (ch[i]) {
+      case '\n':
+       System.out.print("\\n");
+       break;
+      case '\t':
+       System.out.print("\\t");
+       break;
+      default:
+       System.out.print(ch[i]);
+       break;
+      }
+    }
+    System.out.print("\n");
+  }
+
+}
diff --git a/src/org/xml/sax/demo/EntityDemo.java b/src/org/xml/sax/demo/EntityDemo.java
new file mode 100644 (file)
index 0000000..be3948c
--- /dev/null
@@ -0,0 +1,128 @@
+package org.xml.sax.demo;
+// SAX demonstration for custom entity resolution.
+// No warranty; no copyright -- use this as you will.
+// $Id: EntityDemo.java,v 1.2 1998/05/01 20:52:16 david Exp $
+
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+
+import org.xml.sax.helpers.ParserFactory;
+
+import java.io.StringReader;
+import java.net.URL;
+
+
+/**
+  * Demonstrate custom entity resolution.
+  *
+  * <p>Usage: java -Dorg.xml.sax.parser=<var>classname</var> EntityDemo
+  * <var>systemId</var></p>
+  *
+  * <p>If you create an XML document which references an 
+  * external text entity with the public identifier
+  * "-//megginson//TEXT Sample Entity//EN", this application will
+  * substitute the string "Entity resolution works!" for the
+  * entity's contents:</p>
+  *
+  * <pre>
+  * &lt;!DOCTYPE doc [
+  *   &lt;!ENTITY ent 
+  *     PUBLIC "-//megginson//TEXT Sample Entity//EN" "ent.xml">
+  * ]>
+  * &lt;doc>
+  * &lt;para>&ent;&lt;/para>
+  * &lt;/doc>
+  * </pre>
+  *
+  * <p>The SAX parser will open a connection to the URI itself.</p>
+  *
+  * @see DemoHandler
+  */
+public class EntityDemo extends DemoHandler {
+
+                               // This is the Reader that will be
+                               // substituted for the entity contents.
+  StringReader reader =
+    new StringReader("Entity resolution works!");
+
+  /**
+    * Main entry point.
+    */
+  public static void main (String args[])
+    throws Exception
+  {
+    Parser parser;
+    EntityDemo handler;
+
+                               // Check the command-line usage.
+    if (args.length != 1) {
+      System.err.println("Usage: java -Dorg.xml.sax.parser=<classname> " +
+                        "EntityDemo <document>");
+      System.exit(2);
+    }
+
+                               // Make the parser, using the value
+                               // provided in the org.xml.sax.parser property.
+    parser = ParserFactory.makeParser();
+
+                               // Create an event handler, and register
+                               // it with the SAX parser.
+    handler = new EntityDemo();
+    parser.setEntityResolver(handler);
+    parser.setDTDHandler(handler);
+    parser.setDocumentHandler(handler);
+    parser.setErrorHandler(handler);
+
+                               // Parse the document.
+    parser.parse(makeAbsoluteURL(args[0]));
+  }
+
+
+  /**
+    * Override resolveEntity().
+    *
+    * <p>If the public identifier is "-//megginson//TEXT Sample
+    * //Entity//EN", instruct the parser to read the entity's
+    * contents from the StringReader rather than from the 
+    * system identifier.</p>
+    *
+    * <p>The public identifier is safer than the system identifier,
+    * since the parser may have resolved the system identifier to
+    * an absolute URL.</p>
+    *
+    * @see org.xml.sax.EntityResolver#resolveEntity
+    */
+  @Override
+       public InputSource resolveEntity (String publicId, String systemId)
+  {
+    if (publicId != null &&
+       publicId.equals("-//megginson//TEXT Sample Entity//EN")) {
+      return new InputSource(reader);
+    } else {
+      return null;
+    }
+  }
+
+
+  /**
+    * If a URL is relative, make it absolute against the current directory.
+    */
+  private static String makeAbsoluteURL (String url)
+    throws java.net.MalformedURLException
+  {
+    URL baseURL;
+
+    String currentDirectory = System.getProperty("user.dir");
+    String fileSep = System.getProperty("file.separator");
+    String file = currentDirectory.replace(fileSep.charAt(0), '/') + '/';
+
+    if (file.charAt(0) != '/') {
+      file = "/" + file;
+    }
+    baseURL = new URL("file", null, file);
+
+    return new URL(baseURL, url).toString();
+  }
+
+}
diff --git a/src/org/xml/sax/ext/Attributes2.java b/src/org/xml/sax/ext/Attributes2.java
new file mode 100644 (file)
index 0000000..cb1d679
--- /dev/null
@@ -0,0 +1,132 @@
+// Attributes2.java - extended Attributes
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Attributes2.java,v 1.6 2004/03/08 13:01:00 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Attributes;
+
+
+/**
+ * SAX2 extension to augment the per-attribute information
+ * provided though {@link Attributes}.
+ * If an implementation supports this extension, the attributes
+ * provided in {@link org.xml.sax.ContentHandler#startElement
+ * ContentHandler.startElement() } will implement this interface,
+ * and the <em>http://xml.org/sax/features/use-attributes2</em>
+ * feature flag will have the value <em>true</em>.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> XMLReader implementations are not required to support this
+ * information, and it is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>Note that if an attribute was defaulted (<em>!isSpecified()</em>)
+ * it will of necessity also have been declared (<em>isDeclared()</em>)
+ * in the DTD.
+ * Similarly if an attribute's type is anything except CDATA, then it
+ * must have been declared.
+ * </p>
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public interface Attributes2 extends Attributes
+{
+    /**
+     * Returns false unless the attribute was declared in the DTD.
+     * This helps distinguish two kinds of attributes that SAX reports
+     * as CDATA:  ones that were declared (and hence are usually valid),
+     * and those that were not (and which are never valid).
+     *
+     * @param index The attribute index (zero-based).
+     * @return true if the attribute was declared in the DTD,
+     *         false otherwise.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    public boolean isDeclared (int index);
+
+    /**
+     * Returns false unless the attribute was declared in the DTD.
+     * This helps distinguish two kinds of attributes that SAX reports
+     * as CDATA:  ones that were declared (and hence are usually valid),
+     * and those that were not (and which are never valid).
+     *
+     * @param qName The XML qualified (prefixed) name.
+     * @return true if the attribute was declared in the DTD,
+     *         false otherwise.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied name does not identify an attribute.
+     */
+    public boolean isDeclared (String qName);
+
+    /**
+     * Returns false unless the attribute was declared in the DTD.
+     * This helps distinguish two kinds of attributes that SAX reports
+     * as CDATA:  ones that were declared (and hence are usually valid),
+     * and those that were not (and which are never valid).
+     *
+     * <p>Remember that since DTDs do not "understand" namespaces, the
+     * namespace URI associated with an attribute may not have come from
+     * the DTD.  The declaration will have applied to the attribute's
+     * <em>qName</em>.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return true if the attribute was declared in the DTD,
+     *         false otherwise.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied names do not identify an attribute.
+     */
+    public boolean isDeclared (String uri, String localName);
+
+    /**
+     * Returns true unless the attribute value was provided
+     * by DTD defaulting.
+     *
+     * @param index The attribute index (zero-based).
+     * @return true if the value was found in the XML text,
+     *         false if the value was provided by DTD defaulting.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    public boolean isSpecified (int index);
+
+    /**
+     * Returns true unless the attribute value was provided
+     * by DTD defaulting.
+     *
+     * <p>Remember that since DTDs do not "understand" namespaces, the
+     * namespace URI associated with an attribute may not have come from
+     * the DTD.  The declaration will have applied to the attribute's
+     * <em>qName</em>.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return true if the value was found in the XML text,
+     *         false if the value was provided by DTD defaulting.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied names do not identify an attribute.
+     */
+    public boolean isSpecified (String uri, String localName);
+
+    /**
+     * Returns true unless the attribute value was provided
+     * by DTD defaulting.
+     *
+     * @param qName The XML qualified (prefixed) name.
+     * @return true if the value was found in the XML text,
+     *         false if the value was provided by DTD defaulting.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied name does not identify an attribute.
+     */
+    public boolean isSpecified (String qName);
+}
diff --git a/src/org/xml/sax/ext/Attributes2Impl.java b/src/org/xml/sax/ext/Attributes2Impl.java
new file mode 100644 (file)
index 0000000..ad24c78
--- /dev/null
@@ -0,0 +1,310 @@
+// Attributes2Impl.java - extended AttributesImpl
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Attributes2Impl.java,v 1.5 2004/03/08 13:01:01 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
+
+
+/**
+ * SAX2 extension helper for additional Attributes information,
+ * implementing the {@link Attributes2} interface.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p>This is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>The <em>specified</em> flag for each attribute will always
+ * be true, unless it has been set to false in the copy constructor
+ * or using {@link #setSpecified}.
+ * Similarly, the <em>declared</em> flag for each attribute will
+ * always be false, except for defaulted attributes (<em>specified</em>
+ * is false), non-CDATA attributes, or when it is set to true using
+ * {@link #setDeclared}.
+ * If you change an attribute's type by hand, you may need to modify
+ * its <em>declared</em> flag to match. 
+ * </p>
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public class Attributes2Impl extends AttributesImpl implements Attributes2
+{
+    private boolean    declared [];
+    private boolean    specified [];
+
+
+    /**
+     * Construct a new, empty Attributes2Impl object.
+     */
+    public Attributes2Impl () { }
+
+
+    /**
+     * Copy an existing Attributes or Attributes2 object.
+     * If the object implements Attributes2, values of the
+     * <em>specified</em> and <em>declared</em> flags for each
+     * attribute are copied.
+     * Otherwise the flag values are defaulted to assume no DTD was used,
+     * unless there is evidence to the contrary (such as attributes with
+     * type other than CDATA, which must have been <em>declared</em>).
+     *
+     * <p>This constructor is especially useful inside a
+     * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
+     *
+     * @param atts The existing Attributes object.
+     */
+    public Attributes2Impl (Attributes atts)
+    {
+       super (atts);
+    }
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of Attributes2
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Returns the current value of the attribute's "declared" flag.
+     */
+    // javadoc mostly from interface
+    @Override
+               public boolean isDeclared (int index)
+    {
+       if (index < 0 || index >= getLength ())
+           throw new ArrayIndexOutOfBoundsException (
+               "No attribute at index: " + index);
+       return declared [index];
+    }
+
+
+    /**
+     * Returns the current value of the attribute's "declared" flag.
+     */
+    // javadoc mostly from interface
+    @Override
+               public boolean isDeclared (String uri, String localName)
+    {
+       int index = getIndex (uri, localName);
+
+       if (index < 0)
+           throw new IllegalArgumentException (
+               "No such attribute: local=" + localName
+               + ", namespace=" + uri);
+       return declared [index];
+    }
+
+
+    /**
+     * Returns the current value of the attribute's "declared" flag.
+     */
+    // javadoc mostly from interface
+    @Override
+               public boolean isDeclared (String qName)
+    {
+       int index = getIndex (qName);
+
+       if (index < 0)
+           throw new IllegalArgumentException (
+               "No such attribute: " + qName);
+       return declared [index];
+    }
+
+
+    /**
+     * Returns the current value of an attribute's "specified" flag.
+     *
+     * @param index The attribute index (zero-based).
+     * @return current flag value
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    @Override
+               public boolean isSpecified (int index)
+    {
+       if (index < 0 || index >= getLength ())
+           throw new ArrayIndexOutOfBoundsException (
+               "No attribute at index: " + index);
+       return specified [index];
+    }
+
+
+    /**
+     * Returns the current value of an attribute's "specified" flag.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return current flag value
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied names do not identify an attribute.
+     */
+    @Override
+               public boolean isSpecified (String uri, String localName)
+    {
+       int index = getIndex (uri, localName);
+
+       if (index < 0)
+           throw new IllegalArgumentException (
+               "No such attribute: local=" + localName
+               + ", namespace=" + uri);
+       return specified [index];
+    }
+
+
+    /**
+     * Returns the current value of an attribute's "specified" flag.
+     *
+     * @param qName The XML qualified (prefixed) name.
+     * @return current flag value
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied name does not identify an attribute.
+     */
+    @Override
+               public boolean isSpecified (String qName)
+    {
+       int index = getIndex (qName);
+
+       if (index < 0)
+           throw new IllegalArgumentException (
+               "No such attribute: " + qName);
+       return specified [index];
+    }
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Manipulators
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Copy an entire Attributes object.  The "specified" flags are
+     * assigned as true, and "declared" flags as false (except when
+     * an attribute's type is not CDATA),
+     * unless the object is an Attributes2 object.
+     * In that case those flag values are all copied.
+     *
+     * @see AttributesImpl#setAttributes
+     */
+    @Override
+               public void setAttributes (Attributes atts)
+    {
+       int length = atts.getLength ();
+
+       super.setAttributes (atts);
+       declared = new boolean [length];
+       specified = new boolean [length];
+
+       if (atts instanceof Attributes2) {
+           Attributes2 a2 = (Attributes2) atts;
+           for (int i = 0; i < length; i++) {
+               declared [i] = a2.isDeclared (i);
+               specified [i] = a2.isSpecified (i);
+           }
+       } else {
+           for (int i = 0; i < length; i++) {
+               declared [i] = !"CDATA".equals (atts.getType (i));
+               specified [i] = true;
+           }
+       }
+    }
+
+
+    /**
+     * Add an attribute to the end of the list, setting its
+     * "specified" flag to true.  To set that flag's value
+     * to false, use {@link #setSpecified}.
+     *
+     * <p>Unless the attribute <em>type</em> is CDATA, this attribute
+     * is marked as being declared in the DTD.  To set that flag's value
+     * to true for CDATA attributes, use {@link #setDeclared}.
+     *
+     * @see AttributesImpl#addAttribute
+     */
+    @Override
+               public void addAttribute (String uri, String localName, String qName,
+                             String type, String value)
+    {
+       super.addAttribute (uri, localName, qName, type, value);
+
+       int length = getLength ();
+
+       if (length < specified.length) {
+           boolean     newFlags [];
+
+           newFlags = new boolean [length];
+           System.arraycopy (declared, 0, newFlags, 0, declared.length);
+           declared = newFlags;
+
+           newFlags = new boolean [length];
+           System.arraycopy (specified, 0, newFlags, 0, specified.length);
+           specified = newFlags;
+       }
+
+       specified [length - 1] = true;
+       declared [length - 1] = !"CDATA".equals (type);
+    }
+
+
+    // javadoc entirely from superclass
+    @Override
+               public void removeAttribute (int index)
+    {
+       int origMax = getLength () - 1;
+
+       super.removeAttribute (index);
+       if (index != origMax) {
+           System.arraycopy (declared, index + 1, declared, index,
+                   origMax - index);
+           System.arraycopy (specified, index + 1, specified, index,
+                   origMax - index);
+       }
+    }
+
+
+    /**
+     * Assign a value to the "declared" flag of a specific attribute.
+     * This is normally needed only for attributes of type CDATA,
+     * including attributes whose type is changed to or from CDATA.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param value The desired flag value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     * @see #setType
+     */
+    public void setDeclared (int index, boolean value)
+    {
+       if (index < 0 || index >= getLength ())
+           throw new ArrayIndexOutOfBoundsException (
+               "No attribute at index: " + index);
+       declared [index] = value;
+    }
+
+
+    /**
+     * Assign a value to the "specified" flag of a specific attribute.
+     * This is the only way this flag can be cleared, except clearing
+     * by initialization with the copy constructor.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param value The desired flag value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    public void setSpecified (int index, boolean value)
+    {
+       if (index < 0 || index >= getLength ())
+           throw new ArrayIndexOutOfBoundsException (
+               "No attribute at index: " + index);
+       specified [index] = value;
+    }
+}
diff --git a/src/org/xml/sax/ext/DeclHandler.java b/src/org/xml/sax/ext/DeclHandler.java
new file mode 100644 (file)
index 0000000..865e33c
--- /dev/null
@@ -0,0 +1,146 @@
+// DeclHandler.java - Optional handler for DTD declaration events.
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: DeclHandler.java,v 1.6 2004/04/22 13:28:49 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.SAXException;
+
+
+/**
+ * SAX2 extension handler for DTD declaration events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is an optional extension handler for SAX2 to provide more
+ * complete information about DTD declarations in an XML document.
+ * XML readers are not required to recognize this handler, and it
+ * is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>Note that data-related DTD declarations (unparsed entities and
+ * notations) are already reported through the {@link
+ * org.xml.sax.DTDHandler DTDHandler} interface.</p>
+ *
+ * <p>If you are using the declaration handler together with a lexical
+ * handler, all of the events will occur between the
+ * {@link org.xml.sax.ext.LexicalHandler#startDTD startDTD} and the
+ * {@link org.xml.sax.ext.LexicalHandler#endDTD endDTD} events.</p>
+ *
+ * <p>To set the DeclHandler for an XML reader, use the
+ * {@link org.xml.sax.XMLReader#setProperty setProperty} method
+ * with the property name
+ * <code>http://xml.org/sax/properties/declaration-handler</code>
+ * and an object implementing this interface (or null) as the value.
+ * If the reader does not report declaration events, it will throw a
+ * {@link org.xml.sax.SAXNotRecognizedException SAXNotRecognizedException}
+ * when you attempt to register the handler.</p>
+ *
+ * @since SAX 2.0 (extensions 1.0)
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public interface DeclHandler
+{
+
+    /**
+     * Report an element type declaration.
+     *
+     * <p>The content model will consist of the string "EMPTY", the
+     * string "ANY", or a parenthesised group, optionally followed
+     * by an occurrence indicator.  The model will be normalized so
+     * that all parameter entities are fully resolved and all whitespace 
+     * is removed,and will include the enclosing parentheses.  Other
+     * normalization (such as removing redundant parentheses or 
+     * simplifying occurrence indicators) is at the discretion of the
+     * parser.</p>
+     *
+     * @param name The element type name.
+     * @param model The content model as a normalized string.
+     * @exception SAXException The application may raise an exception.
+     */
+    public abstract void elementDecl (String name, String model)
+       throws SAXException;
+
+
+    /**
+     * Report an attribute type declaration.
+     *
+     * <p>Only the effective (first) declaration for an attribute will
+     * be reported.  The type will be one of the strings "CDATA",
+     * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
+     * "ENTITIES", a parenthesized token group with 
+     * the separator "|" and all whitespace removed, or the word
+     * "NOTATION" followed by a space followed by a parenthesized
+     * token group with all whitespace removed.</p>
+     *
+     * <p>The value will be the value as reported to applications,
+     * appropriately normalized and with entity and character
+     * references expanded.  </p>
+     *
+     * @param eName The name of the associated element.
+     * @param aName The name of the attribute.
+     * @param type A string representing the attribute type.
+     * @param mode A string representing the attribute defaulting mode
+     *        ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
+     *        none of these applies.
+     * @param value A string representing the attribute's default value,
+     *        or null if there is none.
+     * @exception SAXException The application may raise an exception.
+     */
+    public abstract void attributeDecl (String eName,
+                                       String aName,
+                                       String type,
+                                       String mode,
+                                       String value)
+       throws SAXException;
+
+
+    /**
+     * Report an internal entity declaration.
+     *
+     * <p>Only the effective (first) declaration for each entity
+     * will be reported.  All parameter entities in the value
+     * will be expanded, but general entities will not.</p>
+     *
+     * @param name The name of the entity.  If it is a parameter
+     *        entity, the name will begin with '%'.
+     * @param value The replacement text of the entity.
+     * @exception SAXException The application may raise an exception.
+     * @see #externalEntityDecl
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    public abstract void internalEntityDecl (String name, String value)
+       throws SAXException;
+
+
+    /**
+     * Report a parsed external entity declaration.
+     *
+     * <p>Only the effective (first) declaration for each entity
+     * will be reported.</p>
+     *
+     * <p>If the system identifier is a URL, the parser must resolve it
+     * fully before passing it to the application.</p>
+     *
+     * @param name The name of the entity.  If it is a parameter
+     *        entity, the name will begin with '%'.
+     * @param publicId The entity's public identifier, or null if none
+     *        was given.
+     * @param systemId The entity's system identifier.
+     * @exception SAXException The application may raise an exception.
+     * @see #internalEntityDecl
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    public abstract void externalEntityDecl (String name, String publicId,
+                                            String systemId)
+       throws SAXException;
+
+}
+
+// end of DeclHandler.java
diff --git a/src/org/xml/sax/ext/DefaultHandler2.java b/src/org/xml/sax/ext/DefaultHandler2.java
new file mode 100644 (file)
index 0000000..f2096ad
--- /dev/null
@@ -0,0 +1,144 @@
+// DefaultHandler2.java - extended DefaultHandler
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: DefaultHandler2.java,v 1.3 2002/01/12 19:04:19 dbrownell Exp $
+
+package org.xml.sax.ext;
+
+import java.io.IOException;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * This class extends the SAX2 base handler class to support the
+ * SAX2 {@link LexicalHandler}, {@link DeclHandler}, and
+ * {@link EntityResolver2} extensions.  Except for overriding the
+ * original SAX1 {@link DefaultHandler#resolveEntity resolveEntity()}
+ * method the added handler methods just return.  Subclassers may
+ * override everything on a method-by-method basis.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> <em>Note:</em> this class might yet learn that the
+ * <em>ContentHandler.setDocumentLocator()</em> call might be passed a
+ * {@link Locator2} object, and that the
+ * <em>ContentHandler.startElement()</em> call might be passed a
+ * {@link Attributes2} object.
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public class DefaultHandler2 extends DefaultHandler
+    implements LexicalHandler, DeclHandler, EntityResolver2
+{
+    /** Constructs a handler which ignores all parsing events. */
+    public DefaultHandler2 () { }
+
+
+    // SAX2 ext-1.0 LexicalHandler
+
+    @Override
+               public void startCDATA ()
+    throws SAXException
+       {}
+
+    @Override
+               public void endCDATA ()
+    throws SAXException
+       {}
+
+    @Override
+               public void startDTD (String name, String publicId, String systemId)
+    throws SAXException
+       {}
+
+    @Override
+               public void endDTD ()
+    throws SAXException
+       {}
+
+    @Override
+               public void startEntity (String name)
+    throws SAXException
+       {}
+
+    @Override
+               public void endEntity (String name)
+    throws SAXException
+       {}
+
+    @Override
+               public void comment (char ch [], int start, int length)
+    throws SAXException
+       { }
+
+
+    // SAX2 ext-1.0 DeclHandler
+
+    @Override
+               public void attributeDecl (String eName, String aName,
+           String type, String mode, String value)
+    throws SAXException
+       {}
+
+    @Override
+               public void elementDecl (String name, String model)
+    throws SAXException
+       {}
+
+    @Override
+               public void externalEntityDecl (String name,
+       String publicId, String systemId)
+    throws SAXException
+       {}
+
+    @Override
+               public void internalEntityDecl (String name, String value)
+    throws SAXException
+       {}
+
+    // SAX2 ext-1.1 EntityResolver2
+
+    /**
+     * Tells the parser that if no external subset has been declared
+     * in the document text, none should be used.
+     */
+    @Override
+               public InputSource getExternalSubset (String name, String baseURI)
+    throws SAXException, IOException
+       { return null; }
+
+    /**
+     * Tells the parser to resolve the systemId against the baseURI
+     * and read the entity text from that resulting absolute URI.
+     * Note that because the older
+     * {@link DefaultHandler#resolveEntity DefaultHandler.resolveEntity()},
+     * method is overridden to call this one, this method may sometimes 
+     * be invoked with null <em>name</em> and <em>baseURI</em>, and
+     * with the <em>systemId</em> already absolutized.
+     */
+    @Override
+               public InputSource resolveEntity (String name, String publicId,
+           String baseURI, String systemId)
+    throws SAXException, IOException
+       { return null; }
+    
+    // SAX1 EntityResolver
+
+    /**
+     * Invokes
+     * {@link EntityResolver2#resolveEntity EntityResolver2.resolveEntity()}
+     * with null entity name and base URI.
+     * You only need to override that method to use this class.
+     */
+    @Override
+               public InputSource resolveEntity (String publicId, String systemId)
+    throws SAXException, IOException
+       { return resolveEntity (null, publicId, null, systemId); }
+}
diff --git a/src/org/xml/sax/ext/EntityResolver2.java b/src/org/xml/sax/ext/EntityResolver2.java
new file mode 100644 (file)
index 0000000..a1108a3
--- /dev/null
@@ -0,0 +1,197 @@
+// EntityResolver2.java - Extended SAX entity resolver.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: EntityResolver2.java,v 1.2 2002/01/12 19:20:08 dbrownell Exp $
+
+package org.xml.sax.ext;
+
+import java.io.IOException;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Extended interface for mapping external entity references to input
+ * sources, or providing a missing external subset.  The
+ * {@link XMLReader#setEntityResolver XMLReader.setEntityResolver()} method
+ * is used to provide implementations of this interface to parsers.
+ * When a parser uses the methods in this interface, the
+ * {@link EntityResolver2#resolveEntity EntityResolver2.resolveEntity()}
+ * method (in this interface) is used <em>instead of</em> the older (SAX 1.0)
+ * {@link EntityResolver#resolveEntity EntityResolver.resolveEntity()} method.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p>If a SAX application requires the customized handling which this
+ * interface defines for external entities, it must ensure that it uses
+ * an XMLReader with the
+ * <em>http://xml.org/sax/features/use-entity-resolver2</em> feature flag
+ * set to <em>true</em> (which is its default value when the feature is
+ * recognized).  If that flag is unrecognized, or its value is false,
+ * or the resolver does not implement this interface, then only the
+ * {@link EntityResolver} method will be used.
+ * </p>
+ *
+ * <p>That supports three categories of application that modify entity
+ * resolution.  <em>Old Style</em> applications won't know about this interface;
+ * they will provide an EntityResolver.
+ * <em>Transitional Mode</em> provide an EntityResolver2 and automatically
+ * get the benefit of its methods in any systems (parsers or other tools)
+ * supporting it, due to polymorphism.
+ * Both <em>Old Style</em> and <em>Transitional Mode</em> applications will
+ * work with any SAX2 parser.
+ * <em>New style</em> applications will fail to run except on SAX2 parsers
+ * that support this particular feature.
+ * They will insist that feature flag have a value of "true", and the
+ * EntityResolver2 implementation they provide  might throw an exception
+ * if the original SAX 1.0 style entity resolution method is invoked.
+ * </p>
+ *
+ * @see org.xml.sax.XMLReader#setEntityResolver
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBD
+ */
+public interface EntityResolver2 extends EntityResolver
+{
+    /**
+     * Allows applications to provide an external subset for documents
+     * that don't explicitly define one.  Documents with DOCTYPE declarations
+     * that omit an external subset can thus augment the declarations
+     * available for validation, entity processing, and attribute processing
+     * (normalization, defaulting, and reporting types including ID).
+     * This augmentation is reported
+     * through the {@link LexicalHandler#startDTD startDTD()} method as if
+     * the document text had originally included the external subset;
+     * this callback is made before any internal subset data or errors
+     * are reported.</p>
+     *
+     * <p>This method can also be used with documents that have no DOCTYPE
+     * declaration.  When the root element is encountered,
+     * but no DOCTYPE declaration has been seen, this method is
+     * invoked.  If it returns a value for the external subset, that root
+     * element is declared to be the root element, giving the effect of
+     * splicing a DOCTYPE declaration at the end the prolog of a document
+     * that could not otherwise be valid.  The sequence of parser callbacks
+     * in that case logically resembles this:</p>
+     *
+     * <pre>
+     * ... comments and PIs from the prolog (as usual)
+     * startDTD ("rootName", source.getPublicId (), source.getSystemId ());
+     * startEntity ("[dtd]");
+     * ... declarations, comments, and PIs from the external subset
+     * endEntity ("[dtd]");
+     * endDTD ();
+     * ... then the rest of the document (as usual)
+     * startElement (..., "rootName", ...);
+     * </pre>
+     *
+     * <p>Note that the InputSource gets no further resolution.
+     * Implementations of this method may wish to invoke
+     * {@link #resolveEntity resolveEntity()} to gain benefits such as use
+     * of local caches of DTD entities.  Also, this method will never be
+     * used by a (non-validating) processor that is not including external
+     * parameter entities. </p>
+     *
+     * <p>Uses for this method include facilitating data validation when
+     * interoperating with XML processors that would always require
+     * undesirable network accesses for external entities, or which for
+     * other reasons adopt a "no DTDs" policy.
+     * Non-validation motives include forcing documents to include DTDs so
+     * that attributes are handled consistently.
+     * For example, an XPath processor needs to know which attibutes have
+     * type "ID" before it can process a widely used type of reference.</p>
+     * 
+     * <p><strong>Warning:</strong> Returning an external subset modifies
+     * the input document.  By providing definitions for general entities,
+     * it can make a malformed document appear to be well formed.
+     * </p>
+     *
+     * @param name Identifies the document root element.  This name comes
+     * from a DOCTYPE declaration (where available) or from the actual
+     * root element. 
+     * @param baseURI The document's base URI, serving as an additional
+     * hint for selecting the external subset.  This is always an absolute
+     * URI, unless it is null because the XMLReader was given an InputSource
+     * without one.
+     *
+     * @return An InputSource object describing the new external subset
+     * to be used by the parser, or null to indicate that no external
+     * subset is provided.
+     *
+     * @exception SAXException Any SAX exception, possibly wrapping
+     * another exception.
+     * @exception IOException Probably indicating a failure to create
+     * a new InputStream or Reader, or an illegal URL.
+     */
+    public InputSource getExternalSubset (String name, String baseURI)
+    throws SAXException, IOException;
+
+    /**
+     * Allows applications to map references to external entities into input
+     * sources, or tell the parser it should use conventional URI resolution.
+     * This method is only called for external entities which have been
+     * properly declared.
+     * This method provides more flexibility than the {@link EntityResolver}
+     * interface, supporting implementations of more complex catalogue
+     * schemes such as the one defined by the <a href=
+       "http://www.oasis-open.org/committees/entity/spec-2001-08-06.html"
+       >OASIS XML Catalogs</a> specification.</p>
+     *
+     * <p>Parsers configured to use this resolver method will call it
+     * to determine the input source to use for any external entity
+     * being included because of a reference in the XML text.
+     * That excludes the document entity, and any external entity returned
+     * by {@link #getExternalSubset getExternalSubset()}.
+     * When a (non-validating) processor is configured not to include
+     * a class of entities (parameter or general) through use of feature
+     * flags, this method is not invoked for such entities.  </p>
+     *
+     * <p>Note that the entity naming scheme used here is the same one
+     * used in the {@link LexicalHandler}, or in the {@link
+       org.xml.sax.ContentHandler#skippedEntity
+       ContentHandler.skippedEntity()}
+     * method. </p>
+     *
+     * @param name Identifies the external entity being resolved.
+     * Either "[dtd]" for the external subset, or a name starting
+     * with "%" to indicate a parameter entity, or else the name of
+     * a general entity.  This is never null when invoked by a SAX2
+     * parser.
+     * @param publicId The public identifier of the external entity being
+     * referenced (normalized as required by the XML specification), or
+     * null if none was supplied.
+     * @param baseURI The URI with respect to which relative systemIDs
+     * are interpreted.  This is always an absolute URI, unless it is
+     * null (likely because the XMLReader was given an InputSource without
+     *  one).  This URI is defined by the XML specification to be the one
+     * associated with the "&lt;" starting the relevant declaration.
+     * @param systemId The system identifier of the external entity
+     * being referenced; either a relative or absolute URI.
+     *  This is never null when invoked by a SAX2 parser; only declared
+     * entities, and any external subset, are resolved by such parsers.
+     *
+     * @return An InputSource object describing the new input source to
+     * be used by the parser.  Returning null directs the parser to
+     * resolve the system ID against the base URI and open a connection
+     * to resulting URI.
+     *
+     * @exception SAXException Any SAX exception, possibly wrapping
+     * another exception.
+     * @exception IOException Probably indicating a failure to create
+     * a new InputStream or Reader, or an illegal URL.
+     */
+    public InputSource resolveEntity (
+           String name,
+           String publicId,
+           String baseURI,
+           String systemId
+    ) throws SAXException, IOException;
+}
diff --git a/src/org/xml/sax/ext/LexicalHandler.java b/src/org/xml/sax/ext/LexicalHandler.java
new file mode 100644 (file)
index 0000000..d63d87f
--- /dev/null
@@ -0,0 +1,212 @@
+// LexicalHandler.java - optional handler for lexical parse events.
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: LexicalHandler.java,v 1.5 2002/01/30 21:00:44 dbrownell Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.SAXException;
+
+/**
+ * SAX2 extension handler for lexical events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is an optional extension handler for SAX2 to provide
+ * lexical information about an XML document, such as comments
+ * and CDATA section boundaries.
+ * XML readers are not required to recognize this handler, and it
+ * is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>The events in the lexical handler apply to the entire document,
+ * not just to the document element, and all lexical handler events
+ * must appear between the content handler's startDocument and
+ * endDocument events.</p>
+ *
+ * <p>To set the LexicalHandler for an XML reader, use the
+ * {@link org.xml.sax.XMLReader#setProperty setProperty} method
+ * with the property name
+ * <code>http://xml.org/sax/properties/lexical-handler</code>
+ * and an object implementing this interface (or null) as the value.
+ * If the reader does not report lexical events, it will throw a
+ * {@link org.xml.sax.SAXNotRecognizedException SAXNotRecognizedException}
+ * when you attempt to register the handler.</p>
+ *
+ * @since SAX 2.0 (extensions 1.0)
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public interface LexicalHandler
+{
+
+    /**
+     * Report the start of DTD declarations, if any.
+     *
+     * <p>This method is intended to report the beginning of the
+     * DOCTYPE declaration; if the document has no DOCTYPE declaration,
+     * this method will not be invoked.</p>
+     *
+     * <p>All declarations reported through 
+     * {@link org.xml.sax.DTDHandler DTDHandler} or
+     * {@link org.xml.sax.ext.DeclHandler DeclHandler} events must appear
+     * between the startDTD and {@link #endDTD endDTD} events.
+     * Declarations are assumed to belong to the internal DTD subset
+     * unless they appear between {@link #startEntity startEntity}
+     * and {@link #endEntity endEntity} events.  Comments and
+     * processing instructions from the DTD should also be reported
+     * between the startDTD and endDTD events, in their original 
+     * order of (logical) occurrence; they are not required to
+     * appear in their correct locations relative to DTDHandler
+     * or DeclHandler events, however.</p>
+     *
+     * <p>Note that the start/endDTD events will appear within
+     * the start/endDocument events from ContentHandler and
+     * before the first 
+     * {@link org.xml.sax.ContentHandler#startElement startElement}
+     * event.</p>
+     *
+     * @param name The document type name.
+     * @param publicId The declared public identifier for the
+     *        external DTD subset, or null if none was declared.
+     * @param systemId The declared system identifier for the
+     *        external DTD subset, or null if none was declared.
+     *        (Note that this is not resolved against the document
+     *        base URI.)
+     * @exception SAXException The application may raise an
+     *            exception.
+     * @see #endDTD
+     * @see #startEntity
+     */
+    public abstract void startDTD (String name, String publicId,
+                                  String systemId)
+       throws SAXException;
+
+
+    /**
+     * Report the end of DTD declarations.
+     *
+     * <p>This method is intended to report the end of the
+     * DOCTYPE declaration; if the document has no DOCTYPE declaration,
+     * this method will not be invoked.</p>
+     *
+     * @exception SAXException The application may raise an exception.
+     * @see #startDTD
+     */
+    public abstract void endDTD ()
+       throws SAXException;
+
+
+    /**
+     * Report the beginning of some internal and external XML entities.
+     *
+     * <p>The reporting of parameter entities (including
+     * the external DTD subset) is optional, and SAX2 drivers that
+     * report LexicalHandler events may not implement it; you can use the
+     * <code
+     * >http://xml.org/sax/features/lexical-handler/parameter-entities</code>
+     * feature to query or control the reporting of parameter entities.</p>
+     *
+     * <p>General entities are reported with their regular names,
+     * parameter entities have '%' prepended to their names, and 
+     * the external DTD subset has the pseudo-entity name "[dtd]".</p>
+     *
+     * <p>When a SAX2 driver is providing these events, all other 
+     * events must be properly nested within start/end entity 
+     * events.  There is no additional requirement that events from 
+     * {@link org.xml.sax.ext.DeclHandler DeclHandler} or
+     * {@link org.xml.sax.DTDHandler DTDHandler} be properly ordered.</p>
+     *
+     * <p>Note that skipped entities will be reported through the
+     * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
+     * event, which is part of the ContentHandler interface.</p>
+     *
+     * <p>Because of the streaming event model that SAX uses, some
+     * entity boundaries cannot be reported under any 
+     * circumstances:</p>
+     *
+     * <ul>
+     * <li>general entities within attribute values</li>
+     * <li>parameter entities within declarations</li>
+     * </ul>
+     *
+     * <p>These will be silently expanded, with no indication of where
+     * the original entity boundaries were.</p>
+     *
+     * <p>Note also that the boundaries of character references (which
+     * are not really entities anyway) are not reported.</p>
+     *
+     * <p>All start/endEntity events must be properly nested.
+     *
+     * @param name The name of the entity.  If it is a parameter
+     *        entity, the name will begin with '%', and if it is the
+     *        external DTD subset, it will be "[dtd]".
+     * @exception SAXException The application may raise an exception.
+     * @see #endEntity
+     * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
+     * @see org.xml.sax.ext.DeclHandler#externalEntityDecl 
+     */
+    public abstract void startEntity (String name)
+       throws SAXException;
+
+
+    /**
+     * Report the end of an entity.
+     *
+     * @param name The name of the entity that is ending.
+     * @exception SAXException The application may raise an exception.
+     * @see #startEntity
+     */
+    public abstract void endEntity (String name)
+       throws SAXException;
+
+
+    /**
+     * Report the start of a CDATA section.
+     *
+     * <p>The contents of the CDATA section will be reported through
+     * the regular {@link org.xml.sax.ContentHandler#characters
+     * characters} event; this event is intended only to report
+     * the boundary.</p>
+     *
+     * @exception SAXException The application may raise an exception.
+     * @see #endCDATA
+     */
+    public abstract void startCDATA ()
+       throws SAXException;
+
+
+    /**
+     * Report the end of a CDATA section.
+     *
+     * @exception SAXException The application may raise an exception.
+     * @see #startCDATA
+     */
+    public abstract void endCDATA ()
+       throws SAXException;
+
+
+    /**
+     * Report an XML comment anywhere in the document.
+     *
+     * <p>This callback will be used for comments inside or outside the
+     * document element, including comments in the external DTD
+     * subset (if read).  Comments in the DTD must be properly
+     * nested inside start/endDTD and start/endEntity events (if
+     * used).</p>
+     *
+     * @param ch An array holding the characters in the comment.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use from the array.
+     * @exception SAXException The application may raise an exception.
+     */
+    public abstract void comment (char ch[], int start, int length)
+       throws SAXException;
+
+}
+
+// end of LexicalHandler.java
diff --git a/src/org/xml/sax/ext/Locator2.java b/src/org/xml/sax/ext/Locator2.java
new file mode 100644 (file)
index 0000000..6de9a16
--- /dev/null
@@ -0,0 +1,75 @@
+// Locator2.java - extended Locator
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Locator2.java,v 1.5 2004/03/17 14:30:10 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Locator;
+
+
+/**
+ * SAX2 extension to augment the entity information provided 
+ * though a {@link Locator}.
+ * If an implementation supports this extension, the Locator
+ * provided in {@link org.xml.sax.ContentHandler#setDocumentLocator
+ * ContentHandler.setDocumentLocator() } will implement this
+ * interface, and the
+ * <em>http://xml.org/sax/features/use-locator2</em> feature
+ * flag will have the value <em>true</em>.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> XMLReader implementations are not required to support this
+ * information, and it is not part of core-only SAX2 distributions.</p>
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public interface Locator2 extends Locator
+{
+    /**
+     * Returns the version of XML used for the entity.  This will
+     * normally be the identifier from the current entity's
+     * <em>&lt;?xml&nbsp;version='...'&nbsp;...?&gt;</em> declaration,
+     * or be defaulted by the parser.
+     *
+     * @return Identifier for the XML version being used to interpret
+     * the entity's text, or null if that information is not yet
+     * available in the current parsing state.
+     */
+    public String getXMLVersion ();
+
+    /**
+     * Returns the name of the character encoding for the entity.
+     * If the encoding was declared externally (for example, in a MIME
+     * Content-Type header), that will be the name returned.  Else if there
+     * was an <em>&lt;?xml&nbsp;...encoding='...'?&gt;</em> declaration at
+     * the start of the document, that encoding name will be returned.
+     * Otherwise the encoding will been inferred (normally to be UTF-8, or
+     * some UTF-16 variant), and that inferred name will be returned.
+     *
+     * <p>When an {@link org.xml.sax.InputSource InputSource} is used
+     * to provide an entity's character stream, this method returns the
+     * encoding provided in that input stream.
+     *
+     * <p> Note that some recent W3C specifications require that text
+     * in some encodings be normalized, using Unicode Normalization
+     * Form C, before processing.  Such normalization must be performed
+     * by applications, and would normally be triggered based on the
+     * value returned by this method.
+     *
+     * <p> Encoding names may be those used by the underlying JVM,
+     * and comparisons should be case-insensitive.
+     *
+     * @return Name of the character encoding being used to interpret
+     * * the entity's text, or null if this was not provided for a *
+     * character stream passed through an InputSource or is otherwise
+     * not yet available in the current parsing state.
+     */
+    public String getEncoding ();
+}
diff --git a/src/org/xml/sax/ext/Locator2Impl.java b/src/org/xml/sax/ext/Locator2Impl.java
new file mode 100644 (file)
index 0000000..89ea4ba
--- /dev/null
@@ -0,0 +1,103 @@
+// Locator2Impl.java - extended LocatorImpl
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Locator2Impl.java,v 1.3 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.LocatorImpl;
+
+
+/**
+ * SAX2 extension helper for holding additional Entity information,
+ * implementing the {@link Locator2} interface.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> This is not part of core-only SAX2 distributions.</p>
+ *
+ * @since SAX 2.0.2
+ * @author David Brownell
+ * @version TBS
+ */
+public class Locator2Impl extends LocatorImpl implements Locator2
+{
+    private String     encoding;
+    private String     version;
+
+
+    /**
+     * Construct a new, empty Locator2Impl object.
+     * This will not normally be useful, since the main purpose
+     * of this class is to make a snapshot of an existing Locator.
+     */
+    public Locator2Impl () { }
+
+    /**
+     * Copy an existing Locator or Locator2 object.
+     * If the object implements Locator2, values of the
+     * <em>encoding</em> and <em>version</em>strings are copied,
+     * otherwise they set to <em>null</em>. 
+     *
+     * @param locator The existing Locator object.
+     */
+    public Locator2Impl (Locator locator)
+    {
+       super (locator);
+       if (locator instanceof Locator2) {
+           Locator2    l2 = (Locator2) locator;
+
+           version = l2.getXMLVersion ();
+           encoding = l2.getEncoding ();
+       }
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // Locator2 method implementations
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Returns the current value of the version property.
+     *
+     * @see #setXMLVersion
+     */
+    @Override
+               public String getXMLVersion ()
+       { return version; }
+
+    /**
+     * Returns the current value of the encoding property.
+     *
+     * @see #setEncoding
+     */
+    @Override
+               public String getEncoding ()
+       { return encoding; }
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Setters 
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Assigns the current value of the version property.
+     *
+     * @param version the new "version" value
+     * @see #getXMLVersion
+     */
+    public void setXMLVersion (String version)
+       { this.version = version; }
+
+    /**
+     * Assigns the current value of the encoding property.
+     *
+     * @param encoding the new "encoding" value
+     * @see #getEncoding
+     */
+    public void setEncoding (String encoding)
+       { this.encoding = encoding; }
+}
diff --git a/src/org/xml/sax/helpers/AttributeListImpl.java b/src/org/xml/sax/helpers/AttributeListImpl.java
new file mode 100644 (file)
index 0000000..fba22ea
--- /dev/null
@@ -0,0 +1,318 @@
+// SAX default implementation for AttributeList.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: AttributeListImpl.java,v 1.6 2002/01/30 20:52:22 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import org.xml.sax.AttributeList;
+
+import java.util.Vector;
+
+
+/**e
+ * Default implementation for AttributeList.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>AttributeList implements the deprecated SAX1 {@link
+ * org.xml.sax.AttributeList AttributeList} interface, and has been
+ * replaced by the new SAX2 {@link org.xml.sax.helpers.AttributesImpl
+ * AttributesImpl} interface.</p>
+ *
+ * <p>This class provides a convenience implementation of the SAX
+ * {@link org.xml.sax.AttributeList AttributeList} interface.  This 
+ * implementation is useful both for SAX parser writers, who can use 
+ * it to provide attributes to the application, and for SAX application 
+ * writers, who can use it to create a persistent copy of an element's 
+ * attribute specifications:</p>
+ *
+ * <pre>
+ * private AttributeList myatts;
+ *
+ * public void startElement (String name, AttributeList atts)
+ * {
+ *              // create a persistent copy of the attribute list
+ *              // for use outside this method
+ *   myatts = new AttributeListImpl(atts);
+ *   [...]
+ * }
+ * </pre>
+ *
+ * <p>Please note that SAX parsers are not required to use this
+ * class to provide an implementation of AttributeList; it is
+ * supplied only as an optional convenience.  In particular, 
+ * parser writers are encouraged to invent more efficient
+ * implementations.</p>
+ *
+ * @deprecated This class implements a deprecated interface,
+ *             {@link org.xml.sax.AttributeList AttributeList};
+ *             that interface has been replaced by
+ *             {@link org.xml.sax.Attributes Attributes},
+ *             which is implemented in the
+ *             {@link org.xml.sax.helpers.AttributesImpl 
+ *            AttributesImpl} helper class.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.AttributeList
+ * @see org.xml.sax.DocumentHandler#startElement 
+ */
+public class AttributeListImpl implements AttributeList
+{
+    
+    /**
+     * Create an empty attribute list.
+     *
+     * <p>This constructor is most useful for parser writers, who
+     * will use it to create a single, reusable attribute list that
+     * can be reset with the clear method between elements.</p>
+     *
+     * @see #addAttribute
+     * @see #clear
+     */
+    public AttributeListImpl ()
+    {
+    }
+    
+    
+    /**
+     * Construct a persistent copy of an existing attribute list.
+     *
+     * <p>This constructor is most useful for application writers,
+     * who will use it to create a persistent copy of an existing
+     * attribute list.</p>
+     *
+     * @param atts The attribute list to copy
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    public AttributeListImpl (AttributeList atts)
+    {
+       setAttributeList(atts);
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Methods specific to this class.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Set the attribute list, discarding previous contents.
+     *
+     * <p>This method allows an application writer to reuse an
+     * attribute list easily.</p>
+     *
+     * @param atts The attribute list to copy.
+     */
+    public void setAttributeList (AttributeList atts)
+    {
+       int count = atts.getLength();
+       
+       clear();
+       
+       for (int i = 0; i < count; i++) {
+           addAttribute(atts.getName(i), atts.getType(i), atts.getValue(i));
+       }
+    }
+    
+    
+    /**
+     * Add an attribute to an attribute list.
+     *
+     * <p>This method is provided for SAX parser writers, to allow them
+     * to build up an attribute list incrementally before delivering
+     * it to the application.</p>
+     *
+     * @param name The attribute name.
+     * @param type The attribute type ("NMTOKEN" for an enumeration).
+     * @param value The attribute value (must not be null).
+     * @see #removeAttribute
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    public void addAttribute (String name, String type, String value)
+    {
+       names.addElement(name);
+       types.addElement(type);
+       values.addElement(value);
+    }
+    
+    
+    /**
+     * Remove an attribute from the list.
+     *
+     * <p>SAX application writers can use this method to filter an
+     * attribute out of an AttributeList.  Note that invoking this
+     * method will change the length of the attribute list and
+     * some of the attribute's indices.</p>
+     *
+     * <p>If the requested attribute is not in the list, this is
+     * a no-op.</p>
+     *
+     * @param name The attribute name.
+     * @see #addAttribute
+     */
+    public void removeAttribute (String name)
+    {
+       int i = names.indexOf(name);
+       
+       if (i >= 0) {
+           names.removeElementAt(i);
+           types.removeElementAt(i);
+           values.removeElementAt(i);
+       }
+    }
+    
+    
+    /**
+     * Clear the attribute list.
+     *
+     * <p>SAX parser writers can use this method to reset the attribute
+     * list between DocumentHandler.startElement events.  Normally,
+     * it will make sense to reuse the same AttributeListImpl object
+     * rather than allocating a new one each time.</p>
+     *
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    public void clear ()
+    {
+       names.removeAllElements();
+       types.removeAllElements();
+       values.removeAllElements();
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.AttributeList
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Return the number of attributes in the list.
+     *
+     * @return The number of attributes in the list.
+     * @see org.xml.sax.AttributeList#getLength
+     */
+    @Override
+               public int getLength ()
+    {
+       return names.size();
+    }
+    
+    
+    /**
+     * Get the name of an attribute (by position).
+     *
+     * @param i The position of the attribute in the list.
+     * @return The attribute name as a string, or null if there
+     *         is no attribute at that position.
+     * @see org.xml.sax.AttributeList#getName(int)
+     */
+    @Override
+               public String getName (int i)
+    {
+       if (i < 0) {
+           return null;
+       }
+       try {
+           return (String)names.elementAt(i);
+       } catch (ArrayIndexOutOfBoundsException e) {
+           return null;
+       }
+    }
+    
+    
+    /**
+     * Get the type of an attribute (by position).
+     *
+     * @param i The position of the attribute in the list.
+     * @return The attribute type as a string ("NMTOKEN" for an
+     *         enumeration, and "CDATA" if no declaration was
+     *         read), or null if there is no attribute at
+     *         that position.
+     * @see org.xml.sax.AttributeList#getType(int)
+     */
+    @Override
+               public String getType (int i)
+    {
+       if (i < 0) {
+           return null;
+       }
+       try {
+           return (String)types.elementAt(i);
+       } catch (ArrayIndexOutOfBoundsException e) {
+           return null;
+       }
+    }
+    
+    
+    /**
+     * Get the value of an attribute (by position).
+     *
+     * @param i The position of the attribute in the list.
+     * @return The attribute value as a string, or null if
+     *         there is no attribute at that position.
+     * @see org.xml.sax.AttributeList#getValue(int)
+     */
+    @Override
+               public String getValue (int i)
+    {
+       if (i < 0) {
+           return null;
+       }
+       try {
+           return (String)values.elementAt(i);
+       } catch (ArrayIndexOutOfBoundsException e) {
+           return null;
+       }
+    }
+    
+    
+    /**
+     * Get the type of an attribute (by name).
+     *
+     * @param name The attribute name.
+     * @return The attribute type as a string ("NMTOKEN" for an
+     *         enumeration, and "CDATA" if no declaration was
+     *         read).
+     * @see org.xml.sax.AttributeList#getType(java.lang.String)
+     */
+    @Override
+               public String getType (String name)
+    {
+       return getType(names.indexOf(name));
+    }
+    
+    
+    /**
+     * Get the value of an attribute (by name).
+     *
+     * @param name The attribute name.
+     * @see org.xml.sax.AttributeList#getValue(java.lang.String)
+     */
+    @Override
+               public String getValue (String name)
+    {
+       return getValue(names.indexOf(name));
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    Vector names = new Vector();
+    Vector types = new Vector();
+    Vector values = new Vector();
+
+}
+
+// end of AttributeListImpl.java
diff --git a/src/org/xml/sax/helpers/AttributesImpl.java b/src/org/xml/sax/helpers/AttributesImpl.java
new file mode 100644 (file)
index 0000000..fac6b26
--- /dev/null
@@ -0,0 +1,630 @@
+// AttributesImpl.java - default implementation of Attributes.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: AttributesImpl.java,v 1.9 2002/01/30 20:52:24 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import org.xml.sax.Attributes;
+
+
+/**
+ * Default implementation of the Attributes interface.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class provides a default implementation of the SAX2
+ * {@link org.xml.sax.Attributes Attributes} interface, with the 
+ * addition of manipulators so that the list can be modified or 
+ * reused.</p>
+ *
+ * <p>There are two typical uses of this class:</p>
+ *
+ * <ol>
+ * <li>to take a persistent snapshot of an Attributes object
+ *  in a {@link org.xml.sax.ContentHandler#startElement startElement} event; or</li>
+ * <li>to construct or modify an Attributes object in a SAX2 driver or filter.</li>
+ * </ol>
+ *
+ * <p>This class replaces the now-deprecated SAX1 {@link 
+ * org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
+ * class; in addition to supporting the updated Attributes
+ * interface rather than the deprecated {@link org.xml.sax.AttributeList
+ * AttributeList} interface, it also includes a much more efficient 
+ * implementation using a single array rather than a set of Vectors.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public class AttributesImpl implements Attributes
+{
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Constructors.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct a new, empty AttributesImpl object.
+     */
+    public AttributesImpl ()
+    {
+       length = 0;
+       data = null;
+    }
+
+
+    /**
+     * Copy an existing Attributes object.
+     *
+     * <p>This constructor is especially useful inside a
+     * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
+     *
+     * @param atts The existing Attributes object.
+     */
+    public AttributesImpl (Attributes atts)
+    {
+       setAttributes(atts);
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.Attributes.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Return the number of attributes in the list.
+     *
+     * @return The number of attributes in the list.
+     * @see org.xml.sax.Attributes#getLength
+     */
+    @Override
+               public int getLength ()
+    {
+       return length;
+    }
+
+
+    /**
+     * Return an attribute's Namespace URI.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The Namespace URI, the empty string if none is
+     *         available, or null if the index is out of range.
+     * @see org.xml.sax.Attributes#getURI
+     */
+    @Override
+               public String getURI (int index)
+    {
+       if (index >= 0 && index < length) {
+           return data[index*5];
+       } else {
+           return null;
+       }
+    }
+
+
+    /**
+     * Return an attribute's local name.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's local name, the empty string if 
+     *         none is available, or null if the index if out of range.
+     * @see org.xml.sax.Attributes#getLocalName
+     */
+    @Override
+               public String getLocalName (int index)
+    {
+       if (index >= 0 && index < length) {
+           return data[index*5+1];
+       } else {
+           return null;
+       }
+    }
+
+
+    /**
+     * Return an attribute's qualified (prefixed) name.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's qualified name, the empty string if 
+     *         none is available, or null if the index is out of bounds.
+     * @see org.xml.sax.Attributes#getQName
+     */
+    @Override
+               public String getQName (int index)
+    {
+       if (index >= 0 && index < length) {
+           return data[index*5+2];
+       } else {
+           return null;
+       }
+    }
+
+
+    /**
+     * Return an attribute's type by index.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's type, "CDATA" if the type is unknown, or null
+     *         if the index is out of bounds.
+     * @see org.xml.sax.Attributes#getType(int)
+     */
+    @Override
+               public String getType (int index)
+    {
+       if (index >= 0 && index < length) {
+           return data[index*5+3];
+       } else {
+           return null;
+       }
+    }
+
+
+    /**
+     * Return an attribute's value by index.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's value or null if the index is out of bounds.
+     * @see org.xml.sax.Attributes#getValue(int)
+     */
+    @Override
+               public String getValue (int index)
+    {
+       if (index >= 0 && index < length) {
+           return data[index*5+4];
+       } else {
+           return null;
+       }
+    }
+
+
+    /**
+     * Look up an attribute's index by Namespace name.
+     *
+     * <p>In many cases, it will be more efficient to look up the name once and
+     * use the index query methods rather than using the name query methods
+     * repeatedly.</p>
+     *
+     * @param uri The attribute's Namespace URI, or the empty
+     *        string if none is available.
+     * @param localName The attribute's local name.
+     * @return The attribute's index, or -1 if none matches.
+     * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
+     */
+    @Override
+               public int getIndex (String uri, String localName)
+    {
+       int max = length * 5;
+       for (int i = 0; i < max; i += 5) {
+           if (data[i].equals(uri) && data[i+1].equals(localName)) {
+               return i / 5;
+           }
+       } 
+       return -1;
+    }
+
+
+    /**
+     * Look up an attribute's index by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's index, or -1 if none matches.
+     * @see org.xml.sax.Attributes#getIndex(java.lang.String)
+     */
+    @Override
+               public int getIndex (String qName)
+    {
+       int max = length * 5;
+       for (int i = 0; i < max; i += 5) {
+           if (data[i+2].equals(qName)) {
+               return i / 5;
+           }
+       } 
+       return -1;
+    }
+
+
+    /**
+     * Look up an attribute's type by Namespace-qualified name.
+     *
+     * @param uri The Namespace URI, or the empty string for a name
+     *        with no explicit Namespace URI.
+     * @param localName The local name.
+     * @return The attribute's type, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getType(java.lang.String,java.lang.String)
+     */
+    @Override
+               public String getType (String uri, String localName)
+    {
+       int max = length * 5;
+       for (int i = 0; i < max; i += 5) {
+           if (data[i].equals(uri) && data[i+1].equals(localName)) {
+               return data[i+3];
+           }
+       } 
+       return null;
+    }
+
+
+    /**
+     * Look up an attribute's type by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's type, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getType(java.lang.String)
+     */
+    @Override
+               public String getType (String qName)
+    {
+       int max = length * 5;
+       for (int i = 0; i < max; i += 5) {
+           if (data[i+2].equals(qName)) {
+               return data[i+3];
+           }
+       }
+       return null;
+    }
+
+
+    /**
+     * Look up an attribute's value by Namespace-qualified name.
+     *
+     * @param uri The Namespace URI, or the empty string for a name
+     *        with no explicit Namespace URI.
+     * @param localName The local name.
+     * @return The attribute's value, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getValue(java.lang.String,java.lang.String)
+     */
+    @Override
+               public String getValue (String uri, String localName)
+    {
+       int max = length * 5;
+       for (int i = 0; i < max; i += 5) {
+           if (data[i].equals(uri) && data[i+1].equals(localName)) {
+               return data[i+4];
+           }
+       }
+       return null;
+    }
+
+
+    /**
+     * Look up an attribute's value by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's value, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getValue(java.lang.String)
+     */
+    @Override
+               public String getValue (String qName)
+    {
+       int max = length * 5;
+       for (int i = 0; i < max; i += 5) {
+           if (data[i+2].equals(qName)) {
+               return data[i+4];
+           }
+       }
+       return null;
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Manipulators.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Clear the attribute list for reuse.
+     *
+     * <p>Note that little memory is freed by this call:
+     * the current array is kept so it can be 
+     * reused.</p>
+     */
+    public void clear ()
+    {
+       if (data != null) {
+           for (int i = 0; i < (length * 5); i++)
+               data [i] = null;
+       }
+       length = 0;
+    }
+
+
+    /**
+     * Copy an entire Attributes object.
+     *
+     * <p>It may be more efficient to reuse an existing object
+     * rather than constantly allocating new ones.</p>
+     * 
+     * @param atts The attributes to copy.
+     */
+    public void setAttributes (Attributes atts)
+    {
+        clear();
+        length = atts.getLength();
+        if (length > 0) {
+            data = new String[length*5];
+            for (int i = 0; i < length; i++) {
+                data[i*5] = atts.getURI(i);
+                data[i*5+1] = atts.getLocalName(i);
+                data[i*5+2] = atts.getQName(i);
+                data[i*5+3] = atts.getType(i);
+                data[i*5+4] = atts.getValue(i);
+            }
+       }
+    }
+
+
+    /**
+     * Add an attribute to the end of the list.
+     *
+     * <p>For the sake of speed, this method does no checking
+     * to see if the attribute is already in the list: that is
+     * the responsibility of the application.</p>
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        none is available or Namespace processing is not
+     *        being performed.
+     * @param localName The local name, or the empty string if
+     *        Namespace processing is not being performed.
+     * @param qName The qualified (prefixed) name, or the empty string
+     *        if qualified names are not available.
+     * @param type The attribute type as a string.
+     * @param value The attribute value.
+     */
+    public void addAttribute (String uri, String localName, String qName,
+                             String type, String value)
+    {
+       ensureCapacity(length+1);
+       data[length*5] = uri;
+       data[length*5+1] = localName;
+       data[length*5+2] = qName;
+       data[length*5+3] = type;
+       data[length*5+4] = value;
+       length++;
+    }
+
+
+    /**
+     * Set an attribute in the list.
+     *
+     * <p>For the sake of speed, this method does no checking
+     * for name conflicts or well-formedness: such checks are the
+     * responsibility of the application.</p>
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param uri The Namespace URI, or the empty string if
+     *        none is available or Namespace processing is not
+     *        being performed.
+     * @param localName The local name, or the empty string if
+     *        Namespace processing is not being performed.
+     * @param qName The qualified name, or the empty string
+     *        if qualified names are not available.
+     * @param type The attribute type as a string.
+     * @param value The attribute value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setAttribute (int index, String uri, String localName,
+                             String qName, String type, String value)
+    {
+       if (index >= 0 && index < length) {
+           data[index*5] = uri;
+           data[index*5+1] = localName;
+           data[index*5+2] = qName;
+           data[index*5+3] = type;
+           data[index*5+4] = value;
+       } else {
+           badIndex(index);
+       }
+    }
+
+
+    /**
+     * Remove an attribute from the list.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void removeAttribute (int index)
+    {
+       if (index >= 0 && index < length) {
+           if (index < length - 1) {
+               System.arraycopy(data, (index+1)*5, data, index*5,
+                                (length-index-1)*5);
+           }
+           index = (length - 1) * 5;
+           data [index++] = null;
+           data [index++] = null;
+           data [index++] = null;
+           data [index++] = null;
+           data [index] = null;
+           length--;
+       } else {
+           badIndex(index);
+       }
+    }
+
+
+    /**
+     * Set the Namespace URI of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param uri The attribute's Namespace URI, or the empty
+     *        string for none.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setURI (int index, String uri)
+    {
+       if (index >= 0 && index < length) {
+           data[index*5] = uri;
+       } else {
+           badIndex(index);
+       }
+    }
+
+
+    /**
+     * Set the local name of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param localName The attribute's local name, or the empty
+     *        string for none.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setLocalName (int index, String localName)
+    {
+       if (index >= 0 && index < length) {
+           data[index*5+1] = localName;
+       } else {
+           badIndex(index);
+       }
+    }
+
+
+    /**
+     * Set the qualified name of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param qName The attribute's qualified name, or the empty
+     *        string for none.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setQName (int index, String qName)
+    {
+       if (index >= 0 && index < length) {
+           data[index*5+2] = qName;
+       } else {
+           badIndex(index);
+       }
+    }
+
+
+    /**
+     * Set the type of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param type The attribute's type.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setType (int index, String type)
+    {
+       if (index >= 0 && index < length) {
+           data[index*5+3] = type;
+       } else {
+           badIndex(index);
+       }
+    }
+
+
+    /**
+     * Set the value of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param value The attribute's value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setValue (int index, String value)
+    {
+       if (index >= 0 && index < length) {
+           data[index*5+4] = value;
+       } else {
+           badIndex(index);
+       }
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal methods.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Ensure the internal array's capacity.
+     *
+     * @param n The minimum number of attributes that the array must
+     *        be able to hold.
+     */
+    private void ensureCapacity (int n)    {
+        if (n <= 0) {
+            return;
+        }
+        int max;
+        if (data == null || data.length == 0) {
+            max = 25;
+        }
+        else if (data.length >= n * 5) {
+            return;
+        }
+        else {
+            max = data.length;
+        }
+        while (max < n * 5) {
+            max *= 2;
+        }
+
+        String newData[] = new String[max];
+        if (length > 0) {
+            System.arraycopy(data, 0, newData, 0, length*5);
+        }
+        data = newData;
+    }
+
+
+    /**
+     * Report a bad array index in a manipulator.
+     *
+     * @param index The index to report.
+     * @exception java.lang.ArrayIndexOutOfBoundsException Always.
+     */
+    private void badIndex (int index)
+       throws ArrayIndexOutOfBoundsException
+    {
+       String msg =
+           "Attempt to modify attribute at illegal index: " + index;
+       throw new ArrayIndexOutOfBoundsException(msg);
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    int length;
+    String data [];
+
+}
+
+// end of AttributesImpl.java
+
diff --git a/src/org/xml/sax/helpers/DefaultHandler.java b/src/org/xml/sax/helpers/DefaultHandler.java
new file mode 100644 (file)
index 0000000..83bde62
--- /dev/null
@@ -0,0 +1,484 @@
+// DefaultHandler.java - default implementation of the core handlers.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: DefaultHandler.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+
+/**
+ * Default base class for SAX2 event handlers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class is available as a convenience base class for SAX2
+ * applications: it provides default implementations for all of the
+ * callbacks in the four core SAX2 handler classes:</p>
+ *
+ * <ul>
+ * <li>{@link org.xml.sax.EntityResolver EntityResolver}</li>
+ * <li>{@link org.xml.sax.DTDHandler DTDHandler}</li>
+ * <li>{@link org.xml.sax.ContentHandler ContentHandler}</li>
+ * <li>{@link org.xml.sax.ErrorHandler ErrorHandler}</li>
+ * </ul>
+ *
+ * <p>Application writers can extend this class when they need to
+ * implement only part of an interface; parser writers can
+ * instantiate this class to provide default handlers when the
+ * application has not supplied its own.</p>
+ *
+ * <p>This class replaces the deprecated SAX1
+ * {@link org.xml.sax.HandlerBase HandlerBase} class.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson,
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.ContentHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public class DefaultHandler
+    implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler
+{
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the EntityResolver interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Resolve an external entity.
+     *
+     * <p>Always return null, so that the parser will use the system
+     * identifier provided in the XML document.  This method implements
+     * the SAX default behaviour: application writers can override it
+     * in a subclass to do special translations such as catalog lookups
+     * or URI redirection.</p>
+     *
+     * @param publicId The public identifer, or null if none is
+     *                 available.
+     * @param systemId The system identifier provided in the XML 
+     *                 document.
+     * @return The new input source, or null to require the
+     *         default behaviour.
+     * @exception java.io.IOException If there is an error setting
+     *            up the new input source.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.EntityResolver#resolveEntity
+     */
+    @Override
+               public InputSource resolveEntity (String publicId, String systemId)
+       throws IOException, SAXException
+    {
+       return null;
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of DTDHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a notation declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to keep track of the notations
+     * declared in a document.</p>
+     *
+     * @param name The notation name.
+     * @param publicId The notation public identifier, or null if not
+     *                 available.
+     * @param systemId The notation system identifier.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DTDHandler#notationDecl
+     */
+    @Override
+               public void notationDecl (String name, String publicId, String systemId)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of an unparsed entity declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to keep track of the unparsed entities
+     * declared in a document.</p>
+     *
+     * @param name The entity name.
+     * @param publicId The entity public identifier, or null if not
+     *                 available.
+     * @param systemId The entity system identifier.
+     * @param notationName The name of the associated notation.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    @Override
+               public void unparsedEntityDecl (String name, String publicId,
+                                   String systemId, String notationName)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of ContentHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive a Locator object for document events.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to store the locator for use
+     * with other document events.</p>
+     *
+     * @param locator A locator for all SAX document events.
+     * @see org.xml.sax.ContentHandler#setDocumentLocator
+     * @see org.xml.sax.Locator
+     */
+    @Override
+               public void setDocumentLocator (Locator locator)
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the beginning of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the beginning
+     * of a document (such as allocating the root node of a tree or
+     * creating an output file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#startDocument
+     */
+    @Override
+               public void startDocument ()
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end
+     * of a document (such as finalising a tree or closing an output
+     * file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#endDocument
+     */
+    @Override
+               public void endDocument ()
+       throws SAXException
+    {
+       // no op
+    }
+
+
+    /**
+     * Receive notification of the start of a Namespace mapping.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the start of
+     * each Namespace prefix scope (such as storing the prefix mapping).</p>
+     *
+     * @param prefix The Namespace prefix being declared.
+     * @param uri The Namespace URI mapped to the prefix.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#startPrefixMapping
+     */
+    @Override
+               public void startPrefixMapping (String prefix, String uri)
+       throws SAXException
+    {
+       // no op
+    }
+
+
+    /**
+     * Receive notification of the end of a Namespace mapping.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end of
+     * each prefix mapping.</p>
+     *
+     * @param prefix The Namespace prefix being declared.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#endPrefixMapping
+     */
+    @Override
+               public void endPrefixMapping (String prefix)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the start of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the start of
+     * each element (such as allocating a new tree node or writing
+     * output to a file).</p>
+     *
+     * @param uri The Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed.
+     * @param localName The local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed.
+     * @param qName The qualified name (with prefix), or the
+     *        empty string if qualified names are not available.
+     * @param attributes The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#startElement
+     */
+    @Override
+               public void startElement (String uri, String localName,
+                             String qName, Attributes attributes)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end of
+     * each element (such as finalising a tree node or writing
+     * output to a file).</p>
+     *
+     * @param uri The Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed.
+     * @param localName The local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed.
+     * @param qName The qualified name (with prefix), or the
+     *        empty string if qualified names are not available.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#endElement
+     */
+    @Override
+               public void endElement (String uri, String localName, String qName)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of character data inside an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of character data
+     * (such as adding the data to a node or buffer, or printing it to
+     * a file).</p>
+     *
+     * @param ch The characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#characters
+     */
+    @Override
+               public void characters (char ch[], int start, int length)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of ignorable
+     * whitespace (such as adding data to a node or buffer, or printing
+     * it to a file).</p>
+     *
+     * @param ch The whitespace characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#ignorableWhitespace
+     */
+    @Override
+               public void ignorableWhitespace (char ch[], int start, int length)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions for each
+     * processing instruction, such as setting status variables or
+     * invoking other methods.</p>
+     *
+     * @param target The processing instruction target.
+     * @param data The processing instruction data, or null if
+     *             none is supplied.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#processingInstruction
+     */
+    @Override
+               public void processingInstruction (String target, String data)
+       throws SAXException
+    {
+       // no op
+    }
+
+
+    /**
+     * Receive notification of a skipped entity.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions for each
+     * processing instruction, such as setting status variables or
+     * invoking other methods.</p>
+     *
+     * @param name The name of the skipped entity.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#processingInstruction
+     */
+    @Override
+               public void skippedEntity (String name)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the ErrorHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a parser warning.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each warning, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    @Override
+               public void warning (SAXParseException e)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Receive notification of a recoverable parser error.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each error, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    @Override
+               public void error (SAXParseException e)
+       throws SAXException
+    {
+       // no op
+    }
+    
+    
+    /**
+     * Report a fatal XML parsing error.
+     *
+     * <p>The default implementation throws a SAXParseException.
+     * Application writers may override this method in a subclass if
+     * they need to take specific actions for each fatal error (such as
+     * collecting all of the errors into a single report): in any case,
+     * the application must stop all regular processing when this
+     * method is invoked, since the document is no longer reliable, and
+     * the parser may no longer report parsing events.</p>
+     *
+     * @param e The error information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#fatalError
+     * @see org.xml.sax.SAXParseException
+     */
+    @Override
+               public void fatalError (SAXParseException e)
+       throws SAXException
+    {
+       throw e;
+    }
+    
+}
+
+// end of DefaultHandler.java
diff --git a/src/org/xml/sax/helpers/LocatorImpl.java b/src/org/xml/sax/helpers/LocatorImpl.java
new file mode 100644 (file)
index 0000000..90eab7e
--- /dev/null
@@ -0,0 +1,218 @@
+// SAX default implementation for Locator.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: LocatorImpl.java,v 1.6 2002/01/30 20:52:27 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import org.xml.sax.Locator;
+
+
+/**
+ * Provide an optional convenience implementation of Locator.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class is available mainly for application writers, who
+ * can use it to make a persistent snapshot of a locator at any
+ * point during a document parse:</p>
+ *
+ * <pre>
+ * Locator locator;
+ * Locator startloc;
+ *
+ * public void setLocator (Locator locator)
+ * {
+ *         // note the locator
+ *   this.locator = locator;
+ * }
+ *
+ * public void startDocument ()
+ * {
+ *         // save the location of the start of the document
+ *         // for future use.
+ *   Locator startloc = new LocatorImpl(locator);
+ * }
+ *</pre>
+ *
+ * <p>Normally, parser writers will not use this class, since it
+ * is more efficient to provide location information only when
+ * requested, rather than constantly updating a Locator object.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.Locator Locator
+ */
+public class LocatorImpl implements Locator
+{
+    
+    
+    /**
+     * Zero-argument constructor.
+     *
+     * <p>This will not normally be useful, since the main purpose
+     * of this class is to make a snapshot of an existing Locator.</p>
+     */
+    public LocatorImpl ()
+    {
+    }
+    
+    
+    /**
+     * Copy constructor.
+     *
+     * <p>Create a persistent copy of the current state of a locator.
+     * When the original locator changes, this copy will still keep
+     * the original values (and it can be used outside the scope of
+     * DocumentHandler methods).</p>
+     *
+     * @param locator The locator to copy.
+     */
+    public LocatorImpl (Locator locator)
+    {
+       setPublicId(locator.getPublicId());
+       setSystemId(locator.getSystemId());
+       setLineNumber(locator.getLineNumber());
+       setColumnNumber(locator.getColumnNumber());
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.Locator
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Return the saved public identifier.
+     *
+     * @return The public identifier as a string, or null if none
+     *         is available.
+     * @see org.xml.sax.Locator#getPublicId
+     * @see #setPublicId
+     */
+    @Override
+               public String getPublicId ()
+    {
+       return publicId;
+    }
+    
+    
+    /**
+     * Return the saved system identifier.
+     *
+     * @return The system identifier as a string, or null if none
+     *         is available.
+     * @see org.xml.sax.Locator#getSystemId
+     * @see #setSystemId
+     */
+    @Override
+               public String getSystemId ()
+    {
+       return systemId;
+    }
+    
+    
+    /**
+     * Return the saved line number (1-based).
+     *
+     * @return The line number as an integer, or -1 if none is available.
+     * @see org.xml.sax.Locator#getLineNumber
+     * @see #setLineNumber
+     */
+    @Override
+               public int getLineNumber ()
+    {
+       return lineNumber;
+    }
+    
+    
+    /**
+     * Return the saved column number (1-based).
+     *
+     * @return The column number as an integer, or -1 if none is available.
+     * @see org.xml.sax.Locator#getColumnNumber
+     * @see #setColumnNumber
+     */
+    @Override
+               public int getColumnNumber ()
+    {
+       return columnNumber;
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Setters for the properties (not in org.xml.sax.Locator)
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Set the public identifier for this locator.
+     *
+     * @param publicId The new public identifier, or null 
+     *        if none is available.
+     * @see #getPublicId
+     */
+    public void setPublicId (String publicId)
+    {
+       this.publicId = publicId;
+    }
+    
+    
+    /**
+     * Set the system identifier for this locator.
+     *
+     * @param systemId The new system identifier, or null 
+     *        if none is available.
+     * @see #getSystemId
+     */
+    public void setSystemId (String systemId)
+    {
+       this.systemId = systemId;
+    }
+    
+    
+    /**
+     * Set the line number for this locator (1-based).
+     *
+     * @param lineNumber The line number, or -1 if none is available.
+     * @see #getLineNumber
+     */
+    public void setLineNumber (int lineNumber)
+    {
+       this.lineNumber = lineNumber;
+    }
+    
+    
+    /**
+     * Set the column number for this locator (1-based).
+     *
+     * @param columnNumber The column number, or -1 if none is available.
+     * @see #getColumnNumber
+     */
+    public void setColumnNumber (int columnNumber)
+    {
+       this.columnNumber = columnNumber;
+    }
+    
+    
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+    
+    private String publicId;
+    private String systemId;
+    private int lineNumber;
+    private int columnNumber;
+    
+}
+
+// end of LocatorImpl.java
diff --git a/src/org/xml/sax/helpers/NamespaceSupport.java b/src/org/xml/sax/helpers/NamespaceSupport.java
new file mode 100644 (file)
index 0000000..3c15f5e
--- /dev/null
@@ -0,0 +1,835 @@
+// NamespaceSupport.java - generic Namespace support for SAX.
+// http://www.saxproject.org
+// Written by David Megginson
+// This class is in the Public Domain.  NO WARRANTY!
+// $Id: NamespaceSupport.java,v 1.15 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.util.EmptyStackException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+
+/**
+ * Encapsulate Namespace logic for use by applications using SAX,
+ * or internally by SAX drivers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class encapsulates the logic of Namespace processing: it
+ * tracks the declarations currently in force for each context and
+ * automatically processes qualified XML names into their Namespace
+ * parts; it can also be used in reverse for generating XML qnames
+ * from Namespaces.</p>
+ *
+ * <p>Namespace support objects are reusable, but the reset method
+ * must be invoked between each session.</p>
+ *
+ * <p>Here is a simple session:</p>
+ *
+ * <pre>
+ * String parts[] = new String[3];
+ * NamespaceSupport support = new NamespaceSupport();
+ *
+ * support.pushContext();
+ * support.declarePrefix("", "http://www.w3.org/1999/xhtml");
+ * support.declarePrefix("dc", "http://www.purl.org/dc#");
+ *
+ * parts = support.processName("p", parts, false);
+ * System.out.println("Namespace URI: " + parts[0]);
+ * System.out.println("Local name: " + parts[1]);
+ * System.out.println("Raw name: " + parts[2]);
+ *
+ * parts = support.processName("dc:title", parts, false);
+ * System.out.println("Namespace URI: " + parts[0]);
+ * System.out.println("Local name: " + parts[1]);
+ * System.out.println("Raw name: " + parts[2]);
+ *
+ * support.popContext();
+ * </pre>
+ *
+ * <p>Note that this class is optimized for the use case where most
+ * elements do not contain Namespace declarations: if the same
+ * prefix/URI mapping is repeated for each context (for example), this
+ * class will be somewhat less efficient.</p>
+ *
+ * <p>Although SAX drivers (parsers) may choose to use this class to
+ * implement namespace handling, they are not required to do so.
+ * Applications must track namespace information themselves if they
+ * want to use namespace information.
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public class NamespaceSupport
+{
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Constants.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * The XML Namespace URI as a constant.
+     * The value is <code>http://www.w3.org/XML/1998/namespace</code>
+     * as defined in the "Namespaces in XML" * recommendation.
+     *
+     * <p>This is the Namespace URI that is automatically mapped
+     * to the "xml" prefix.</p>
+     */
+    public final static String XMLNS =
+       "http://www.w3.org/XML/1998/namespace";
+
+
+    /**
+     * The namespace declaration URI as a constant.
+     * The value is <code>http://www.w3.org/xmlns/2000/</code>, as defined
+     * in a backwards-incompatible erratum to the "Namespaces in XML"
+     * recommendation.  Because that erratum postdated SAX2, SAX2 defaults 
+     * to the original recommendation, and does not normally use this URI.
+     * 
+     *
+     * <p>This is the Namespace URI that is optionally applied to
+     * <em>xmlns</em> and <em>xmlns:*</em> attributes, which are used to
+     * declare namespaces.  </p>
+     *
+     * @since SAX 2.1alpha
+     * @see #setNamespaceDeclUris
+     * @see #isNamespaceDeclUris
+     */
+    public final static String NSDECL =
+       "http://www.w3.org/xmlns/2000/";
+
+
+    /**
+     * An empty enumeration.
+     */
+    private final static Enumeration EMPTY_ENUMERATION =
+       new Vector().elements();
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Constructor.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Create a new Namespace support object.
+     */
+    public NamespaceSupport ()
+    {
+       reset();
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Context management.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Reset this Namespace support object for reuse.
+     *
+     * <p>It is necessary to invoke this method before reusing the
+     * Namespace support object for a new session.  If namespace
+     * declaration URIs are to be supported, that flag must also
+     * be set to a non-default value.
+     * </p>
+     *
+     * @see #setNamespaceDeclUris
+     */
+    public void reset ()
+    {
+       contexts = new Context[32];
+       namespaceDeclUris = false;
+       contextPos = 0;
+       contexts[contextPos] = currentContext = new Context();
+       currentContext.declarePrefix("xml", XMLNS);
+    }
+
+
+    /**
+     * Start a new Namespace context.
+     * The new context will automatically inherit
+     * the declarations of its parent context, but it will also keep
+     * track of which declarations were made within this context.
+     *
+     * <p>Event callback code should start a new context once per element.
+     * This means being ready to call this in either of two places.
+     * For elements that don't include namespace declarations, the
+     * <em>ContentHandler.startElement()</em> callback is the right place.
+     * For elements with such a declaration, it'd done in the first
+     * <em>ContentHandler.startPrefixMapping()</em> callback.
+     * A boolean flag can be used to
+     * track whether a context has been started yet.  When either of
+     * those methods is called, it checks the flag to see if a new context
+     * needs to be started.  If so, it starts the context and sets the
+     * flag.  After <em>ContentHandler.startElement()</em>
+     * does that, it always clears the flag.
+     *
+     * <p>Normally, SAX drivers would push a new context at the beginning
+     * of each XML element.  Then they perform a first pass over the
+     * attributes to process all namespace declarations, making
+     * <em>ContentHandler.startPrefixMapping()</em> callbacks.
+     * Then a second pass is made, to determine the namespace-qualified
+     * names for all attributes and for the element name.
+     * Finally all the information for the
+     * <em>ContentHandler.startElement()</em> callback is available,
+     * so it can then be made.
+     *
+     * <p>The Namespace support object always starts with a base context
+     * already in force: in this context, only the "xml" prefix is
+     * declared.</p>
+     *
+     * @see org.xml.sax.ContentHandler
+     * @see #popContext
+     */
+    public void pushContext ()
+    {
+       int max = contexts.length;
+
+       contexts [contextPos].declsOK = false;
+       contextPos++;
+
+                               // Extend the array if necessary
+       if (contextPos >= max) {
+           Context newContexts[] = new Context[max*2];
+           System.arraycopy(contexts, 0, newContexts, 0, max);
+           max *= 2;
+           contexts = newContexts;
+       }
+
+                               // Allocate the context if necessary.
+       currentContext = contexts[contextPos];
+       if (currentContext == null) {
+           contexts[contextPos] = currentContext = new Context();
+       }
+
+                               // Set the parent, if any.
+       if (contextPos > 0) {
+           currentContext.setParent(contexts[contextPos - 1]);
+       }
+    }
+
+
+    /**
+     * Revert to the previous Namespace context.
+     *
+     * <p>Normally, you should pop the context at the end of each
+     * XML element.  After popping the context, all Namespace prefix
+     * mappings that were previously in force are restored.</p>
+     *
+     * <p>You must not attempt to declare additional Namespace
+     * prefixes after popping a context, unless you push another
+     * context first.</p>
+     *
+     * @see #pushContext
+     */
+    public void popContext ()
+    {
+       contexts[contextPos].clear();
+       contextPos--;
+       if (contextPos < 0) {
+           throw new EmptyStackException();
+       }
+       currentContext = contexts[contextPos];
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Operations within a context.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Declare a Namespace prefix.  All prefixes must be declared
+     * before they are referenced.  For example, a SAX driver (parser)
+     * would scan an element's attributes
+     * in two passes:  first for namespace declarations,
+     * then a second pass using {@link #processName processName()} to
+     * interpret prefixes against (potentially redefined) prefixes.
+     *
+     * <p>This method declares a prefix in the current Namespace
+     * context; the prefix will remain in force until this context
+     * is popped, unless it is shadowed in a descendant context.</p>
+     *
+     * <p>To declare the default element Namespace, use the empty string as
+     * the prefix.</p>
+     *
+     * <p>Note that you must <em>not</em> declare a prefix after
+     * you've pushed and popped another Namespace context, or
+     * treated the declarations phase as complete by processing
+     * a prefixed name.</p>
+     *
+     * <p>Note that there is an asymmetry in this library: {@link
+     * #getPrefix getPrefix} will not return the "" prefix,
+     * even if you have declared a default element namespace.
+     * To check for a default namespace,
+     * you have to look it up explicitly using {@link #getURI getURI}.
+     * This asymmetry exists to make it easier to look up prefixes
+     * for attribute names, where the default prefix is not allowed.</p>
+     *
+     * @param prefix The prefix to declare, or the empty string to
+     * indicate the default element namespace.  This may never have
+     * the value "xml" or "xmlns".
+     * @param uri The Namespace URI to associate with the prefix.
+     * @return true if the prefix was legal, false otherwise
+     *
+     * @see #processName
+     * @see #getURI
+     * @see #getPrefix
+     */
+    public boolean declarePrefix (String prefix, String uri)
+    {
+       if (prefix.equals("xml") || prefix.equals("xmlns")) {
+           return false;
+       } else {
+           currentContext.declarePrefix(prefix, uri);
+           return true;
+       }
+    }
+
+
+    /**
+     * Process a raw XML qualified name, after all declarations in the
+     * current context have been handled by {@link #declarePrefix
+     * declarePrefix()}.
+     *
+     * <p>This method processes a raw XML qualified name in the
+     * current context by removing the prefix and looking it up among
+     * the prefixes currently declared.  The return value will be the
+     * array supplied by the caller, filled in as follows:</p>
+     *
+     * <dl>
+     * <dt>parts[0]</dt>
+     * <dd>The Namespace URI, or an empty string if none is
+     *  in use.</dd>
+     * <dt>parts[1]</dt>
+     * <dd>The local name (without prefix).</dd>
+     * <dt>parts[2]</dt>
+     * <dd>The original raw name.</dd>
+     * </dl>
+     *
+     * <p>All of the strings in the array will be internalized.  If
+     * the raw name has a prefix that has not been declared, then
+     * the return value will be null.</p>
+     *
+     * <p>Note that attribute names are processed differently than
+     * element names: an unprefixed element name will receive the
+     * default Namespace (if any), while an unprefixed attribute name
+     * will not.</p>
+     *
+     * @param qName The XML qualified name to be processed.
+     * @param parts An array supplied by the caller, capable of
+     *        holding at least three members.
+     * @param isAttribute A flag indicating whether this is an
+     *        attribute name (true) or an element name (false).
+     * @return The supplied array holding three internalized strings 
+     *        representing the Namespace URI (or empty string), the
+     *        local name, and the XML qualified name; or null if there
+     *        is an undeclared prefix.
+     * @see #declarePrefix
+     * @see java.lang.String#intern */
+    public String [] processName (String qName, String parts[],
+                                 boolean isAttribute)
+    {
+       String myParts[] = currentContext.processName(qName, isAttribute);
+       if (myParts == null) {
+           return null;
+       } else {
+           parts[0] = myParts[0];
+           parts[1] = myParts[1];
+           parts[2] = myParts[2];
+           return parts;
+       }
+    }
+
+
+    /**
+     * Look up a prefix and get the currently-mapped Namespace URI.
+     *
+     * <p>This method looks up the prefix in the current context.
+     * Use the empty string ("") for the default Namespace.</p>
+     *
+     * @param prefix The prefix to look up.
+     * @return The associated Namespace URI, or null if the prefix
+     *         is undeclared in this context.
+     * @see #getPrefix
+     * @see #getPrefixes
+     */
+    public String getURI (String prefix)
+    {
+       return currentContext.getURI(prefix);
+    }
+
+
+    /**
+     * Return an enumeration of all prefixes whose declarations are
+     * active in the current context.
+     * This includes declarations from parent contexts that have
+     * not been overridden.
+     *
+     * <p><strong>Note:</strong> if there is a default prefix, it will not be
+     * returned in this enumeration; check for the default prefix
+     * using the {@link #getURI getURI} with an argument of "".</p>
+     *
+     * @return An enumeration of prefixes (never empty).
+     * @see #getDeclaredPrefixes
+     * @see #getURI
+     */
+    public Enumeration getPrefixes ()
+    {
+       return currentContext.getPrefixes();
+    }
+
+
+    /**
+     * Return one of the prefixes mapped to a Namespace URI.
+     *
+     * <p>If more than one prefix is currently mapped to the same
+     * URI, this method will make an arbitrary selection; if you
+     * want all of the prefixes, use the {@link #getPrefixes}
+     * method instead.</p>
+     *
+     * <p><strong>Note:</strong> this will never return the empty (default) prefix;
+     * to check for a default prefix, use the {@link #getURI getURI}
+     * method with an argument of "".</p>
+     *
+     * @param uri the namespace URI
+     * @return one of the prefixes currently mapped to the URI supplied,
+     *         or null if none is mapped or if the URI is assigned to
+     *         the default namespace
+     * @see #getPrefixes(java.lang.String)
+     * @see #getURI
+     */
+    public String getPrefix (String uri)
+    {
+       return currentContext.getPrefix(uri);
+    }
+
+
+    /**
+     * Return an enumeration of all prefixes for a given URI whose
+     * declarations are active in the current context.
+     * This includes declarations from parent contexts that have
+     * not been overridden.
+     *
+     * <p>This method returns prefixes mapped to a specific Namespace
+     * URI.  The xml: prefix will be included.  If you want only one
+     * prefix that's mapped to the Namespace URI, and you don't care 
+     * which one you get, use the {@link #getPrefix getPrefix}
+     *  method instead.</p>
+     *
+     * <p><strong>Note:</strong> the empty (default) prefix is <em>never</em> included
+     * in this enumeration; to check for the presence of a default
+     * Namespace, use the {@link #getURI getURI} method with an
+     * argument of "".</p>
+     *
+     * @param uri The Namespace URI.
+     * @return An enumeration of prefixes (never empty).
+     * @see #getPrefix
+     * @see #getDeclaredPrefixes
+     * @see #getURI
+     */
+    public Enumeration getPrefixes (String uri)
+    {
+       Vector prefixes = new Vector();
+       Enumeration allPrefixes = getPrefixes();
+       while (allPrefixes.hasMoreElements()) {
+           String prefix = (String)allPrefixes.nextElement();
+           if (uri.equals(getURI(prefix))) {
+               prefixes.addElement(prefix);
+           }
+       }
+       return prefixes.elements();
+    }
+
+
+    /**
+     * Return an enumeration of all prefixes declared in this context.
+     *
+     * <p>The empty (default) prefix will be included in this 
+     * enumeration; note that this behaviour differs from that of
+     * {@link #getPrefix} and {@link #getPrefixes}.</p>
+     *
+     * @return An enumeration of all prefixes declared in this
+     *         context.
+     * @see #getPrefixes
+     * @see #getURI
+     */
+    public Enumeration getDeclaredPrefixes ()
+    {
+       return currentContext.getDeclaredPrefixes();
+    }
+
+    /**
+     * Controls whether namespace declaration attributes are placed
+     * into the {@link #NSDECL NSDECL} namespace
+     * by {@link #processName processName()}.  This may only be
+     * changed before any contexts have been pushed.
+     *
+     * @since SAX 2.1alpha
+     *
+     * @exception IllegalStateException when attempting to set this
+     * after any context has been pushed.
+     */
+    public void setNamespaceDeclUris (boolean value)
+    {
+       if (contextPos != 0)
+           throw new IllegalStateException ();
+       if (value == namespaceDeclUris)
+           return;
+       namespaceDeclUris = value;
+       if (value)
+           currentContext.declarePrefix ("xmlns", NSDECL);
+       else {
+           contexts[contextPos] = currentContext = new Context();
+           currentContext.declarePrefix("xml", XMLNS);
+       }
+    }
+
+    /**
+     * Returns true if namespace declaration attributes are placed into
+     * a namespace.  This behavior is not the default.
+     *
+     * @since SAX 2.1alpha
+     */
+    public boolean isNamespaceDeclUris ()
+       { return namespaceDeclUris; }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    private Context contexts[];
+    private Context currentContext;
+    private int contextPos;
+    private boolean namespaceDeclUris;
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal classes.
+    ////////////////////////////////////////////////////////////////////
+
+    /**
+     * Internal class for a single Namespace context.
+     *
+     * <p>This module caches and reuses Namespace contexts,
+     * so the number allocated
+     * will be equal to the element depth of the document, not to the total
+     * number of elements (i.e. 5-10 rather than tens of thousands).
+     * Also, data structures used to represent contexts are shared when
+     * possible (child contexts without declarations) to further reduce
+     * the amount of memory that's consumed.
+     * </p>
+     */
+    final class Context {
+
+       /**
+        * Create the root-level Namespace context.
+        */
+       Context ()
+       {
+           copyTables();
+       }
+       
+       
+       /**
+        * (Re)set the parent of this Namespace context.
+        * The context must either have been freshly constructed,
+        * or must have been cleared.
+        *
+        * @param context The parent Namespace context object.
+        */
+       void setParent (Context parent)
+       {
+           this.parent = parent;
+           declarations = null;
+           prefixTable = parent.prefixTable;
+           uriTable = parent.uriTable;
+           elementNameTable = parent.elementNameTable;
+           attributeNameTable = parent.attributeNameTable;
+           defaultNS = parent.defaultNS;
+           declSeen = false;
+           declsOK = true;
+       }
+
+       /**
+        * Makes associated state become collectible,
+        * invalidating this context.
+        * {@link #setParent} must be called before
+        * this context may be used again.
+        */
+       void clear ()
+       {
+           parent = null;
+           prefixTable = null;
+           uriTable = null;
+           elementNameTable = null;
+           attributeNameTable = null;
+           defaultNS = null;
+       }
+       
+       
+       /**
+        * Declare a Namespace prefix for this context.
+        *
+        * @param prefix The prefix to declare.
+        * @param uri The associated Namespace URI.
+        * @see org.xml.sax.helpers.NamespaceSupport#declarePrefix
+        */
+       void declarePrefix (String prefix, String uri)
+       {
+                               // Lazy processing...
+           if (!declsOK)
+               throw new IllegalStateException (
+                   "can't declare any more prefixes in this context");
+           if (!declSeen) {
+               copyTables();
+           }
+           if (declarations == null) {
+               declarations = new Vector();
+           }
+           
+           prefix = prefix.intern();
+           uri = uri.intern();
+           if ("".equals(prefix)) {
+               if ("".equals(uri)) {
+                   defaultNS = null;
+               } else {
+                   defaultNS = uri;
+               }
+           } else {
+               prefixTable.put(prefix, uri);
+               uriTable.put(uri, prefix); // may wipe out another prefix
+           }
+           declarations.addElement(prefix);
+       }
+
+
+       /**
+        * Process an XML qualified name in this context.
+        *
+        * @param qName The XML qualified name.
+        * @param isAttribute true if this is an attribute name.
+        * @return An array of three strings containing the
+        *         URI part (or empty string), the local part,
+        *         and the raw name, all internalized, or null
+        *         if there is an undeclared prefix.
+        * @see org.xml.sax.helpers.NamespaceSupport#processName
+        */
+       String [] processName (String qName, boolean isAttribute)
+       {
+           String name[];
+           Hashtable table;
+           
+                               // detect errors in call sequence
+           declsOK = false;
+
+                               // Select the appropriate table.
+           if (isAttribute) {
+               table = attributeNameTable;
+           } else {
+               table = elementNameTable;
+           }
+           
+                               // Start by looking in the cache, and
+                               // return immediately if the name
+                               // is already known in this content
+           name = (String[])table.get(qName);
+           if (name != null) {
+               return name;
+           }
+           
+                               // We haven't seen this name in this
+                               // context before.  Maybe in the parent
+                               // context, but we can't assume prefix
+                               // bindings are the same.
+           name = new String[3];
+           name[2] = qName.intern();
+           int index = qName.indexOf(':');
+           
+           
+                               // No prefix.
+           if (index == -1) {
+               if (isAttribute) {
+                   if (qName == "xmlns" && namespaceDeclUris)
+                       name[0] = NSDECL;
+                   else
+                       name[0] = "";
+               } else if (defaultNS == null) {
+                   name[0] = "";
+               } else {
+                   name[0] = defaultNS;
+               }
+               name[1] = name[2];
+           }
+           
+                               // Prefix
+           else {
+               String prefix = qName.substring(0, index);
+               String local = qName.substring(index+1);
+               String uri;
+               if ("".equals(prefix)) {
+                   uri = defaultNS;
+               } else {
+                   uri = (String)prefixTable.get(prefix);
+               }
+               if (uri == null
+                       || (!isAttribute && "xmlns".equals (prefix))) {
+                   return null;
+               }
+               name[0] = uri;
+               name[1] = local.intern();
+           }
+           
+                               // Save in the cache for future use.
+                               // (Could be shared with parent context...)
+           table.put(name[2], name);
+           return name;
+       }
+       
+
+       /**
+        * Look up the URI associated with a prefix in this context.
+        *
+        * @param prefix The prefix to look up.
+        * @return The associated Namespace URI, or null if none is
+        *         declared.    
+        * @see org.xml.sax.helpers.NamespaceSupport#getURI
+        */
+       String getURI (String prefix)
+       {
+           if ("".equals(prefix)) {
+               return defaultNS;
+           } else if (prefixTable == null) {
+               return null;
+           } else {
+               return (String)prefixTable.get(prefix);
+           }
+       }
+
+
+       /**
+        * Look up one of the prefixes associated with a URI in this context.
+        *
+        * <p>Since many prefixes may be mapped to the same URI,
+        * the return value may be unreliable.</p>
+        *
+        * @param uri The URI to look up.
+        * @return The associated prefix, or null if none is declared.
+        * @see org.xml.sax.helpers.NamespaceSupport#getPrefix
+        */
+       String getPrefix (String uri)
+       {
+           if (uriTable == null) {
+               return null;
+           } else {
+               return (String)uriTable.get(uri);
+           }
+       }
+       
+       
+       /**
+        * Return an enumeration of prefixes declared in this context.
+        *
+        * @return An enumeration of prefixes (possibly empty).
+        * @see org.xml.sax.helpers.NamespaceSupport#getDeclaredPrefixes
+        */
+       Enumeration getDeclaredPrefixes ()
+       {
+           if (declarations == null) {
+               return EMPTY_ENUMERATION;
+           } else {
+               return declarations.elements();
+           }
+       }
+       
+       
+       /**
+        * Return an enumeration of all prefixes currently in force.
+        *
+        * <p>The default prefix, if in force, is <em>not</em>
+        * returned, and will have to be checked for separately.</p>
+        *
+        * @return An enumeration of prefixes (never empty).
+        * @see org.xml.sax.helpers.NamespaceSupport#getPrefixes
+        */
+       Enumeration getPrefixes ()
+       {
+           if (prefixTable == null) {
+               return EMPTY_ENUMERATION;
+           } else {
+               return prefixTable.keys();
+           }
+       }
+       
+       
+\f
+       ////////////////////////////////////////////////////////////////
+       // Internal methods.
+       ////////////////////////////////////////////////////////////////
+
+
+       /**
+        * Copy on write for the internal tables in this context.
+        *
+        * <p>This class is optimized for the normal case where most
+        * elements do not contain Namespace declarations.</p>
+        */     
+       private void copyTables ()
+       {
+           if (prefixTable != null) {
+               prefixTable = (Hashtable)prefixTable.clone();
+           } else {
+               prefixTable = new Hashtable();
+           }
+           if (uriTable != null) {
+               uriTable = (Hashtable)uriTable.clone();
+           } else {
+               uriTable = new Hashtable();
+           }
+           elementNameTable = new Hashtable();
+           attributeNameTable = new Hashtable();
+           declSeen = true;
+       }
+
+
+\f
+       ////////////////////////////////////////////////////////////////
+       // Protected state.
+       ////////////////////////////////////////////////////////////////
+       
+       Hashtable prefixTable;
+       Hashtable uriTable;
+       Hashtable elementNameTable;
+       Hashtable attributeNameTable;
+       String defaultNS = null;
+       boolean declsOK = true;
+       
+
+\f
+       ////////////////////////////////////////////////////////////////
+       // Internal state.
+       ////////////////////////////////////////////////////////////////
+       
+       private Vector declarations = null;
+       private boolean declSeen = false;
+       private Context parent = null;
+    }
+}
+
+// end of NamespaceSupport.java
diff --git a/src/org/xml/sax/helpers/NewInstance.java b/src/org/xml/sax/helpers/NewInstance.java
new file mode 100644 (file)
index 0000000..6fc34d6
--- /dev/null
@@ -0,0 +1,79 @@
+// NewInstance.java - create a new instance of a class by name.
+// http://www.saxproject.org
+// Written by Edwin Goei, edwingo@apache.org
+// and by David Brownell, dbrownell@users.sourceforge.net
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: NewInstance.java,v 1.4 2002/01/30 20:52:27 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Create a new instance of a class by name.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class contains a static method for creating an instance of a
+ * class from an explicit class name.  It tries to use the thread's context
+ * ClassLoader if possible and falls back to using
+ * Class.forName(String).</p>
+ *
+ * <p>This code is designed to compile and run on JDK version 1.1 and later
+ * including versions of Java 2.</p>
+ *
+ * @author Edwin Goei, David Brownell
+ * @version 2.0.1 (sax2r2)
+ */
+class NewInstance {
+
+    /**
+     * Creates a new instance of the specified class name
+     *
+     * Package private so this code is not exposed at the API level.
+     */
+    static Object newInstance (ClassLoader classLoader, String className)
+        throws ClassNotFoundException, IllegalAccessException,
+            InstantiationException
+    {
+        Class driverClass;
+        if (classLoader == null) {
+            driverClass = Class.forName(className);
+        } else {
+            driverClass = classLoader.loadClass(className);
+        }
+        return driverClass.newInstance();
+    }
+
+    /**
+     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
+     * the context ClassLoader.
+     */           
+    static ClassLoader getClassLoader ()
+    {
+        Method m = null;
+
+        try {
+            m = Thread.class.getMethod("getContextClassLoader", null);
+        } catch (NoSuchMethodException e) {
+            // Assume that we are running JDK 1.1, use the current ClassLoader
+            return NewInstance.class.getClassLoader();
+        }
+
+        try {
+            return (ClassLoader) m.invoke(Thread.currentThread(), null);
+        } catch (IllegalAccessException e) {
+            // assert(false)
+            throw new UnknownError(e.getMessage());
+        } catch (InvocationTargetException e) {
+            // assert(e.getTargetException() instanceof SecurityException)
+            throw new UnknownError(e.getMessage());
+        }
+    }
+}
diff --git a/src/org/xml/sax/helpers/ParserAdapter.java b/src/org/xml/sax/helpers/ParserAdapter.java
new file mode 100644 (file)
index 0000000..b723219
--- /dev/null
@@ -0,0 +1,1080 @@
+// ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: ParserAdapter.java,v 1.16 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.xml.sax.Parser;     // deprecated
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.AttributeList; // deprecated
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler; // deprecated
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+
+/**
+ * Adapt a SAX1 Parser as a SAX2 XMLReader.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser}
+ * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader},
+ * with feature, property, and Namespace support.  Note
+ * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity
+ * skippedEntity} events, since SAX1 does not make that information available.</p>
+ *
+ * <p>This adapter does not test for duplicate Namespace-qualified
+ * attribute names.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.helpers.XMLReaderAdapter
+ * @see org.xml.sax.XMLReader
+ * @see org.xml.sax.Parser
+ */
+public class ParserAdapter implements XMLReader, DocumentHandler
+{
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Constructors.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct a new parser adapter.
+     *
+     * <p>Use the "org.xml.sax.parser" property to locate the
+     * embedded SAX1 driver.</p>
+     *
+     * @exception SAXException If the embedded driver
+     *            cannot be instantiated or if the
+     *            org.xml.sax.parser property is not specified.
+     */
+    public ParserAdapter ()
+      throws SAXException
+    {
+       super();
+
+       String driver = System.getProperty("org.xml.sax.parser");
+
+       try {
+           setup(ParserFactory.makeParser());
+       } catch (ClassNotFoundException e1) {
+           throw new
+               SAXException("Cannot find SAX1 driver class " +
+                            driver, e1);
+       } catch (IllegalAccessException e2) {
+           throw new
+               SAXException("SAX1 driver class " +
+                            driver +
+                            " found but cannot be loaded", e2);
+       } catch (InstantiationException e3) {
+           throw new
+               SAXException("SAX1 driver class " +
+                            driver +
+                            " loaded but cannot be instantiated", e3);
+       } catch (ClassCastException e4) {
+           throw new
+               SAXException("SAX1 driver class " +
+                            driver +
+                            " does not implement org.xml.sax.Parser");
+       } catch (NullPointerException e5) {
+           throw new 
+               SAXException("System property org.xml.sax.parser not specified");
+       }
+    }
+
+
+    /**
+     * Construct a new parser adapter.
+     *
+     * <p>Note that the embedded parser cannot be changed once the
+     * adapter is created; to embed a different parser, allocate
+     * a new ParserAdapter.</p>
+     *
+     * @param parser The SAX1 parser to embed.
+     * @exception java.lang.NullPointerException If the parser parameter
+     *            is null.
+     */
+    public ParserAdapter (Parser parser)
+    {
+       super();
+       setup(parser);
+    }
+
+
+    /**
+     * Internal setup method.
+     *
+     * @param parser The embedded parser.
+     * @exception java.lang.NullPointerException If the parser parameter
+     *            is null.
+     */
+    private void setup (Parser parser)
+    {
+       if (parser == null) {
+           throw new
+               NullPointerException("Parser argument must not be null");
+       }
+       this.parser = parser;
+       atts = new AttributesImpl();
+       nsSupport = new NamespaceSupport();
+       attAdapter = new AttributeListAdapter();
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.XMLReader.
+    ////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Internal constants for the sake of convenience.
+    //
+    private final static String FEATURES = "http://xml.org/sax/features/";
+    private final static String NAMESPACES = FEATURES + "namespaces";
+    private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes";
+    private final static String XMLNS_URIs = FEATURES + "xmlns-uris";
+
+
+    /**
+     * Set a feature flag for the parser.
+     *
+     * <p>The only features recognized are namespaces and 
+     * namespace-prefixes.</p>
+     *
+     * @param name The feature name, as a complete URI.
+     * @param value The requested feature value.
+     * @exception SAXNotRecognizedException If the feature
+     *            can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the feature
+     *            can't be assigned that value.
+     * @see org.xml.sax.XMLReader#setFeature
+     */
+    @Override
+               public void setFeature (String name, boolean value)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       if (name.equals(NAMESPACES)) {
+           checkNotParsing("feature", name);
+           namespaces = value;
+           if (!namespaces && !prefixes) {
+               prefixes = true;
+           }
+       } else if (name.equals(NAMESPACE_PREFIXES)) {
+           checkNotParsing("feature", name);
+           prefixes = value;
+           if (!prefixes && !namespaces) {
+               namespaces = true;
+           }
+       } else if (name.equals(XMLNS_URIs)) {
+           checkNotParsing("feature", name);
+           uris = value;
+       } else {
+           throw new SAXNotRecognizedException("Feature: " + name);
+       }
+    }
+
+
+    /**
+     * Check a parser feature flag.
+     *
+     * <p>The only features recognized are namespaces and 
+     * namespace-prefixes.</p>
+     *
+     * @param name The feature name, as a complete URI.
+     * @return The current feature value.
+     * @exception SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the
+     *            feature is not currently readable.
+     * @see org.xml.sax.XMLReader#setFeature
+     */
+    @Override
+               public boolean getFeature (String name)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       if (name.equals(NAMESPACES)) {
+           return namespaces;
+       } else if (name.equals(NAMESPACE_PREFIXES)) {
+           return prefixes;
+       } else if (name.equals(XMLNS_URIs)) {
+           return uris;
+       } else {
+           throw new SAXNotRecognizedException("Feature: " + name);
+       }
+    }
+
+
+    /**
+     * Set a parser property.
+     *
+     * <p>No properties are currently recognized.</p>
+     *
+     * @param name The property name.
+     * @param value The property value.
+     * @exception SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the property
+     *            can't be assigned that value.
+     * @see org.xml.sax.XMLReader#setProperty
+     */
+    @Override
+               public void setProperty (String name, Object value)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       throw new SAXNotRecognizedException("Property: " + name);
+    }
+
+
+    /**
+     * Get a parser property.
+     *
+     * <p>No properties are currently recognized.</p>
+     *
+     * @param name The property name.
+     * @return The property value.
+     * @exception SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the property
+     *            value is not currently readable.
+     * @see org.xml.sax.XMLReader#getProperty
+     */
+    @Override
+               public Object getProperty (String name)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       throw new SAXNotRecognizedException("Property: " + name);
+    }
+
+
+    /**
+     * Set the entity resolver.
+     *
+     * @param resolver The new entity resolver.
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    @Override
+               public void setEntityResolver (EntityResolver resolver)
+    {
+       entityResolver = resolver;
+    }
+
+
+    /**
+     * Return the current entity resolver.
+     *
+     * @return The current entity resolver, or null if none was supplied.
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    @Override
+               public EntityResolver getEntityResolver ()
+    {
+       return entityResolver;
+    }
+
+
+    /**
+     * Set the DTD handler.
+     *
+     * @param handler the new DTD handler
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    @Override
+               public void setDTDHandler (DTDHandler handler)
+    {
+       dtdHandler = handler;
+    }
+
+
+    /**
+     * Return the current DTD handler.
+     *
+     * @return the current DTD handler, or null if none was supplied
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    @Override
+               public DTDHandler getDTDHandler ()
+    {
+       return dtdHandler;
+    }
+
+
+    /**
+     * Set the content handler.
+     *
+     * @param handler the new content handler
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    @Override
+               public void setContentHandler (ContentHandler handler)
+    {
+       contentHandler = handler;
+    }
+
+
+    /**
+     * Return the current content handler.
+     *
+     * @return The current content handler, or null if none was supplied.
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    @Override
+               public ContentHandler getContentHandler ()
+    {
+       return contentHandler;
+    }
+
+
+    /**
+     * Set the error handler.
+     *
+     * @param handler The new error handler.
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    @Override
+               public void setErrorHandler (ErrorHandler handler)
+    {
+       errorHandler = handler;
+    }
+
+
+    /**
+     * Return the current error handler.
+     *
+     * @return The current error handler, or null if none was supplied.
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    @Override
+               public ErrorHandler getErrorHandler ()
+    {
+       return errorHandler;
+    }
+
+
+    /**
+     * Parse an XML document.
+     *
+     * @param systemId The absolute URL of the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(org.xml.sax.InputSource)
+     * @see org.xml.sax.Parser#parse(java.lang.String)
+     */
+    @Override
+               public void parse (String systemId)
+       throws IOException, SAXException
+    {
+       parse(new InputSource(systemId));
+    }
+
+
+    /**
+     * Parse an XML document.
+     *
+     * @param input An input source for the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(java.lang.String)
+     * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
+     */
+    @Override
+               public void parse (InputSource input)
+       throws IOException, SAXException
+    {
+       if (parsing) {
+           throw new SAXException("Parser is already in use");
+       }
+       setupParser();
+       parsing = true;
+       try {
+           parser.parse(input);
+       } finally {
+           parsing = false;
+       }
+       parsing = false;
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.DocumentHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 document locator event.
+     *
+     * @param locator A document locator.
+     * @see org.xml.sax.ContentHandler#setDocumentLocator
+     */
+    @Override
+               public void setDocumentLocator (Locator locator)
+    {
+       this.locator = locator;
+       if (contentHandler != null) {
+           contentHandler.setDocumentLocator(locator);
+       }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 start document event.
+     *
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#startDocument
+     */
+    @Override
+               public void startDocument ()
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.startDocument();
+       }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 end document event.
+     *
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#endDocument
+     */
+    @Override
+               public void endDocument ()
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.endDocument();
+       }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 startElement event.
+     *
+     * <p>If necessary, perform Namespace processing.</p>
+     *
+     * @param qName The qualified (prefixed) name.
+     * @param qAtts The XML attribute list (with qnames).
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     */
+    @Override
+               public void startElement (String qName, AttributeList qAtts)
+       throws SAXException
+    {
+                               // These are exceptions from the
+                               // first pass; they should be
+                               // ignored if there's a second pass,
+                               // but reported otherwise.
+       Vector exceptions = null;
+
+                               // If we're not doing Namespace
+                               // processing, dispatch this quickly.
+       if (!namespaces) {
+           if (contentHandler != null) {
+               attAdapter.setAttributeList(qAtts);
+               contentHandler.startElement("", "", qName.intern(),
+                                           attAdapter);
+           }
+           return;
+       }
+
+
+                               // OK, we're doing Namespace processing.
+       nsSupport.pushContext();
+       int length = qAtts.getLength();
+       
+                               // First pass:  handle NS decls
+       for (int i = 0; i < length; i++) {
+           String attQName = qAtts.getName(i);
+
+           if (!attQName.startsWith("xmlns"))
+               continue;
+                               // Could be a declaration...
+           String prefix;
+           int n = attQName.indexOf(':');
+
+                               // xmlns=...
+           if (n == -1 && attQName.length () == 5) {
+               prefix = "";
+           } else if (n != 5) {
+               // XML namespaces spec doesn't discuss "xmlnsf:oo"
+               // (and similarly named) attributes ... at most, warn
+               continue;
+           } else              // xmlns:foo=...
+               prefix = attQName.substring(n+1);
+
+           String value = qAtts.getValue(i);
+           if (!nsSupport.declarePrefix(prefix, value)) {
+               reportError("Illegal Namespace prefix: " + prefix);
+               continue;
+           }
+           if (contentHandler != null)
+               contentHandler.startPrefixMapping(prefix, value);
+       }
+       
+                               // Second pass: copy all relevant
+                               // attributes into the SAX2 AttributeList
+                               // using updated prefix bindings
+       atts.clear();
+       for (int i = 0; i < length; i++) {
+           String attQName = qAtts.getName(i);
+           String type = qAtts.getType(i);
+           String value = qAtts.getValue(i);
+
+                               // Declaration?
+           if (attQName.startsWith("xmlns")) {
+               String prefix;
+               int n = attQName.indexOf(':');
+
+               if (n == -1 && attQName.length () == 5) {
+                   prefix = "";
+               } else if (n != 5) {
+                   // XML namespaces spec doesn't discuss "xmlnsf:oo"
+                   // (and similarly named) attributes ... ignore
+                   prefix = null;
+               } else {
+                   prefix = attQName.substring(6);
+               }
+                               // Yes, decl:  report or prune
+               if (prefix != null) {
+                   if (prefixes) {
+                       if (uris)
+                           // note funky case:  localname can be null
+                           // when declaring the default prefix, and
+                           // yet the uri isn't null.
+                           atts.addAttribute (nsSupport.XMLNS, prefix,
+                                   attQName.intern(), type, value);
+                       else
+                           atts.addAttribute ("", "",
+                                   attQName.intern(), type, value);
+                   }
+                   continue;
+               }
+           } 
+
+                               // Not a declaration -- report
+           try {
+               String attName[] = processName(attQName, true, true);
+               atts.addAttribute(attName[0], attName[1], attName[2],
+                                 type, value);
+           } catch (SAXException e) {
+               if (exceptions == null)
+                   exceptions = new Vector();
+               exceptions.addElement(e);
+               atts.addAttribute("", attQName, attQName, type, value);
+           }
+       }
+       
+       // now handle the deferred exception reports
+       if (exceptions != null && errorHandler != null) {
+           for (int i = 0; i < exceptions.size(); i++)
+               errorHandler.error((SAXParseException)
+                               (exceptions.elementAt(i)));
+       }
+
+                               // OK, finally report the event.
+       if (contentHandler != null) {
+           String name[] = processName(qName, false, false);
+           contentHandler.startElement(name[0], name[1], name[2], atts);
+       }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 end element event.
+     *
+     * @param qName The qualified (prefixed) name.
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#endElement
+     */
+    @Override
+               public void endElement (String qName)
+       throws SAXException
+    {
+                               // If we're not doing Namespace
+                               // processing, dispatch this quickly.
+       if (!namespaces) {
+           if (contentHandler != null) {
+               contentHandler.endElement("", "", qName.intern());
+           }
+           return;
+       }
+
+                               // Split the name.
+       String names[] = processName(qName, false, false);
+       if (contentHandler != null) {
+           contentHandler.endElement(names[0], names[1], names[2]);
+           Enumeration prefixes = nsSupport.getDeclaredPrefixes();
+           while (prefixes.hasMoreElements()) {
+               String prefix = (String)prefixes.nextElement();
+               contentHandler.endPrefixMapping(prefix);
+           }
+       }
+       nsSupport.popContext();
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 characters event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#characters
+     */
+    @Override
+               public void characters (char ch[], int start, int length)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.characters(ch, start, length);
+       }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 ignorable whitespace event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#ignorableWhitespace
+     */
+    @Override
+               public void ignorableWhitespace (char ch[], int start, int length)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.ignorableWhitespace(ch, start, length);
+       }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 processing instruction event.
+     *
+     * @param target The processing instruction target.
+     * @param data The remainder of the processing instruction
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#processingInstruction
+     */
+    @Override
+               public void processingInstruction (String target, String data)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.processingInstruction(target, data);
+       }
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal utility methods.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initialize the parser before each run.
+     */
+    private void setupParser ()
+    {
+       // catch an illegal "nonsense" state.
+       if (!prefixes && !namespaces)
+           throw new IllegalStateException ();
+
+       nsSupport.reset();
+       if (uris)
+           nsSupport.setNamespaceDeclUris (true);
+
+       if (entityResolver != null) {
+           parser.setEntityResolver(entityResolver);
+       }
+       if (dtdHandler != null) {
+           parser.setDTDHandler(dtdHandler);
+       }
+       if (errorHandler != null) {
+           parser.setErrorHandler(errorHandler);
+       }
+       parser.setDocumentHandler(this);
+       locator = null;
+    }
+
+
+    /**
+     * Process a qualified (prefixed) name.
+     *
+     * <p>If the name has an undeclared prefix, use only the qname
+     * and make an ErrorHandler.error callback in case the app is
+     * interested.</p>
+     *
+     * @param qName The qualified (prefixed) name.
+     * @param isAttribute true if this is an attribute name.
+     * @return The name split into three parts.
+     * @exception SAXException The client may throw
+     *            an exception if there is an error callback.
+     */
+    private String [] processName (String qName, boolean isAttribute,
+                                  boolean useException)
+       throws SAXException
+    {
+       String parts[] = nsSupport.processName(qName, nameParts,
+                                              isAttribute);
+       if (parts == null) {
+           if (useException)
+               throw makeException("Undeclared prefix: " + qName);
+           reportError("Undeclared prefix: " + qName);
+           parts = new String[3];
+           parts[0] = parts[1] = "";
+           parts[2] = qName.intern();
+       }
+       return parts;
+    }
+
+
+    /**
+     * Report a non-fatal error.
+     *
+     * @param message The error message.
+     * @exception SAXException The client may throw
+     *            an exception.
+     */
+    void reportError (String message)
+       throws SAXException
+    {
+       if (errorHandler != null)
+           errorHandler.error(makeException(message));
+    }
+
+    
+    /**
+     * Construct an exception for the current context.
+     *
+     * @param message The error message.
+     */
+    private SAXParseException makeException (String message)
+    {
+       if (locator != null) {
+           return new SAXParseException(message, locator);
+       } else {
+           return new SAXParseException(message, null, null, -1, -1);
+       }
+    }
+
+
+    /**
+     * Throw an exception if we are parsing.
+     *
+     * <p>Use this method to detect illegal feature or
+     * property changes.</p>
+     *
+     * @param type The type of thing (feature or property).
+     * @param name The feature or property name.
+     * @exception SAXNotSupportedException If a
+     *            document is currently being parsed.
+     */
+    private void checkNotParsing (String type, String name)
+       throws SAXNotSupportedException
+    {
+       if (parsing) {
+           throw new SAXNotSupportedException("Cannot change " +
+                                              type + ' ' +
+                                              name + " while parsing");
+                                              
+       }
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    private NamespaceSupport nsSupport;
+    private AttributeListAdapter attAdapter;
+
+    private boolean parsing = false;
+    private String nameParts[] = new String[3];
+
+    private Parser parser = null;
+
+    private AttributesImpl atts = null;
+
+                               // Features
+    private boolean namespaces = true;
+    private boolean prefixes = false;
+    private boolean uris = false;
+
+                               // Properties
+
+                               // Handlers
+    Locator locator;
+
+    EntityResolver entityResolver = null;
+    DTDHandler dtdHandler = null;
+    ContentHandler contentHandler = null;
+    ErrorHandler errorHandler = null;
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Inner class to wrap an AttributeList when not doing NS proc.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Adapt a SAX1 AttributeList as a SAX2 Attributes object.
+     *
+     * <p>This class is in the Public Domain, and comes with NO
+     * WARRANTY of any kind.</p>
+     *
+     * <p>This wrapper class is used only when Namespace support
+     * is disabled -- it provides pretty much a direct mapping
+     * from SAX1 to SAX2, except that names and types are 
+     * interned whenever requested.</p>
+     */
+    final class AttributeListAdapter implements Attributes
+    {
+
+       /**
+        * Construct a new adapter.
+        */
+       AttributeListAdapter ()
+       {
+       }
+
+
+       /**
+        * Set the embedded AttributeList.
+        *
+        * <p>This method must be invoked before any of the others
+        * can be used.</p>
+        *
+        * @param The SAX1 attribute list (with qnames).
+        */
+       void setAttributeList (AttributeList qAtts)
+       {
+           this.qAtts = qAtts;
+       }
+
+
+       /**
+        * Return the length of the attribute list.
+        *
+        * @return The number of attributes in the list.
+        * @see org.xml.sax.Attributes#getLength
+        */
+       @Override
+       public int getLength ()
+       {
+           return qAtts.getLength();
+       }
+
+
+       /**
+        * Return the Namespace URI of the specified attribute.
+        *
+        * @param The attribute's index.
+        * @return Always the empty string.
+        * @see org.xml.sax.Attributes#getURI
+        */
+       @Override
+       public String getURI (int i)
+       {
+           return "";
+       }
+
+
+       /**
+        * Return the local name of the specified attribute.
+        *
+        * @param The attribute's index.
+        * @return Always the empty string.
+        * @see org.xml.sax.Attributes#getLocalName
+        */
+       @Override
+       public String getLocalName (int i)
+       {
+           return "";
+       }
+
+
+       /**
+        * Return the qualified (prefixed) name of the specified attribute.
+        *
+        * @param The attribute's index.
+        * @return The attribute's qualified name, internalized.
+        */
+       @Override
+       public String getQName (int i)
+       {
+           return qAtts.getName(i).intern();
+       }
+
+
+       /**
+        * Return the type of the specified attribute.
+        *
+        * @param The attribute's index.
+        * @return The attribute's type as an internalized string.
+        */
+       @Override
+       public String getType (int i)
+       {
+           return qAtts.getType(i).intern();
+       }
+
+
+       /**
+        * Return the value of the specified attribute.
+        *
+        * @param The attribute's index.
+        * @return The attribute's value.
+        */
+       @Override
+       public String getValue (int i)
+       {
+           return qAtts.getValue(i);
+       }
+
+
+       /**
+        * Look up an attribute index by Namespace name.
+        *
+        * @param uri The Namespace URI or the empty string.
+        * @param localName The local name.
+        * @return The attributes index, or -1 if none was found.
+        * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
+        */
+       @Override
+       public int getIndex (String uri, String localName)
+       {
+           return -1;
+       }
+
+
+       /**
+        * Look up an attribute index by qualified (prefixed) name.
+        *
+        * @param qName The qualified name.
+        * @return The attributes index, or -1 if none was found.
+        * @see org.xml.sax.Attributes#getIndex(java.lang.String)
+        */
+       @Override
+       public int getIndex (String qName)
+       {
+           int max = atts.getLength();
+           for (int i = 0; i < max; i++) {
+               if (qAtts.getName(i).equals(qName)) {
+                   return i;
+               }
+           }
+           return -1;
+       }
+
+
+       /**
+        * Look up the type of an attribute by Namespace name.
+        *
+        * @param uri The Namespace URI
+        * @param localName The local name.
+        * @return The attribute's type as an internalized string.
+        */
+       @Override
+       public String getType (String uri, String localName)
+       {
+           return null;
+       }
+
+
+       /**
+        * Look up the type of an attribute by qualified (prefixed) name.
+        *
+        * @param qName The qualified name.
+        * @return The attribute's type as an internalized string.
+        */
+       @Override
+       public String getType (String qName)
+       {
+           return qAtts.getType(qName).intern();
+       }
+
+
+       /**
+        * Look up the value of an attribute by Namespace name.
+        *
+        * @param uri The Namespace URI
+        * @param localName The local name.
+        * @return The attribute's value.
+        */
+       @Override
+       public String getValue (String uri, String localName)
+       {
+           return null;
+       }
+
+
+       /**
+        * Look up the value of an attribute by qualified (prefixed) name.
+        *
+        * @param qName The qualified name.
+        * @return The attribute's value.
+        */
+       @Override
+       public String getValue (String qName)
+       {
+           return qAtts.getValue(qName);
+       }
+
+       private AttributeList qAtts;
+    }
+}
+
+// end of ParserAdapter.java
diff --git a/src/org/xml/sax/helpers/ParserFactory.java b/src/org/xml/sax/helpers/ParserFactory.java
new file mode 100644 (file)
index 0000000..8ca7838
--- /dev/null
@@ -0,0 +1,123 @@
+// SAX parser factory.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: ParserFactory.java,v 1.7 2002/01/30 20:52:36 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import org.xml.sax.Parser;
+
+
+/**
+ * Java-specific class for dynamically loading SAX parsers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p><strong>Note:</strong> This class is designed to work with the now-deprecated
+ * SAX1 {@link org.xml.sax.Parser Parser} class.  SAX2 applications should use
+ * {@link org.xml.sax.helpers.XMLReaderFactory XMLReaderFactory} instead.</p>
+ *
+ * <p>ParserFactory is not part of the platform-independent definition
+ * of SAX; it is an additional convenience class designed
+ * specifically for Java XML application writers.  SAX applications
+ * can use the static methods in this class to allocate a SAX parser
+ * dynamically at run-time based either on the value of the
+ * `org.xml.sax.parser' system property or on a string containing the class
+ * name.</p>
+ *
+ * <p>Note that the application still requires an XML parser that
+ * implements SAX1.</p>
+ *
+ * @deprecated This class works with the deprecated
+ *             {@link org.xml.sax.Parser Parser}
+ *             interface.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public class ParserFactory {
+    
+    
+    /**
+     * Private null constructor.
+     */
+    private ParserFactory ()
+    {
+    }
+    
+    
+    /**
+     * Create a new SAX parser using the `org.xml.sax.parser' system property.
+     *
+     * <p>The named class must exist and must implement the
+     * {@link org.xml.sax.Parser Parser} interface.</p>
+     *
+     * @exception java.lang.NullPointerException There is no value
+     *            for the `org.xml.sax.parser' system property.
+     * @exception java.lang.ClassNotFoundException The SAX parser
+     *            class was not found (check your CLASSPATH).
+     * @exception IllegalAccessException The SAX parser class was
+     *            found, but you do not have permission to load
+     *            it.
+     * @exception InstantiationException The SAX parser class was
+     *            found but could not be instantiated.
+     * @exception java.lang.ClassCastException The SAX parser class
+     *            was found and instantiated, but does not implement
+     *            org.xml.sax.Parser.
+     * @see #makeParser(java.lang.String)
+     * @see org.xml.sax.Parser
+     */
+    public static Parser makeParser ()
+       throws ClassNotFoundException,
+       IllegalAccessException, 
+       InstantiationException,
+       NullPointerException,
+       ClassCastException
+    {
+       String className = System.getProperty("org.xml.sax.parser");
+       if (className == null) {
+           throw new NullPointerException("No value for sax.parser property");
+       } else {
+           return makeParser(className);
+       }
+    }
+    
+    
+    /**
+     * Create a new SAX parser object using the class name provided.
+     *
+     * <p>The named class must exist and must implement the
+     * {@link org.xml.sax.Parser Parser} interface.</p>
+     *
+     * @param className A string containing the name of the
+     *                  SAX parser class.
+     * @exception java.lang.ClassNotFoundException The SAX parser
+     *            class was not found (check your CLASSPATH).
+     * @exception IllegalAccessException The SAX parser class was
+     *            found, but you do not have permission to load
+     *            it.
+     * @exception InstantiationException The SAX parser class was
+     *            found but could not be instantiated.
+     * @exception java.lang.ClassCastException The SAX parser class
+     *            was found and instantiated, but does not implement
+     *            org.xml.sax.Parser.
+     * @see #makeParser()
+     * @see org.xml.sax.Parser
+     */
+    public static Parser makeParser (String className)
+       throws ClassNotFoundException,
+       IllegalAccessException, 
+       InstantiationException,
+       ClassCastException
+    {
+       return (Parser) NewInstance.newInstance (
+               NewInstance.getClassLoader (), className);
+    }
+    
+}
+
diff --git a/src/org/xml/sax/helpers/XMLFilterImpl.java b/src/org/xml/sax/helpers/XMLFilterImpl.java
new file mode 100644 (file)
index 0000000..6f329d9
--- /dev/null
@@ -0,0 +1,746 @@
+// XMLFilterImpl.java - base SAX2 filter implementation.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLFilterImpl.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.XMLFilter;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXNotRecognizedException;
+
+
+/**
+ * Base class for deriving an XML filter.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class is designed to sit between an {@link org.xml.sax.XMLReader
+ * XMLReader} and the client application's event handlers.  By default, it
+ * does nothing but pass requests up to the reader and events
+ * on to the handlers unmodified, but subclasses can override
+ * specific methods to modify the event stream or the configuration
+ * requests as they pass through.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLFilter
+ * @see org.xml.sax.XMLReader
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.ContentHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public class XMLFilterImpl
+    implements XMLFilter, EntityResolver, DTDHandler, ContentHandler, ErrorHandler
+{
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Constructors.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct an empty XML filter, with no parent.
+     *
+     * <p>This filter will have no parent: you must assign a parent
+     * before you start a parse or do any configuration with
+     * setFeature or setProperty, unless you use this as a pure event
+     * consumer rather than as an {@link XMLReader}.</p>
+     *
+     * @see org.xml.sax.XMLReader#setFeature
+     * @see org.xml.sax.XMLReader#setProperty
+     * @see #setParent
+     */
+    public XMLFilterImpl ()
+    {
+       super();
+    }
+
+
+    /**
+     * Construct an XML filter with the specified parent.
+     *
+     * @see #setParent
+     * @see #getParent
+     */
+    public XMLFilterImpl (XMLReader parent)
+    {
+        super();
+       setParent(parent);
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.XMLFilter.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set the parent reader.
+     *
+     * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which 
+     * this filter will obtain its events and to which it will pass its 
+     * configuration requests.  The parent may itself be another filter.</p>
+     *
+     * <p>If there is no parent reader set, any attempt to parse
+     * or to set or get a feature or property will fail.</p>
+     *
+     * @param parent The parent XML reader.
+     * @see #getParent
+     */
+    @Override
+               public void setParent (XMLReader parent)
+    {
+       this.parent = parent;
+    }
+
+
+    /**
+     * Get the parent reader.
+     *
+     * @return The parent XML reader, or null if none is set.
+     * @see #setParent
+     */
+    @Override
+               public XMLReader getParent ()
+    {
+       return parent;
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.XMLReader.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set the value of a feature.
+     *
+     * <p>This will always fail if the parent is null.</p>
+     *
+     * @param name The feature name.
+     * @param value The requested feature value.
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the feature name but 
+     *            cannot set the requested value.
+     */
+    @Override
+               public void setFeature (String name, boolean value)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       if (parent != null) {
+           parent.setFeature(name, value);
+       } else {
+           throw new SAXNotRecognizedException("Feature: " + name);
+       }
+    }
+
+
+    /**
+     * Look up the value of a feature.
+     *
+     * <p>This will always fail if the parent is null.</p>
+     *
+     * @param name The feature name.
+     * @return The current value of the feature.
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the feature name but 
+     *            cannot determine its value at this time.
+     */
+    @Override
+               public boolean getFeature (String name)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       if (parent != null) {
+           return parent.getFeature(name);
+       } else {
+           throw new SAXNotRecognizedException("Feature: " + name);
+       }
+    }
+
+
+    /**
+     * Set the value of a property.
+     *
+     * <p>This will always fail if the parent is null.</p>
+     *
+     * @param name The property name.
+     * @param value The requested property value.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the property name but 
+     *            cannot set the requested value.
+     */
+    @Override
+               public void setProperty (String name, Object value)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       if (parent != null) {
+           parent.setProperty(name, value);
+       } else {
+           throw new SAXNotRecognizedException("Property: " + name);
+       }
+    }
+
+
+    /**
+     * Look up the value of a property.
+     *
+     * @param name The property name.
+     * @return The current value of the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the property name but 
+     *            cannot determine its value at this time.
+     */
+    @Override
+               public Object getProperty (String name)
+       throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+       if (parent != null) {
+           return parent.getProperty(name);
+       } else {
+           throw new SAXNotRecognizedException("Property: " + name);
+       }
+    }
+
+
+    /**
+     * Set the entity resolver.
+     *
+     * @param resolver The new entity resolver.
+     */
+    @Override
+               public void setEntityResolver (EntityResolver resolver)
+    {
+       entityResolver = resolver;
+    }
+
+
+    /**
+     * Get the current entity resolver.
+     *
+     * @return The current entity resolver, or null if none was set.
+     */
+    @Override
+               public EntityResolver getEntityResolver ()
+    {
+       return entityResolver;
+    }
+
+
+    /**
+     * Set the DTD event handler.
+     *
+     * @param handler the new DTD handler
+     */
+    @Override
+               public void setDTDHandler (DTDHandler handler)
+    {
+       dtdHandler = handler;
+    }
+
+
+    /**
+     * Get the current DTD event handler.
+     *
+     * @return The current DTD handler, or null if none was set.
+     */
+    @Override
+               public DTDHandler getDTDHandler ()
+    {
+       return dtdHandler;
+    }
+
+
+    /**
+     * Set the content event handler.
+     *
+     * @param handler the new content handler
+     */
+    @Override
+               public void setContentHandler (ContentHandler handler)
+    {
+       contentHandler = handler;
+    }
+
+
+    /**
+     * Get the content event handler.
+     *
+     * @return The current content handler, or null if none was set.
+     */
+    @Override
+               public ContentHandler getContentHandler ()
+    {
+       return contentHandler;
+    }
+
+
+    /**
+     * Set the error event handler.
+     *
+     * @param handler the new error handler
+     */
+    @Override
+               public void setErrorHandler (ErrorHandler handler)
+    {
+       errorHandler = handler;
+    }
+
+
+    /**
+     * Get the current error event handler.
+     *
+     * @return The current error handler, or null if none was set.
+     */
+    @Override
+               public ErrorHandler getErrorHandler ()
+    {
+       return errorHandler;
+    }
+
+
+    /**
+     * Parse a document.
+     *
+     * @param input The input source for the document entity.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     */
+    @Override
+               public void parse (InputSource input)
+       throws SAXException, IOException
+    {
+       setupParse();
+       parent.parse(input);
+    }
+
+
+    /**
+     * Parse a document.
+     *
+     * @param systemId The system identifier as a fully-qualified URI.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     */
+    @Override
+               public void parse (String systemId)
+       throws SAXException, IOException
+    {
+       parse(new InputSource(systemId));
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.EntityResolver.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Filter an external entity resolution.
+     *
+     * @param publicId The entity's public identifier, or null.
+     * @param systemId The entity's system identifier.
+     * @return A new InputSource or null for the default.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     * @exception java.io.IOException The client may throw an
+     *            I/O-related exception while obtaining the
+     *            new InputSource.
+     */
+    @Override
+               public InputSource resolveEntity (String publicId, String systemId)
+       throws SAXException, IOException
+    {
+       if (entityResolver != null) {
+           return entityResolver.resolveEntity(publicId, systemId);
+       } else {
+           return null;
+       }
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.DTDHandler.
+    ////////////////////////////////////////////////////////////////////
+
+    
+    /**
+     * Filter a notation declaration event.
+     *
+     * @param name The notation name.
+     * @param publicId The notation's public identifier, or null.
+     * @param systemId The notation's system identifier, or null.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void notationDecl (String name, String publicId, String systemId)
+       throws SAXException
+    {
+       if (dtdHandler != null) {
+           dtdHandler.notationDecl(name, publicId, systemId);
+       }
+    }
+
+    
+    /**
+     * Filter an unparsed entity declaration event.
+     *
+     * @param name The entity name.
+     * @param publicId The entity's public identifier, or null.
+     * @param systemId The entity's system identifier, or null.
+     * @param notationName The name of the associated notation.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void unparsedEntityDecl (String name, String publicId,
+                                   String systemId, String notationName)
+       throws SAXException
+    {
+       if (dtdHandler != null) {
+           dtdHandler.unparsedEntityDecl(name, publicId, systemId,
+                                         notationName);
+       }
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.ContentHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Filter a new document locator event.
+     *
+     * @param locator The document locator.
+     */
+    @Override
+               public void setDocumentLocator (Locator locator)
+    {
+       this.locator = locator;
+       if (contentHandler != null) {
+           contentHandler.setDocumentLocator(locator);
+       }
+    }
+
+
+    /**
+     * Filter a start document event.
+     *
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void startDocument ()
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.startDocument();
+       }
+    }
+
+
+    /**
+     * Filter an end document event.
+     *
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void endDocument ()
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.endDocument();
+       }
+    }
+
+
+    /**
+     * Filter a start Namespace prefix mapping event.
+     *
+     * @param prefix The Namespace prefix.
+     * @param uri The Namespace URI.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void startPrefixMapping (String prefix, String uri)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.startPrefixMapping(prefix, uri);
+       }
+    }
+
+
+    /**
+     * Filter an end Namespace prefix mapping event.
+     *
+     * @param prefix The Namespace prefix.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void endPrefixMapping (String prefix)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.endPrefixMapping(prefix);
+       }
+    }
+
+
+    /**
+     * Filter a start element event.
+     *
+     * @param uri The element's Namespace URI, or the empty string.
+     * @param localName The element's local name, or the empty string.
+     * @param qName The element's qualified (prefixed) name, or the empty
+     *        string.
+     * @param atts The element's attributes.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void startElement (String uri, String localName, String qName,
+                             Attributes atts)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.startElement(uri, localName, qName, atts);
+       }
+    }
+
+
+    /**
+     * Filter an end element event.
+     *
+     * @param uri The element's Namespace URI, or the empty string.
+     * @param localName The element's local name, or the empty string.
+     * @param qName The element's qualified (prefixed) name, or the empty
+     *        string.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void endElement (String uri, String localName, String qName)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.endElement(uri, localName, qName);
+       }
+    }
+
+
+    /**
+     * Filter a character data event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use from the array.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void characters (char ch[], int start, int length)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.characters(ch, start, length);
+       }
+    }
+
+
+    /**
+     * Filter an ignorable whitespace event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use from the array.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void ignorableWhitespace (char ch[], int start, int length)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.ignorableWhitespace(ch, start, length);
+       }
+    }
+
+
+    /**
+     * Filter a processing instruction event.
+     *
+     * @param target The processing instruction target.
+     * @param data The text following the target.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void processingInstruction (String target, String data)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.processingInstruction(target, data);
+       }
+    }
+
+
+    /**
+     * Filter a skipped entity event.
+     *
+     * @param name The name of the skipped entity.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void skippedEntity (String name)
+       throws SAXException
+    {
+       if (contentHandler != null) {
+           contentHandler.skippedEntity(name);
+       }
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.ErrorHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Filter a warning event.
+     *
+     * @param e The warning as an exception.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void warning (SAXParseException e)
+       throws SAXException
+    {
+       if (errorHandler != null) {
+           errorHandler.warning(e);
+       }
+    }
+
+
+    /**
+     * Filter an error event.
+     *
+     * @param e The error as an exception.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void error (SAXParseException e)
+       throws SAXException
+    {
+       if (errorHandler != null) {
+           errorHandler.error(e);
+       }
+    }
+
+
+    /**
+     * Filter a fatal error event.
+     *
+     * @param e The error as an exception.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    @Override
+               public void fatalError (SAXParseException e)
+       throws SAXException
+    {
+       if (errorHandler != null) {
+           errorHandler.fatalError(e);
+       }
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal methods.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set up before a parse.
+     *
+     * <p>Before every parse, check whether the parent is
+     * non-null, and re-register the filter for all of the 
+     * events.</p>
+     */
+    private void setupParse ()
+    {
+       if (parent == null) {
+           throw new NullPointerException("No parent for filter");
+       }
+       parent.setEntityResolver(this);
+       parent.setDTDHandler(this);
+       parent.setContentHandler(this);
+       parent.setErrorHandler(this);
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    private XMLReader parent = null;
+    private Locator locator = null;
+    private EntityResolver entityResolver = null;
+    private DTDHandler dtdHandler = null;
+    private ContentHandler contentHandler = null;
+    private ErrorHandler errorHandler = null;
+
+}
+
+// end of XMLFilterImpl.java
diff --git a/src/org/xml/sax/helpers/XMLReaderAdapter.java b/src/org/xml/sax/helpers/XMLReaderAdapter.java
new file mode 100644 (file)
index 0000000..8a587c4
--- /dev/null
@@ -0,0 +1,562 @@
+// XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: XMLReaderAdapter.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import org.xml.sax.Parser;     // deprecated
+import org.xml.sax.Locator;
+import org.xml.sax.InputSource;
+import org.xml.sax.AttributeList; // deprecated
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler; // deprecated
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXNotSupportedException;
+
+
+/**
+ * Adapt a SAX2 XMLReader as a SAX1 Parser.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader}
+ * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}.  The XMLReader 
+ * must support a true value for the 
+ * http://xml.org/sax/features/namespace-prefixes property or parsing will fail
+ * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader 
+ * supports a false value for the http://xml.org/sax/features/namespaces 
+ * property, that will also be used to improve efficiency.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.Parser
+ * @see org.xml.sax.XMLReader
+ */
+public class XMLReaderAdapter implements Parser, ContentHandler
+{
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Constructor.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Create a new adapter.
+     *
+     * <p>Use the "org.xml.sax.driver" property to locate the SAX2
+     * driver to embed.</p>
+     *
+     * @exception org.xml.sax.SAXException If the embedded driver
+     *            cannot be instantiated or if the
+     *            org.xml.sax.driver property is not specified.
+     */
+    public XMLReaderAdapter ()
+      throws SAXException
+    {
+       setup(XMLReaderFactory.createXMLReader());
+    }
+
+
+    /**
+     * Create a new adapter.
+     *
+     * <p>Create a new adapter, wrapped around a SAX2 XMLReader.
+     * The adapter will make the XMLReader act like a SAX1
+     * Parser.</p>
+     *
+     * @param xmlReader The SAX2 XMLReader to wrap.
+     * @exception java.lang.NullPointerException If the argument is null.
+     */
+    public XMLReaderAdapter (XMLReader xmlReader)
+    {
+       setup(xmlReader);
+    }
+
+
+
+    /**
+     * Internal setup.
+     *
+     * @param xmlReader The embedded XMLReader.
+     */
+    private void setup (XMLReader xmlReader)
+    {
+       if (xmlReader == null) {
+           throw new NullPointerException("XMLReader must not be null");
+       }
+       this.xmlReader = xmlReader;
+       qAtts = new AttributesAdapter();
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.Parser.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set the locale for error reporting.
+     *
+     * <p>This is not supported in SAX2, and will always throw
+     * an exception.</p>
+     *
+     * @param locale the locale for error reporting.
+     * @see org.xml.sax.Parser#setLocale
+     * @exception org.xml.sax.SAXException Thrown unless overridden.
+     */
+    @Override
+               public void setLocale (Locale locale)
+       throws SAXException
+    {
+       throw new SAXNotSupportedException("setLocale not supported");
+    }
+
+
+    /**
+     * Register the entity resolver.
+     *
+     * @param resolver The new resolver.
+     * @see org.xml.sax.Parser#setEntityResolver
+     */
+    @Override
+               public void setEntityResolver (EntityResolver resolver)
+    {
+       xmlReader.setEntityResolver(resolver);
+    }
+
+
+    /**
+     * Register the DTD event handler.
+     *
+     * @param handler The new DTD event handler.
+     * @see org.xml.sax.Parser#setDTDHandler
+     */
+    @Override
+               public void setDTDHandler (DTDHandler handler)
+    {
+       xmlReader.setDTDHandler(handler);
+    }
+
+
+    /**
+     * Register the SAX1 document event handler.
+     *
+     * <p>Note that the SAX1 document handler has no Namespace
+     * support.</p>
+     *
+     * @param handler The new SAX1 document event handler.
+     * @see org.xml.sax.Parser#setDocumentHandler
+     */
+    @Override
+               public void setDocumentHandler (DocumentHandler handler)
+    {
+       documentHandler = handler;
+    }
+
+
+    /**
+     * Register the error event handler.
+     *
+     * @param handler The new error event handler.
+     * @see org.xml.sax.Parser#setErrorHandler
+     */
+    @Override
+               public void setErrorHandler (ErrorHandler handler)
+    {
+       xmlReader.setErrorHandler(handler);
+    }
+
+
+    /**
+     * Parse the document.
+     *
+     * <p>This method will throw an exception if the embedded
+     * XMLReader does not support the 
+     * http://xml.org/sax/features/namespace-prefixes property.</p>
+     *
+     * @param systemId The absolute URL of the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception org.xml.sax.SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(org.xml.sax.InputSource)
+     * @see org.xml.sax.Parser#parse(java.lang.String)
+     */
+    @Override
+               public void parse (String systemId)
+       throws IOException, SAXException
+    {
+       parse(new InputSource(systemId));
+    }
+
+
+    /**
+     * Parse the document.
+     *
+     * <p>This method will throw an exception if the embedded
+     * XMLReader does not support the 
+     * http://xml.org/sax/features/namespace-prefixes property.</p>
+     *
+     * @param input An input source for the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception org.xml.sax.SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(java.lang.String)
+     * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
+     */
+    @Override
+               public void parse (InputSource input)
+       throws IOException, SAXException
+    {
+       setupXMLReader();
+       xmlReader.parse(input);
+    }
+
+
+    /**
+     * Set up the XML reader.
+     */
+    private void setupXMLReader ()
+       throws SAXException
+    {
+       xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+       try {
+           xmlReader.setFeature("http://xml.org/sax/features/namespaces",
+                                false);
+       } catch (SAXException e) {
+           // NO OP: it's just extra information, and we can ignore it
+       }
+       xmlReader.setContentHandler(this);
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.ContentHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set a document locator.
+     *
+     * @param locator The document locator.
+     * @see org.xml.sax.ContentHandler#setDocumentLocator
+     */
+    @Override
+               public void setDocumentLocator (Locator locator)
+    {
+       if (documentHandler != null)
+           documentHandler.setDocumentLocator(locator);
+    }
+
+
+    /**
+     * Start document event.
+     *
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#startDocument
+     */
+    @Override
+               public void startDocument ()
+       throws SAXException
+    {
+       if (documentHandler != null)
+           documentHandler.startDocument();
+    }
+
+
+    /**
+     * End document event.
+     *
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#endDocument
+     */
+    @Override
+               public void endDocument ()
+       throws SAXException
+    {
+       if (documentHandler != null)
+           documentHandler.endDocument();
+    }
+
+
+    /**
+     * Adapt a SAX2 start prefix mapping event.
+     *
+     * @param prefix The prefix being mapped.
+     * @param uri The Namespace URI being mapped to.
+     * @see org.xml.sax.ContentHandler#startPrefixMapping
+     */
+    @Override
+               public void startPrefixMapping (String prefix, String uri)
+    {
+    }
+
+
+    /**
+     * Adapt a SAX2 end prefix mapping event.
+     *
+     * @param prefix The prefix being mapped.
+     * @see org.xml.sax.ContentHandler#endPrefixMapping
+     */
+    @Override
+               public void endPrefixMapping (String prefix)
+    {
+    }
+
+
+    /**
+     * Adapt a SAX2 start element event.
+     *
+     * @param uri The Namespace URI.
+     * @param localName The Namespace local name.
+     * @param qName The qualified (prefixed) name.
+     * @param atts The SAX2 attributes.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#endDocument
+     */
+    @Override
+               public void startElement (String uri, String localName,
+                             String qName, Attributes atts)
+       throws SAXException
+    {
+       if (documentHandler != null) {
+           qAtts.setAttributes(atts);
+           documentHandler.startElement(qName, qAtts);
+       }
+    }
+
+
+    /**
+     * Adapt a SAX2 end element event.
+     *
+     * @param uri The Namespace URI.
+     * @param localName The Namespace local name.
+     * @param qName The qualified (prefixed) name.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#endElement
+     */
+    @Override
+               public void endElement (String uri, String localName,
+                           String qName)
+       throws SAXException
+    {
+       if (documentHandler != null)
+           documentHandler.endElement(qName);
+    }
+
+
+    /**
+     * Adapt a SAX2 characters event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#characters
+     */
+    @Override
+               public void characters (char ch[], int start, int length)
+       throws SAXException
+    {
+       if (documentHandler != null)
+           documentHandler.characters(ch, start, length);
+    }
+
+
+    /**
+     * Adapt a SAX2 ignorable whitespace event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#ignorableWhitespace
+     */
+    @Override
+               public void ignorableWhitespace (char ch[], int start, int length)
+       throws SAXException
+    {
+       if (documentHandler != null)
+           documentHandler.ignorableWhitespace(ch, start, length);
+    }
+
+
+    /**
+     * Adapt a SAX2 processing instruction event.
+     *
+     * @param target The processing instruction target.
+     * @param data The remainder of the processing instruction
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#processingInstruction
+     */
+    @Override
+               public void processingInstruction (String target, String data)
+       throws SAXException
+    {
+       if (documentHandler != null)
+           documentHandler.processingInstruction(target, data);
+    }
+
+
+    /**
+     * Adapt a SAX2 skipped entity event.
+     *
+     * @param name The name of the skipped entity.
+     * @see org.xml.sax.ContentHandler#skippedEntity
+     * @exception org.xml.sax.SAXException Throwable by subclasses.
+     */
+    @Override
+               public void skippedEntity (String name)
+       throws SAXException
+    {
+    }
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    XMLReader xmlReader;
+    DocumentHandler documentHandler;
+    AttributesAdapter qAtts;
+
+
+\f
+    ////////////////////////////////////////////////////////////////////
+    // Internal class.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Internal class to wrap a SAX2 Attributes object for SAX1.
+     */
+    final class AttributesAdapter implements AttributeList
+    {
+       AttributesAdapter ()
+       {
+       }
+
+
+       /**
+        * Set the embedded Attributes object.
+        *
+        * @param The embedded SAX2 Attributes.
+        */ 
+       void setAttributes (Attributes attributes)
+       {
+           this.attributes = attributes;
+       }
+
+
+       /**
+        * Return the number of attributes.
+        *
+        * @return The length of the attribute list.
+        * @see org.xml.sax.AttributeList#getLength
+        */
+       @Override
+       public int getLength ()
+       {
+           return attributes.getLength();
+       }
+
+
+       /**
+        * Return the qualified (prefixed) name of an attribute by position.
+        *
+        * @return The qualified name.
+        * @see org.xml.sax.AttributeList#getName
+        */
+       @Override
+       public String getName (int i)
+       {
+           return attributes.getQName(i);
+       }
+
+
+       /**
+        * Return the type of an attribute by position.
+        *
+        * @return The type.
+        * @see org.xml.sax.AttributeList#getType(int)
+        */
+       @Override
+       public String getType (int i)
+       {
+           return attributes.getType(i);
+       }
+
+
+       /**
+        * Return the value of an attribute by position.
+        *
+        * @return The value.
+        * @see org.xml.sax.AttributeList#getValue(int)
+        */
+       @Override
+       public String getValue (int i)
+       {
+           return attributes.getValue(i);
+       }
+
+
+       /**
+        * Return the type of an attribute by qualified (prefixed) name.
+        *
+        * @return The type.
+        * @see org.xml.sax.AttributeList#getType(java.lang.String)
+        */
+       @Override
+       public String getType (String qName)
+       {
+           return attributes.getType(qName);
+       }
+
+
+       /**
+        * Return the value of an attribute by qualified (prefixed) name.
+        *
+        * @return The value.
+        * @see org.xml.sax.AttributeList#getValue(java.lang.String)
+        */
+       @Override
+       public String getValue (String qName)
+       {
+           return attributes.getValue(qName);
+       }
+
+       private Attributes attributes;
+    }
+
+}
+
+// end of XMLReaderAdapter.java
diff --git a/src/org/xml/sax/helpers/XMLReaderFactory.java b/src/org/xml/sax/helpers/XMLReaderFactory.java
new file mode 100644 (file)
index 0000000..f50be7a
--- /dev/null
@@ -0,0 +1,202 @@
+// XMLReaderFactory.java - factory for creating a new reader.
+// http://www.saxproject.org
+// Written by David Megginson
+// and by David Brownell
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLReaderFactory.java,v 1.10 2002/04/22 01:00:13 dbrownell Exp $
+
+package org.xml.sax.helpers;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import org.xml.sax.XMLReader;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Factory for creating an XML reader.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class contains static methods for creating an XML reader
+ * from an explicit class name, or based on runtime defaults:</p>
+ *
+ * <pre>
+ * try {
+ *   XMLReader myReader = XMLReaderFactory.createXMLReader();
+ * } catch (SAXException e) {
+ *   System.err.println(e.getMessage());
+ * }
+ * </pre>
+ *
+ * <p><strong>Note to Distributions bundled with parsers:</strong>
+ * You should modify the implementation of the no-arguments
+ * <em>createXMLReader</em> to handle cases where the external
+ * configuration mechanisms aren't set up.  That method should do its
+ * best to return a parser when one is in the class path, even when
+ * nothing bound its class name to <code>org.xml.sax.driver</code> so
+ * those configuration mechanisms would see it.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson, David Brownell
+ * @version 2.0.1 (sax2r2)
+ */
+final public class XMLReaderFactory
+{
+    /**
+     * Private constructor.
+     *
+     * <p>This constructor prevents the class from being instantiated.</p>
+     */
+    private XMLReaderFactory ()
+    {
+    }
+
+    private static final String property = "org.xml.sax.driver";
+
+    /**
+     * Attempt to create an XMLReader from system defaults.
+     * In environments which can support it, the name of the XMLReader
+     * class is determined by trying each these options in order, and
+     * using the first one which succeeds:</p> <ul>
+     *
+     * <li>If the system property <code>org.xml.sax.driver</code>
+     * has a value, that is used as an XMLReader class name. </li>
+     *
+     * <li>The JAR "Services API" is used to look for a class name
+     * in the <em>META-INF/services/org.xml.sax.driver</em> file in
+     * jarfiles available to the runtime.</li>
+     *
+     * <li> SAX parser distributions are strongly encouraged to provide
+     * a default XMLReader class name that will take effect only when
+     * previous options (on this list) are not successful.</li>
+     *
+     * <li>Finally, if {@link ParserFactory#makeParser()} can
+     * return a system default SAX1 parser, that parser is wrapped in
+     * a {@link ParserAdapter}.  (This is a migration aid for SAX1
+     * environments, where the <code>org.xml.sax.parser</code> system
+     * property will often be usable.) </li>
+     *
+     * </ul>
+     *
+     * <p> In environments such as small embedded systems, which can not
+     * support that flexibility, other mechanisms to determine the default
+     * may be used. </p>
+     *
+     * <p>Note that many Java environments allow system properties to be
+     * initialized on a command line.  This means that <em>in most cases</em>
+     * setting a good value for that property ensures that calls to this
+     * method will succeed, except when security policies intervene.
+     * This will also maximize application portability to older SAX
+     * environments, with less robust implementations of this method.
+     * </p>
+     *
+     * @return A new XMLReader.
+     * @exception org.xml.sax.SAXException If no default XMLReader class
+     *            can be identified and instantiated.
+     * @see #createXMLReader(java.lang.String)
+     */
+    public static XMLReader createXMLReader ()
+       throws SAXException
+    {
+       String          className = null;
+       ClassLoader     loader = NewInstance.getClassLoader ();
+       
+       // 1. try the JVM-instance-wide system property
+       try { className = System.getProperty (property); }
+       catch (RuntimeException e) { /* normally fails for applets */ }
+
+       // 2. if that fails, try META-INF/services/
+       if (className == null) {
+           try {
+               String          service = "META-INF/services/" + property;
+               InputStream     in;
+               BufferedReader  reader;
+
+               if (loader == null)
+                   in = ClassLoader.getSystemResourceAsStream (service);
+               else
+                   in = loader.getResourceAsStream (service);
+
+               if (in != null) {
+                   reader = new BufferedReader (
+                           new InputStreamReader (in, "UTF8"));
+                   className = reader.readLine ();
+                   in.close ();
+               }
+           } catch (Exception e) {
+           }
+       }
+
+       // 3. Distro-specific fallback
+       if (className == null) {
+// BEGIN DISTRIBUTION-SPECIFIC
+
+           // EXAMPLE:
+           // className = "com.example.sax.XmlReader";
+           // or a $JAVA_HOME/jre/lib/*properties setting...
+
+// END DISTRIBUTION-SPECIFIC
+       }
+       
+       // do we know the XMLReader implementation class yet?
+       if (className != null)
+           return loadClass (loader, className);
+
+       // 4. panic -- adapt any SAX1 parser
+       try {
+           return new ParserAdapter (ParserFactory.makeParser ());
+       } catch (Exception e) {
+           throw new SAXException ("Can't create default XMLReader; "
+                   + "is system property org.xml.sax.driver set?");
+       }
+    }
+
+
+    /**
+     * Attempt to create an XML reader from a class name.
+     *
+     * <p>Given a class name, this method attempts to load
+     * and instantiate the class as an XML reader.</p>
+     *
+     * <p>Note that this method will not be usable in environments where
+     * the caller (perhaps an applet) is not permitted to load classes
+     * dynamically.</p>
+     *
+     * @return A new XML reader.
+     * @exception org.xml.sax.SAXException If the class cannot be
+     *            loaded, instantiated, and cast to XMLReader.
+     * @see #createXMLReader()
+     */
+    public static XMLReader createXMLReader (String className)
+       throws SAXException
+    {
+       return loadClass (NewInstance.getClassLoader (), className);
+    }
+
+    private static XMLReader loadClass (ClassLoader loader, String className)
+    throws SAXException
+    {
+       try {
+           return (XMLReader) NewInstance.newInstance (loader, className);
+       } catch (ClassNotFoundException e1) {
+           throw new SAXException("SAX2 driver class " + className +
+                                  " not found", e1);
+       } catch (IllegalAccessException e2) {
+           throw new SAXException("SAX2 driver class " + className +
+                                  " found but cannot be loaded", e2);
+       } catch (InstantiationException e3) {
+           throw new SAXException("SAX2 driver class " + className +
+          " loaded but cannot be instantiated (no empty public constructor?)",
+                                  e3);
+       } catch (ClassCastException e4) {
+           throw new SAXException("SAX2 driver class " + className +
+                                  " does not implement XMLReader", e4);
+       }
+    }
+}
diff --git a/src/org/xml/sax/helpers/package.html b/src/org/xml/sax/helpers/package.html
new file mode 100644 (file)
index 0000000..8f323c0
--- /dev/null
@@ -0,0 +1,11 @@
+<HTML><HEAD>
+<!-- $Id: package.html,v 1.6 2002/01/30 20:52:39 dbrownell Exp $ -->
+</HEAD><BODY>
+
+<p>This package contains "helper" classes, including
+support for bootstrapping SAX-based applications.
+
+<p>See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+for more information about SAX.</p>
+
+</BODY></HTML>