You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2005/04/02 21:27:06 UTC

svn commit: r159798 [2/2] - in incubator/jackrabbit/trunk/contrib/jcr-server: client/src/java/org/apache/jackrabbit/client/ server/ server/src/java/org/apache/jackrabbit/server/ server/src/java/org/apache/jackrabbit/server/simple/ server/src/java/org/apache/jackrabbit/server/simple/dav/ server/src/java/org/apache/jackrabbit/server/simple/dav/lock/ server/src/java/org/apache/jackrabbit/webdav/spi/ server/src/java/org/apache/jackrabbit/webdav/spi/property/ server/src/java/org/apache/jackrabbit/webdav/spi/version/ server/src/java/org/apache/jackrabbit/webdav/spi/version/report/ webapp/src/webapp/WEB-INF/ webdav/src/java/org/apache/jackrabbit/webdav/ webdav/src/java/org/apache/jackrabbit/webdav/property/ webdav/src/java/org/apache/jackrabbit/webdav/util/

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/util/Text.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/util/Text.java?view=diff&r1=159797&r2=159798
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/util/Text.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/util/Text.java Sat Apr  2 11:27:01 2005
@@ -19,6 +19,7 @@
 import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.security.NoSuchAlgorithmException;
+import java.security.MessageDigest;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.*;
@@ -26,7 +27,12 @@
 /**
  * This class holds a collection of string utility operations.
  */
-public final class Text extends org.apache.jackrabbit.core.util.Text {
+public final class Text {
+
+    /**
+     * used for the md5
+     */
+    public final static char[] HEXTABLE = "0123456789abcdef".toCharArray();
 
     /**
      * The default format pattern used in strftime() if no pattern
@@ -47,29 +53,28 @@
      * more overhead given all those synchronized blocks waiting for each
      * other during real formatting. But then how knows ?
      * </ol>
-     * <p>
+     * <p/>
      * This formatter must always be used synchronized as follows :
      * <pre>
-	    synchronized (dateFormatter) {
-		dateFormatter.applyPattern( ... );
-		dateFormatter.setTimezone( ... );
-		String result = dateFormatter.format( ... );
-	    }
-     *	</pre>
-     * <p>
+     * synchronized (dateFormatter) {
+     * dateFormatter.applyPattern( ... );
+     * dateFormatter.setTimezone( ... );
+     * String result = dateFormatter.format( ... );
+     * }
+     * 	</pre>
+     * <p/>
      * To parse date and time strings , the formatter is used as follows :
      * <pre>
-	    synchronized (dateFormatter) {
-		dateFormatter.applyPattern( ... );
-		dateFormatter.setTimezone( ... );
-	        try {
-		    Date result = dateFormatter.parse(dateString);
-	        } catch (ParseException pe) {
-		    // handle exception
-	        }
-	    }
-     *	</pre>
-     *
+     * synchronized (dateFormatter) {
+     * dateFormatter.applyPattern( ... );
+     * dateFormatter.setTimezone( ... );
+     * try {
+     * Date result = dateFormatter.parse(dateString);
+     * } catch (ParseException pe) {
+     * // handle exception
+     * }
+     * }
+     * 	</pre>
      */
     private static final SimpleDateFormat dateFormatter = new SimpleDateFormat();
 
@@ -78,12 +83,14 @@
      */
     public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
 
-    /** format for RFC 1123 date string -- "Sun, 06 Nov 1994 08:49:37 GMT" */
+    /**
+     * format for RFC 1123 date string -- "Sun, 06 Nov 1994 08:49:37 GMT"
+     */
     private final static SimpleDateFormat rfc1123Format =
-	new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US);
+            new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US);
 
     static {
-	rfc1123Format.setTimeZone(TIMEZONE_UTC);
+        rfc1123Format.setTimeZone(TIMEZONE_UTC);
     }
 
     /**
@@ -108,56 +115,57 @@
      * characters, empty "" entries are avoided.
      *
      * @param str the string to decompose
-     * @param ch the character to use a split pattern
+     * @param ch  the character to use a split pattern
      * @return an array of strings
      */
     public static String[] explode(String str, int ch) {
-	return explode(str,ch,false);
+        return explode(str, ch, false);
     }
 
     /**
      * returns an array of strings decomposed of the original string, split at
      * every occurance of 'ch'.
-     * @param str the string to decompose
-     * @param ch the character to use a split pattern
+     *
+     * @param str          the string to decompose
+     * @param ch           the character to use a split pattern
      * @param respectEmpty if <code>true</code>, empty elements are generated
      * @return an array of strings
      */
     public static String[] explode(String str, int ch, boolean respectEmpty) {
-	if (str == null) {
+        if (str == null) {
             return empty;
         }
 
         Vector strings = new Vector();
-        int pos     = 0;
+        int pos = 0;
         int lastpos = 0;
 
         // add snipples
         while ((pos = str.indexOf(ch, lastpos)) >= 0) {
-	    if (pos-lastpos>0 || respectEmpty)
+            if (pos - lastpos > 0 || respectEmpty)
                 strings.add(str.substring(lastpos, pos));
-            lastpos = pos+1;
+            lastpos = pos + 1;
         }
         // add rest
         if (lastpos < str.length()) {
             strings.add(str.substring(lastpos));
-        } else if (respectEmpty && lastpos==str.length()) {
-	    strings.add("");
-	}
+        } else if (respectEmpty && lastpos == str.length()) {
+            strings.add("");
+        }
 
         // return stringarray
         return (String[]) strings.toArray(new String[strings.size()]);
     }
 
     public static String implode(String[] arr, String delim) {
-	StringBuffer buf = new StringBuffer();
-	for (int i=0; i<arr.length; i++) {
-	    if (i>0) {
-		buf.append(delim);
-	    }
-	    buf.append(arr[i]);
-	}
-	return buf.toString();
+        StringBuffer buf = new StringBuffer();
+        for (int i = 0; i < arr.length; i++) {
+            if (i > 0) {
+                buf.append(delim);
+            }
+            buf.append(arr[i]);
+        }
+        return buf.toString();
     }
 
     /**
@@ -183,22 +191,23 @@
      *         and zero, if the two handles are equal.
      */
     public static int comparePaths(String h1, String h2) {
-    	char[] ca1=h1.toCharArray(); // this is faster, than a .charAt everytime
-	char[] ca2=h2.toCharArray();
-        int n= ca1.length < ca2.length ? ca1.length : ca2.length;
-        int i=0;
-	while (i<n) {
-    	    if (ca1[i]!=ca2[i]) {
-    		char c1= ca1[i];
-		char c2= ca2[i];
-		// we give the '/' the highest priority
-		if      (c1=='/') c1=1;
-		else if (c2=='/') c2=1;
-		return c1-c2;
-	    }
+        char[] ca1 = h1.toCharArray(); // this is faster, than a .charAt everytime
+        char[] ca2 = h2.toCharArray();
+        int n = ca1.length < ca2.length ? ca1.length : ca2.length;
+        int i = 0;
+        while (i < n) {
+            if (ca1[i] != ca2[i]) {
+                char c1 = ca1[i];
+                char c2 = ca2[i];
+                // we give the '/' the highest priority
+                if (c1 == '/')
+                    c1 = 1;
+                else if (c2 == '/') c2 = 1;
+                return c1 - c2;
+            }
             i++;
-	}
-	return ca1.length-ca2.length;
+        }
+        return ca1.length - ca2.length;
     }
 
     /**
@@ -223,15 +232,15 @@
      * </xmp>
      *
      * @param parent the base handle
-     * @param path the path
+     * @param path   the path
      */
     public static String fullFilePath(String parent, String path) {
-	if (parent==null) parent="";
-	if (path==null) path="";
+        if (parent == null) parent = "";
+        if (path == null) path = "";
 
         // compose source string
         StringBuffer source;
-        if (path.equals("") || (path.charAt(0)!='/' && path.indexOf(':')<0)) {
+        if (path.equals("") || (path.charAt(0) != '/' && path.indexOf(':') < 0)) {
             // relative
             source = new StringBuffer(parent);
             if (!path.equals("")) {
@@ -240,9 +249,9 @@
             }
         } else {
             // absolute
-            source = new StringBuffer(path==null?"":path);
+            source = new StringBuffer(path == null ? "" : path);
         }
-	return makeCanonicalPath(source);
+        return makeCanonicalPath(source);
     }
 
     /**
@@ -268,12 +277,12 @@
      * @param path the path
      */
     public static String fullPath(String base, String path) {
-	if (base==null) base="";
-	if (path==null) path="";
+        if (base == null) base = "";
+        if (path == null) path = "";
 
         // compose source string
         StringBuffer source;
-        if (path.equals("") || path.charAt(0)!='/') {
+        if (path.equals("") || path.charAt(0) != '/') {
             // relative
             source = new StringBuffer(base);
             if (!path.equals("")) {
@@ -282,9 +291,9 @@
             }
         } else {
             // absolute
-            source = new StringBuffer(path==null?"":path);
+            source = new StringBuffer(path == null ? "" : path);
         }
-	return makeCanonicalPath(source);
+        return makeCanonicalPath(source);
     }
 
     /**
@@ -292,41 +301,43 @@
      * <code>
      * Text.makeCanonicalPath(new StringBuffer(path));
      * </code>
+     *
      * @param path path to make canonical
      */
     public static String makeCanonicalPath(String path) {
-	return makeCanonicalPath(new StringBuffer(path));
+        return makeCanonicalPath(new StringBuffer(path));
     }
 
     /**
      * make a cannonical path. removes all /./ and /../ and multiple slashes.
+     *
      * @param source the input source
      * @return a string containing the cannonical path
      */
     public static String makeCanonicalPath(StringBuffer source) {
         // remove/resolve .. and .
-        int   dst=0, pos=0, slash=0, dots=0, last=0, len=source.length();
-        int[] slashes=new int[1024];
-        slashes[0]=source.charAt(0)=='/' ? 0 : -1;
-        while (pos<len) {
-            int ch=source.charAt(pos++);
+        int dst = 0, pos = 0, slash = 0, dots = 0, last = 0, len = source.length();
+        int[] slashes = new int[1024];
+        slashes[0] = source.charAt(0) == '/' ? 0 : -1;
+        while (pos < len) {
+            int ch = source.charAt(pos++);
             switch (ch) {
                 case '/':
                     // ignore multiple slashes
-                    if (last=='/') continue;
+                    if (last == '/') continue;
                     // end of segment
-                    if (dots==1) {
+                    if (dots == 1) {
                         // ignore
-                        dst=slashes[slash];
-                    } else if (dots==2) {
+                        dst = slashes[slash];
+                    } else if (dots == 2) {
                         // backtrack
-                        if (--slash <0) slash=0;
-                        dst=slashes[slash];
+                        if (--slash < 0) slash = 0;
+                        dst = slashes[slash];
                     } else {
                         // remember slash position
-                        slashes[++slash]=dst;
+                        slashes[++slash] = dst;
                     }
-                    dots=0;
+                    dots = 0;
                     break;
                 case '.':
                     // count dots
@@ -334,11 +345,11 @@
                     break;
                 default:
                     // invalidate dots
-                    dots=3;
+                    dots = 3;
             }
-	    last=ch;
-            if (dst>=0) source.setCharAt(dst, (char) (last=ch));
-	    dst++;
+            last = ch;
+            if (dst >= 0) source.setCharAt(dst, (char) (last = ch));
+            dst++;
         }
         // check dots again
         if (dots == 1) {
@@ -351,22 +362,23 @@
         }
 
         // truncate result
-        if (dst>0) source.setLength(dst);
-	return dst==0 ? "/" : source.toString();
+        if (dst > 0) source.setLength(dst);
+        return dst == 0 ? "/" : source.toString();
     }
 
     /**
      * Determines, if two handles are sister-pages, that meens, if they
      * represent the same hierarchic level and share the same parent page.
+     *
      * @param h1 first handle
      * @param h2 second handle
      * @return true if on same level, false otherwise
      */
-     public static boolean isSibling(String h1, String h2) {
+    public static boolean isSibling(String h1, String h2) {
         int pos1 = h1.lastIndexOf('/');
         int pos2 = h2.lastIndexOf('/');
-        return (pos1==pos2 && pos1>=0 && h1.regionMatches(0,h2,0,pos1));
-     }
+        return (pos1 == pos2 && pos1 >= 0 && h1.regionMatches(0, h2, 0, pos1));
+    }
 
     /**
      * Determines if the <code>descendant</code> handle is hierarchical a
@@ -378,7 +390,7 @@
      * /content/playground/en  isNOTDescendantOf  /content/playground/en
      * </xmp>
      *
-     * @param handle the current handle
+     * @param handle     the current handle
      * @param descendant the potential descendant
      * @return <code>true</code> if the <code>descendant</code> is a descendant;
      *         <code>false</code> otherwise.
@@ -386,8 +398,8 @@
      */
     public static boolean isDescendant(String handle, String descendant) {
         return !handle.equals(descendant) &&
-            descendant.startsWith(handle) &&
-                descendant.charAt(handle.length())=='/';
+                descendant.startsWith(handle) &&
+                descendant.charAt(handle.length()) == '/';
     }
 
     /**
@@ -400,55 +412,53 @@
      * /content/playground/en  isNOTDescendantOrEqualOf  /content/designground
      * </xmp>
      *
-     * @param path the path to check
+     * @param path       the path to check
      * @param descendant the potential descendant
      * @return <code>true</code> if the <code>descendant</code> is a descendant
      *         or equal; <code>false</code> otherwise.
      * @since gumbear
      */
     public static boolean isDescendantOrEqual(String path, String descendant) {
-	if (path.equals(descendant)) {
-	    return true;
-	} else {
-	    String pattern = path.endsWith("/") ? path : path + "/";
-	    return descendant.startsWith(pattern);
-	}
+        if (path.equals(descendant)) {
+            return true;
+        } else {
+            String pattern = path.endsWith("/") ? path : path + "/";
+            return descendant.startsWith(pattern);
+        }
     }
 
     /**
      * Returns the label of a handle
+     *
      * @param handle the handle
      * @return the label
      */
     public static String getLabel(String handle) {
-        int pos=handle.lastIndexOf('/');
-        return pos>=0 ? handle.substring(pos+1) : "";
+        int pos = handle.lastIndexOf('/');
+        return pos >= 0 ? handle.substring(pos + 1) : "";
     }
 
     /**
      * Returns the label of a string
+     *
      * @param handle the string
-     * @param delim the delimiter
+     * @param delim  the delimiter
      * @return the label
      */
     public static String getLabel(String handle, char delim) {
-        int pos=handle.lastIndexOf(delim);
-        return pos>=0 ? handle.substring(pos+1) : "";
+        int pos = handle.lastIndexOf(delim);
+        return pos >= 0 ? handle.substring(pos + 1) : "";
     }
 
     /**
      * Digest the plain string using the given algorithm.
      *
      * @param algorithm The alogrithm for the digest. This algorithm must be
-     *        supported by the MessageDigest class.
-     * @param data The plain text String to be digested.
-     *
+     *                  supported by the MessageDigest class.
+     * @param data      The plain text String to be digested.
      * @return The digested plain text String represented as Hex digits.
-     *
      * @throws NoSuchAlgorithmException if the desired algorithm is not supported by
-     *         the MessageDigest class.
-     *
-     * @deprecated since echidna, use {@link #digest(String, String, String)}
+     *                                  the MessageDigest class.
      */
     public static String digest(String algorithm, String data)
             throws NoSuchAlgorithmException {
@@ -457,6 +467,48 @@
     }
 
     /**
+     * Digest the plain string using the given algorithm.
+     *
+     * @param algorithm The alogrithm for the digest. This algorithm must be
+     *                  supported by the MessageDigest class.
+     * @param data      The plain text String to be digested.
+     * @param enc       The character encoding to use
+     * @return The digested plain text String represented as Hex digits.
+     * @throws NoSuchAlgorithmException     if the desired algorithm is not supported by
+     *                                      the MessageDigest class.
+     * @throws UnsupportedEncodingException if the encoding is not supported
+     */
+    public static String digest(String algorithm, String data, String enc)
+            throws NoSuchAlgorithmException, UnsupportedEncodingException {
+
+        return digest(algorithm, data.getBytes(enc));
+    }
+
+    /**
+     * Digest the plain string using the given algorithm.
+     *
+     * @param algorithm The alogrithm for the digest. This algorithm must be
+     *                  supported by the MessageDigest class.
+     * @param data      the data to digest with the given algorithm
+     * @return The digested plain text String represented as Hex digits.
+     * @throws NoSuchAlgorithmException if the desired algorithm is not supported by
+     *                                  the MessageDigest class.
+     */
+    public static String digest(String algorithm, byte[] data)
+            throws NoSuchAlgorithmException {
+
+        MessageDigest md = MessageDigest.getInstance(algorithm);
+        byte[] digest = md.digest(data);
+        StringBuffer res = new StringBuffer(digest.length * 2);
+        for (int i = 0; i < digest.length; i++) {
+            byte b = digest[i];
+            res.append(HEXTABLE[(b >> 4) & 15]);
+            res.append(HEXTABLE[b & 15]);
+        }
+        return res.toString();
+    }
+
+    /**
      * Returns the n<sup>th</sup> relative parent of the handle, where n=level.
      * <p>Example:<br>
      * <code>
@@ -464,18 +516,18 @@
      * </code>
      *
      * @param handle the handle of the page
-     * @param level the level of the parent
+     * @param level  the level of the parent
      */
     public static String getRelativeParent(String handle, int level) {
-	int idx = handle.length();
-	while (level > 0) {
-	    idx = handle.lastIndexOf('/',idx-1);
-	    if (idx < 0) {
-		return "";
-	    }
-	    level--;
-	}
-	return (idx == 0) ? "/" : handle.substring(0,idx);
+        int idx = handle.length();
+        while (level > 0) {
+            idx = handle.lastIndexOf('/', idx - 1);
+            if (idx < 0) {
+                return "";
+            }
+            level--;
+        }
+        return (idx == 0) ? "/" : handle.substring(0, idx);
     }
 
     /**
@@ -486,26 +538,26 @@
      * </code>
      *
      * @param handle the handle of the page
-     * @param level the level of the parent
+     * @param level  the level of the parent
      */
     public static String getAbsoluteParent(String handle, int level) {
-	int idx = 0;
+        int idx = 0;
         int len = handle.length();
-	while (level >= 0 && idx<len) {
-	    idx = handle.indexOf('/', idx+1);
-	    if (idx < 0) {
-		idx=len;
-	    }
-	    level--;
-	}
-	return level>=0 ? "" : handle.substring(0,idx);
+        while (level >= 0 && idx < len) {
+            idx = handle.indexOf('/', idx + 1);
+            if (idx < 0) {
+                idx = len;
+            }
+            level--;
+        }
+        return level >= 0 ? "" : handle.substring(0, idx);
     }
 
     /**
      * The list of characters that are not encoded by the <code>escape()</code>
      * and <code>unescape()</code> METHODS. They contains the characters as
      * defined 'unreserved' in section 2.3 of the RFC 2396 'URI genric syntax':
-     *
+     * <p/>
      * <pre>
      * unreserved  = alphanum | mark
      * mark        = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
@@ -519,26 +571,26 @@
     public static BitSet URISaveEx;
 
     static {
-	URISave = new BitSet(256);
-	int i;
-	for (i = 'a'; i <= 'z'; i++) {
-	    URISave.set(i);
-	}
-	for (i = 'A'; i <= 'Z'; i++) {
-	    URISave.set(i);
-	}
-	for (i = '0'; i <= '9'; i++) {
-	    URISave.set(i);
-	}
-	URISave.set('-');
-	URISave.set('_');
-	URISave.set('.');
-	URISave.set('!');
-	URISave.set('~');
-	URISave.set('*');
-	URISave.set('\'');
-	URISave.set('(');
-	URISave.set(')');
+        URISave = new BitSet(256);
+        int i;
+        for (i = 'a'; i <= 'z'; i++) {
+            URISave.set(i);
+        }
+        for (i = 'A'; i <= 'Z'; i++) {
+            URISave.set(i);
+        }
+        for (i = '0'; i <= '9'; i++) {
+            URISave.set(i);
+        }
+        URISave.set('-');
+        URISave.set('_');
+        URISave.set('.');
+        URISave.set('!');
+        URISave.set('~');
+        URISave.set('*');
+        URISave.set('\'');
+        URISave.set('(');
+        URISave.set(')');
 
         URISaveEx = (BitSet) URISave.clone();
         URISaveEx.set('/');
@@ -553,7 +605,6 @@
      * @param string the string to encode.
      * @param escape the escape character.
      * @return the escaped string
-     *
      * @throws NullPointerException if <code>string</code> is <code>null</code>.
      */
     public static String escape(String string, char escape) {
@@ -570,29 +621,27 @@
      * @param string the string to encode.
      * @param escape the escape character.
      * @param isPath if <code>true</code>, the string is treated as path
-     *
      * @return the escaped string
-     *
      * @throws NullPointerException if <code>string</code> is <code>null</code>.
      */
     public static String escape(String string, char escape, boolean isPath) {
-	try {
-	    BitSet validChars = isPath ? URISaveEx : URISave;
-	    byte[] bytes = string.getBytes("utf-8");
-	    StringBuffer out = new StringBuffer(bytes.length);
-	    for (int i = 0; i < bytes.length; i++) {
-		int c = bytes[i]&0xff;
-		if (validChars.get(c) && c!=escape) {
-		    out.append((char)c);
-		} else {
-		    out.append(escape);
-		    out.append(hexTable[(c>>4) & 0x0f]);
-		    out.append(hexTable[(c   ) & 0x0f]);
-		}
-	    }
-	    return out.toString();
-	} catch (UnsupportedEncodingException e) {
-	    throw new InternalError(e.toString());
+        try {
+            BitSet validChars = isPath ? URISaveEx : URISave;
+            byte[] bytes = string.getBytes("utf-8");
+            StringBuffer out = new StringBuffer(bytes.length);
+            for (int i = 0; i < bytes.length; i++) {
+                int c = bytes[i] & 0xff;
+                if (validChars.get(c) && c != escape) {
+                    out.append((char) c);
+                } else {
+                    out.append(escape);
+                    out.append(HEXTABLE[(c >> 4) & 0x0f]);
+                    out.append(HEXTABLE[(c) & 0x0f]);
+                }
+            }
+            return out.toString();
+        } catch (UnsupportedEncodingException e) {
+            throw new InternalError(e.toString());
         }
     }
 
@@ -603,11 +652,10 @@
      *
      * @param string the string to encode
      * @return the escaped string
-     *
      * @throws NullPointerException if <code>string</code> is <code>null</code>.
      */
     public static String escape(String string) {
-	return escape(string, '%');
+        return escape(string, '%');
     }
 
     /**
@@ -619,47 +667,46 @@
      *
      * @param path the path to encode
      * @return the escaped path
-     *
      * @throws NullPointerException if <code>path</code> is <code>null</code>.
      */
     public static String escapePath(String path) {
-	return escape(path, '%', true);
+        return escape(path, '%', true);
     }
 
     /**
      * Does a URL decoding of the <code>string</code> using the
      * <code>escape</code> character. Please note that in opposite to the
      * {@link java.net.URLDecoder} it does not transform the + into spaces.
+     *
      * @param string the string to decode
      * @param escape the escape character
      * @return the decoded string
-     *
-     * @throws NullPointerException if <code>string</code> is <code>null</code>.
+     * @throws NullPointerException           if <code>string</code> is <code>null</code>.
      * @throws ArrayIndexOutOfBoundsException if not enough character follow an
-     *         escape character
-     * @throws IllegalArgumentException if the 2 characters following the escape
-     *         character do not represent a hex-number.
+     *                                        escape character
+     * @throws IllegalArgumentException       if the 2 characters following the escape
+     *                                        character do not represent a hex-number.
      */
     public static String unescape(String string, char escape) {
-	ByteArrayOutputStream out = new ByteArrayOutputStream(string.length());
-        for (int i=0; i<string.length(); i++) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream(string.length());
+        for (int i = 0; i < string.length(); i++) {
             char c = string.charAt(i);
-	    if (c==escape) {
-		try {
-		    out.write(Integer.parseInt(string.substring(i+1,i+3),16));
-		} catch (NumberFormatException e) {
-		    throw new IllegalArgumentException();
-		}
-		i += 2;
-	    } else {
-		out.write(c);
+            if (c == escape) {
+                try {
+                    out.write(Integer.parseInt(string.substring(i + 1, i + 3), 16));
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException();
+                }
+                i += 2;
+            } else {
+                out.write(c);
             }
         }
 
         try {
-	    return new String(out.toByteArray(), "utf-8");
+            return new String(out.toByteArray(), "utf-8");
         } catch (UnsupportedEncodingException e) {
-	    throw new InternalError(e.toString());
+            throw new InternalError(e.toString());
         }
     }
 
@@ -670,15 +717,14 @@
      *
      * @param string the string to decode
      * @return the decoded string
-     *
-     * @throws NullPointerException if <code>string</code> is <code>null</code>.
+     * @throws NullPointerException           if <code>string</code> is <code>null</code>.
      * @throws ArrayIndexOutOfBoundsException if not enough character follow an
-     *         escape character
-     * @throws IllegalArgumentException if the 2 characters following the escape
-     *         character do not represent a hex-number.
+     *                                        escape character
+     * @throws IllegalArgumentException       if the 2 characters following the escape
+     *                                        character do not represent a hex-number.
      */
     public static String unescape(String string) {
-	return unescape(string, '%');
+        return unescape(string, '%');
     }
 
     /**
@@ -695,15 +741,14 @@
      * Implements a date formatting routine supporting (a subset) of the POSIX
      * <code>strftime()</code> function.
      *
-     * @param date The date value to be formatted
+     * @param date          The date value to be formatted
      * @param formatPattern The pattern used to format the date. This pattern
-     * 		supports a subset of the pattern characters of the POSIX
-     * 		<code>strftime()</code> function. If this pattern is empty or
-     * 		<code>null</code> the default pattern
-     * 		<code>dd.MM.yyyy HH:mm:ss</code> is used.
-     * @param zone Defines for which time zone the date should be outputted. If
-     *      this parameter is <code>null</code>, then the local time zone is taken.
-     *
+     *                      supports a subset of the pattern characters of the POSIX
+     *                      <code>strftime()</code> function. If this pattern is empty or
+     *                      <code>null</code> the default pattern
+     *                      <code>dd.MM.yyyy HH:mm:ss</code> is used.
+     * @param zone          Defines for which time zone the date should be outputted. If
+     *                      this parameter is <code>null</code>, then the local time zone is taken.
      * @return the formatted date as a String.
      */
     public static final String strftime(Date date, String formatPattern, TimeZone zone) {
@@ -719,7 +764,7 @@
 
         // Reuse the global SimpleDateFormat synchronizing on it to prevent
         // multiple tasks from interfering with each other
-        synchronized(dateFormatter) {
+        synchronized (dateFormatter) {
             dateFormatter.applyPattern(formatPattern);
             dateFormatter.setTimeZone(zone);
             return dateFormatter.format(date);
@@ -730,14 +775,14 @@
      * Implements a date formatting routine supporting (a subset) of the POSIX
      * <code>strftime()</code> function.
      *
-     * @param date The date value to be formatted
+     * @param date          The date value to be formatted
      * @param formatPattern The pattern used to format the date. This pattern
-     * 		supports a subset of the pattern characters of the POSIX
-     * 		<code>strftime()</code> function. If this pattern is empty or
-     * 		<code>null</code> the default pattern
-     * 		<code>dd.MM.yyyy HH:mm:ss</code> is used.
-     * @param   asUTC Defines whether to interpret the date as belong to the UTC
-     * 		time zone or the local time zone.
+     *                      supports a subset of the pattern characters of the POSIX
+     *                      <code>strftime()</code> function. If this pattern is empty or
+     *                      <code>null</code> the default pattern
+     *                      <code>dd.MM.yyyy HH:mm:ss</code> is used.
+     * @param asUTC         Defines whether to interpret the date as belong to the UTC
+     *                      time zone or the local time zone.
      */
     public static final String strftime(Date date, String formatPattern, boolean asUTC) {
         return strftime(date, formatPattern, asUTC ? TIMEZONE_UTC : TIMEZONE_LOCAL);
@@ -748,12 +793,12 @@
      * <code>strftime()</code> function. The default pattern
      * <code>dd.MM.yyyy HH:mm:ss</code> is used to format the date.
      *
-     * @param date The date value to be formatted
+     * @param date  The date value to be formatted
      * @param asUTC Defines whether to interpret the date as belong to the UTC
-     * 		time zone or the local time zone.
+     *              time zone or the local time zone.
      */
     public static final String strftime(Date date, boolean asUTC) {
-	return strftime(date, null, asUTC);
+        return strftime(date, null, asUTC);
     }
 
     /**
@@ -765,56 +810,54 @@
      * @param date The date value to be formatted
      */
     public static final String strftime(Date date) {
-	return strftime(date, null, false);
+        return strftime(date, null, false);
     }
 
     /**
      * Parses the date string based on the format pattern which is in the
      * format used by the Java platfrom SimpleDateFormat class.
      *
-     * @param dateString The date string to be parsed
+     * @param dateString    The date string to be parsed
      * @param formatPattern the pattern to use for parsing. If <code>null</code>
-     * 		or empty, the same default pattern is used as with
-     * 		{@link #strftime(Date, String, boolean)}, namely
-     * 		<code>dd.MM.yyyy HH:mm:ss</code>.
-     *
+     *                      or empty, the same default pattern is used as with
+     *                      {@link #strftime(Date, String, boolean)}, namely
+     *                      <code>dd.MM.yyyy HH:mm:ss</code>.
      * @throws ParseException if the date string cannot be parsed accordinung
-     * 		to the format pattern.
+     *                        to the format pattern.
      */
     public static final Date parseDate(String dateString, String formatPattern)
-	    throws ParseException {
+            throws ParseException {
 
-	return parseDate(dateString, formatPattern, false);
+        return parseDate(dateString, formatPattern, false);
     }
 
     /**
      * Parses the date string based on the format pattern which is in the
      * format used by the Java platfrom SimpleDateFormat class.
      *
-     * @param dateString The date string to be parsed
+     * @param dateString    The date string to be parsed
      * @param formatPattern the pattern to use for parsing. If <code>null</code>
-     * 		or empty, the same default pattern is used as with
-     * 		{@link #strftime(Date, String, boolean)}, namely
-     * 		<code>dd.MM.yyyy HH:mm:ss</code>.
-     * @param isUTC if <code>true</code> the date string is considered in UTC,
-     *        otherwise the default timezone of the host is used.
-     *
+     *                      or empty, the same default pattern is used as with
+     *                      {@link #strftime(Date, String, boolean)}, namely
+     *                      <code>dd.MM.yyyy HH:mm:ss</code>.
+     * @param isUTC         if <code>true</code> the date string is considered in UTC,
+     *                      otherwise the default timezone of the host is used.
      * @throws ParseException if the date string cannot be parsed accordinung
-     * 		to the format pattern.
+     *                        to the format pattern.
      */
     public static final Date parseDate(String dateString, String formatPattern,
-				       boolean isUTC)
-	    throws ParseException {
+                                       boolean isUTC)
+            throws ParseException {
 
-	synchronized (dateFormatter) {
-	    dateFormatter.applyPattern(formatPattern);
-	    if (isUTC) {
-		dateFormatter.setTimeZone(TIMEZONE_UTC);
-	    } else {
-		dateFormatter.setTimeZone(TimeZone.getDefault());
-	    }
-	    return dateFormatter.parse(dateString);
-	}
+        synchronized (dateFormatter) {
+            dateFormatter.applyPattern(formatPattern);
+            if (isUTC) {
+                dateFormatter.setTimeZone(TIMEZONE_UTC);
+            } else {
+                dateFormatter.setTimeZone(TimeZone.getDefault());
+            }
+            return dateFormatter.parse(dateString);
+        }
     }
 
     /**
@@ -822,12 +865,11 @@
      * default format <code>dd.MM.yyyy HH:mm:ss</code>.
      *
      * @param dateString The date string to be parsed
-     *
      * @throws ParseException if the date string cannot be parsed accordinung
-     * 		to the format pattern.
+     *                        to the format pattern.
      */
     public static final Date parseDate(String dateString) throws ParseException {
-	return parseDate(dateString, DEFAULT_DATE_FORMAT_PATTERN, false);
+        return parseDate(dateString, DEFAULT_DATE_FORMAT_PATTERN, false);
     }
 
     /**
@@ -835,73 +877,101 @@
      * default format <code>dd.MM.yyyy HH:mm:ss</code>.
      *
      * @param dateString The date string to be parsed
-     * @param isUTC if <code>true</code> the date string is considered in UTC,
-     *        otherwise the default timezone of the host is used.
-     *
-     *
+     * @param isUTC      if <code>true</code> the date string is considered in UTC,
+     *                   otherwise the default timezone of the host is used.
      * @throws ParseException if the date string cannot be parsed accordinung
-     * 		to the format pattern.
+     *                        to the format pattern.
      */
     public static final Date parseDate(String dateString, boolean isUTC)
-	    throws ParseException {
-	return parseDate(dateString, DEFAULT_DATE_FORMAT_PATTERN, isUTC);
+            throws ParseException {
+        return parseDate(dateString, DEFAULT_DATE_FORMAT_PATTERN, isUTC);
     }
 
     //--------- sprintf() formatting constants ---------------------------------
 
-    /** left justified - '-' flag */
+    /**
+     * left justified - '-' flag
+     */
     private static final int FLAG_LJ = 1;
 
-    /** always show sign - '+' flag */
+    /**
+     * always show sign - '+' flag
+     */
     private static final int FLAG_SI = 2;
 
-    /** space placeholder for omitted plus sign - ' ' flag, ignore if SI */
+    /**
+     * space placeholder for omitted plus sign - ' ' flag, ignore if SI
+     */
     private static final int FLAG_SP = 3;
 
-    /** zero padded if right aligned - '0' flag, ignore if LJ */
+    /**
+     * zero padded if right aligned - '0' flag, ignore if LJ
+     */
     private static final int FLAG_ZE = 4;
 
     /**
      * alternate format - '#' flag :
-     * 	SI  - incr. precision to have zero as first char
-     * 	x   - prefix '0x'
-     * 	X   - prefix '0X'
-     *  eEf - always show decimal point, omit trailing zeroes
-     *  gG  - always show decimal point, show trailing zeroes
+     * SI  - incr. precision to have zero as first char
+     * x   - prefix '0x'
+     * X   - prefix '0X'
+     * eEf - always show decimal point, omit trailing zeroes
+     * gG  - always show decimal point, show trailing zeroes
      */
     private static final int FLAG_AL = 5;
 
-    /** interpret ints as short - 'h' size */
+    /**
+     * interpret ints as short - 'h' size
+     */
     private static final int FLAG_SHORT = 8;
 
-    /** interpret ints as long - 'l' size */
+    /**
+     * interpret ints as long - 'l' size
+     */
     private static final int FLAG_LONG = 9;
 
-    /** waiting for format */
+    /**
+     * waiting for format
+     */
     private static final int PARSE_STATE_NONE = 0;
 
-    /** parsing flags */
+    /**
+     * parsing flags
+     */
     private static final int PARSE_STATE_FLAGS = 1;
 
-    /** parsing wdth */
+    /**
+     * parsing wdth
+     */
     private static final int PARSE_STATE_WIDTH = 2;
 
-    /** parsing precision */
+    /**
+     * parsing precision
+     */
     private static final int PARSE_STATE_PRECISION = 3;
 
-    /** parsing size */
+    /**
+     * parsing size
+     */
     private static final int PARSE_STATE_SIZE = 4;
 
-    /** parsing type */
+    /**
+     * parsing type
+     */
     private static final int PARSE_STATE_TYPE = 5;
 
-    /** parsing finished */
+    /**
+     * parsing finished
+     */
     private static final int PARSE_STATE_END = 6;
 
-    /** incomplete pattern at end of format string, throw error */
+    /**
+     * incomplete pattern at end of format string, throw error
+     */
     private static final int PARSE_STATE_ABORT = 7;
 
-    /** end of format string during plain text */
+    /**
+     * end of format string during plain text
+     */
     private static final int PARSE_STATE_TERM = 8;
 
     /**
@@ -909,7 +979,7 @@
      * formatter in Java. The arguments to the method are the formatting string
      * and the list of arguments defined by the formatting instructions
      * contained in the formatting string.
-     * <p>
+     * <p/>
      * Each element in the argument array is either a <code>Number</code> object
      * or any other <code>Object</code> type. Whenever the formatting string
      * stipulates the corresponding argument to be numeric, it is assumed this
@@ -918,9 +988,9 @@
      * argument is stipulated by the formatting string, a simple call to the
      * <code>toString()</code> method of the object yields the
      * <code>String</code> required.
-     * <p>
+     * <p/>
      * <b>SPECIFICATION</b>
-     * <p>
+     * <p/>
      * <code>sprintf</code> accepts a series of arguments, applies to each a
      * format specifier from <code>format</code>, and stores the formatted data
      * to the result <code>Strint</code>. The method throws an
@@ -929,7 +999,7 @@
      * or if any of the argument's type is wrong. <code>sprintf</code> returns
      * when it  reaches the end of the format string. If there are more
      * arguments than the format requires, excess arguments are ignored.
-     * <p>
+     * <p/>
      * <code>format</code> is a <code>String</code> containing two types of
      * objects: ordinary characters (other than <code><i>%</i></code>), which
      * are copied unchanged to the output, and conversion  specifications,
@@ -937,14 +1007,14 @@
      * <code><i>%</i></code> in the output, use <code>%%</code> in the format
      * string.) A conversion specification has the following form:
      * <blockquote>
-     *   <code>
-     *     [ <i>flags</i> ] [ <i>width</i> ] [ "." <i>prec</i> ] [ <i>size</i> ]
-     *     <i>type</i>
-     *   </code>
+     * <code>
+     * [ <i>flags</i> ] [ <i>width</i> ] [ "." <i>prec</i> ] [ <i>size</i> ]
+     * <i>type</i>
+     * </code>
      * </blockquote>
-     * <p>
+     * <p/>
      * The  fields  of the conversion specification have the following meanings:
-     *
+     * <p/>
      * <dl>
      * <dt><i>flags</i>
      * <dd>an optional sequence of characters  which  control  output
@@ -952,75 +1022,75 @@
      * octal and hex prefixes. The  flag  characters are minus (<code>-</code>),
      * plus (<code>+</code>), space ("<code> </code>"), zero (<code>0</code>),
      * and sharp (<code>#</code> ). They can appear in any combination.
-     *
+     * <p/>
      * <table>
-     *   <tr>
-     *     <td><code>-</code></td>
-     *     <td>The result of the conversion is left justified, and the right
-     *         is  padded with blanks. If you do not use this flag, the result
-     *         is right justified,  and  padded  on  the left.</td>
-     *   </tr>
-     *   <tr>
-     *   <td><code>+</code></td>
-     *   <td>The  result of a signed conversion (as determined by <i>type</i>)
-     *       will always begin with a plus or minus sign. (If you do not use
-     *       this flag, positive values do not begin with a plus sign.)</td>
-     *   </tr>
-     *   <tr>
-     *     <td>"<code> </code>" (space)</td>
-     *     <td>If the first character of a  signed conversion  specification is
-     *         not a sign, or if a signed conversion results in no characters,
-     *         the result will begin  with a space. If the space
-     *         (<code> </code>) flag and the plus (<code>+</code>) flag both
-     *         appear, the space flag is ignored.</td>
-     *   </tr>
-     *   <tr>
-     *     <td><code>0</code></td>
-     *     <td>If the <i>type</i> is <code>d</code>, <code>i</code>,
-     *         <code>o</code>, <code>u</code>, <code>x</code>, <code>X</code>,
-     *         <code>e</code>, <code>E</code>, <code>f</code>, <code>g</code>,
-     *         or <code>G</code>:  leading  zeroes,  are  used to pad the field
-     *         width (following any indication of sign or base); no spaces
-     *         are used  for  padding.  If the zero (<code>0</code>) and minus
-     *         (<code>-</code>) flags both appear, the zero (<code>0</code>)
-     *         flag will be ignored. For <code>d</code>, <code>i</code>,
-     *         <code>o</code>, <code>u</code>, <code>x</code>, <code>X</code>
-     *         conversions, if a precision <i>prec</i> is specified, the zero
-     *         (<code>0</code>) flag is ignored.
-     *         <br>
-     *         Note that <i>0</i> is interpreted as a flag, not as the
-     *         beginning of a field width.</td>
-     *   </tr>
-     *   <tr>
-     *     <td><code>#</code></td>
-     *     <td>The result is to be converted to an alternative form, according
-     *         to the <i>type</i> character:
-     *         <dl>
-     *         <dt><code>o</code>
-     *         <dd>Increases precision to force the first digit of the result
-     *             to be a zero.
-     *
-     *         <dt><code>x</code>
-     *         <dl>A non-zero result will have a <code>0x</code> prefix.
-     *
-     *         <dt><code>X</code>
-     *         <dl>A non-zero result will have a <code>0X</code> prefix.
-     *
-     *         <dt><code>e</code>, <code>E</code>, or <code>f</code>
-     *         <dl>The result will always contain a decimal point even if no
-     *             digits follow the point. (Normally, a decimal point appears
-     *             only if a digit follows it.) Trailing zeroes are removed.
-     *
-     *         <dt><code>g</code> or <code>G</code>
-     *         <dl>Same as <code>e</code> or <code>E</code>, but trailing
-     *             zeroes arenot removed.
-     *
-     *         <dt>all others
-     *         <dd>Undefined.
-     *         </dl></td>
-     *   </tr>
+     * <tr>
+     * <td><code>-</code></td>
+     * <td>The result of the conversion is left justified, and the right
+     * is  padded with blanks. If you do not use this flag, the result
+     * is right justified,  and  padded  on  the left.</td>
+     * </tr>
+     * <tr>
+     * <td><code>+</code></td>
+     * <td>The  result of a signed conversion (as determined by <i>type</i>)
+     * will always begin with a plus or minus sign. (If you do not use
+     * this flag, positive values do not begin with a plus sign.)</td>
+     * </tr>
+     * <tr>
+     * <td>"<code> </code>" (space)</td>
+     * <td>If the first character of a  signed conversion  specification is
+     * not a sign, or if a signed conversion results in no characters,
+     * the result will begin  with a space. If the space
+     * (<code> </code>) flag and the plus (<code>+</code>) flag both
+     * appear, the space flag is ignored.</td>
+     * </tr>
+     * <tr>
+     * <td><code>0</code></td>
+     * <td>If the <i>type</i> is <code>d</code>, <code>i</code>,
+     * <code>o</code>, <code>u</code>, <code>x</code>, <code>X</code>,
+     * <code>e</code>, <code>E</code>, <code>f</code>, <code>g</code>,
+     * or <code>G</code>:  leading  zeroes,  are  used to pad the field
+     * width (following any indication of sign or base); no spaces
+     * are used  for  padding.  If the zero (<code>0</code>) and minus
+     * (<code>-</code>) flags both appear, the zero (<code>0</code>)
+     * flag will be ignored. For <code>d</code>, <code>i</code>,
+     * <code>o</code>, <code>u</code>, <code>x</code>, <code>X</code>
+     * conversions, if a precision <i>prec</i> is specified, the zero
+     * (<code>0</code>) flag is ignored.
+     * <br>
+     * Note that <i>0</i> is interpreted as a flag, not as the
+     * beginning of a field width.</td>
+     * </tr>
+     * <tr>
+     * <td><code>#</code></td>
+     * <td>The result is to be converted to an alternative form, according
+     * to the <i>type</i> character:
+     * <dl>
+     * <dt><code>o</code>
+     * <dd>Increases precision to force the first digit of the result
+     * to be a zero.
+     * <p/>
+     * <dt><code>x</code>
+     * <dl>A non-zero result will have a <code>0x</code> prefix.
+     * <p/>
+     * <dt><code>X</code>
+     * <dl>A non-zero result will have a <code>0X</code> prefix.
+     * <p/>
+     * <dt><code>e</code>, <code>E</code>, or <code>f</code>
+     * <dl>The result will always contain a decimal point even if no
+     * digits follow the point. (Normally, a decimal point appears
+     * only if a digit follows it.) Trailing zeroes are removed.
+     * <p/>
+     * <dt><code>g</code> or <code>G</code>
+     * <dl>Same as <code>e</code> or <code>E</code>, but trailing
+     * zeroes arenot removed.
+     * <p/>
+     * <dt>all others
+     * <dd>Undefined.
+     * </dl></td>
+     * </tr>
      * </table>
-     *
+     * <p/>
      * <dt><i>width</i>
      * <dd><i>width</i> is  an optional minimum field width. You can either
      * specify it directly as a decimal integer, or indirectly by using instead
@@ -1028,7 +1098,7 @@
      * is used as the field width. Negative field widths are not supported; if
      * you attempt to specify a negative field width, it is interpreted as a
      * minus (<code>i</code>) flag followed  by a positive field width.
-     *
+     * <p/>
      * <dt><i>prec</i>
      * <dd>an  optional field; if present, it is introduced with
      * `<code>.</code>' (a period). This field gives the maximum number of
@@ -1045,7 +1115,7 @@
      * omitting the precision.  If only a period is specified  the  precision
      * is zero.  If a precision appears with any other conversion <i>type</i>
      * than those listed here, the behavior is undefined.
-     *
+     * <p/>
      * <dt><i>size</i>
      * <dd><code>h</code>, <code>l</code>, and <code>L</code> are optional size
      * characters which override the default way that <code>sprintf</code>
@@ -1063,91 +1133,91 @@
      * <code>G</code> conversion <i>type</i> to apply to a <code>long
      * double</code> argument. If <code>L</code> appears  with any other
      * conversion <i>type</i>, the behavior is undefined.
-     *
+     * <p/>
      * <dt><i>type</i>
      * <dd><i>type</i> specifies  what  kind of conversion <code>sprintf</code>
      * performs. Here is a table of these:
-     *
-     *   <dl>
-     *   <dt><code>%</code>
-     *   <dd>prints the percent character (<code>%</code>)
-     *
-     *   <dt><code>c</code>
-     *   <dd>prints <i>arg</i> as single character. That is the argument is
-     *       converted to a <code>String</code> of which only the first
-     *       character is printed.
-     *
-     *   <dt><code>s</code>
-     *   <dd>Prints characters until precision is reached or the
-     *       <code>String</code> ends; takes any <code>Object</code> whose
-     *       <code>toString()</code> method is called to get the
-     *       <code>String</code> to print.
-     *
-     *   <dt><code>d</code>
-     *   <dd>prints a signed decimal integer; takes a <code>Number</code> (same
-     *       as <code>i</code>)
-     *
-     *   <dt><code>d</code>
-     *   <dd>prints a signed decimal integer; takes a <code>Number</code> (same
-     *       as <code>d</code>)
-     *
-     *   <dt><code>d</code>
-     *   <dd>prints a signed octal integer; takes a <code>Number</code>
-     *
-     *   <dt><code>u</code>
-     *   <dd>prints a unsigned decimal integer; takes a <code>Number</code>.
-     *       This conversion is not supported correctly by the Java
-     *       implementation and is really the same as <code>i</code>.
-     *
-     *   <dt><code>x</code>
-     *   <dd>prints an unsigned hexadecimal integer (using <i>abcdef</i> as
-     *       digits beyond <i>9</i>; takes a <code>Number</code>
-     *
-     *   <dt><code>X</code>
-     *   <dd>prints an unsigned hexadecimal integer (using <i>ABCDEF</i> as
-     *       digits beyond <i>9</i>; takes a <code>Number</code>
-     *
-     *   <dt><code>f</code>
-     *   <dd>prints a signed value of the form <i>[-]9999.9999</i>; takes a
-     *       <code>Number</code>
-     *
-     *   <dt><code>e</code>
-     *   <dd>prints a signed value of the form <i>[-]9.9999e[+|-]999</i>; takes
-     *       a <code>Number</code>
-     *
-     *   <dt><code>E</code>
-     *   <dd>prints the same way as <code>e</code>, but using <i>E</i> to
-     *       introduce the exponent; takes a <code>Number</code>
-     *
-     *   <dt><code>g</code>
-     *   <dd>prints a signed value in either <code>f</code> or <code>e</code>
-     *       form, based  on given value and precision &emdash; trailing zeros
-     *       and the decimal point are printed only if necessary; takes a
-     *       <code>Number</code>
-     *
-     *   <dt><code>G</code>
-     *   <dd>prints the same way as <code>g</code>, but using <code>E</code>
-     *       for the exponent if an exponent is needed; takes a
-     *       <code>Number</code>
-     *
-     *   <dt><code>n</code>
-     *   <dd>Not supported in the Java implementation, throws an
-     *       <code>IllegalArgumentException</code> if used.
-     *
-     *   <dt><code>p</code>
-     *   <dd>Not supported in the Java implementation, throws an
-     *       <code>IllegalArgumentException</code> if used.
-     *   </dl>
-     *
+     * <p/>
+     * <dl>
+     * <dt><code>%</code>
+     * <dd>prints the percent character (<code>%</code>)
+     * <p/>
+     * <dt><code>c</code>
+     * <dd>prints <i>arg</i> as single character. That is the argument is
+     * converted to a <code>String</code> of which only the first
+     * character is printed.
+     * <p/>
+     * <dt><code>s</code>
+     * <dd>Prints characters until precision is reached or the
+     * <code>String</code> ends; takes any <code>Object</code> whose
+     * <code>toString()</code> method is called to get the
+     * <code>String</code> to print.
+     * <p/>
+     * <dt><code>d</code>
+     * <dd>prints a signed decimal integer; takes a <code>Number</code> (same
+     * as <code>i</code>)
+     * <p/>
+     * <dt><code>d</code>
+     * <dd>prints a signed decimal integer; takes a <code>Number</code> (same
+     * as <code>d</code>)
+     * <p/>
+     * <dt><code>d</code>
+     * <dd>prints a signed octal integer; takes a <code>Number</code>
+     * <p/>
+     * <dt><code>u</code>
+     * <dd>prints a unsigned decimal integer; takes a <code>Number</code>.
+     * This conversion is not supported correctly by the Java
+     * implementation and is really the same as <code>i</code>.
+     * <p/>
+     * <dt><code>x</code>
+     * <dd>prints an unsigned hexadecimal integer (using <i>abcdef</i> as
+     * digits beyond <i>9</i>; takes a <code>Number</code>
+     * <p/>
+     * <dt><code>X</code>
+     * <dd>prints an unsigned hexadecimal integer (using <i>ABCDEF</i> as
+     * digits beyond <i>9</i>; takes a <code>Number</code>
+     * <p/>
+     * <dt><code>f</code>
+     * <dd>prints a signed value of the form <i>[-]9999.9999</i>; takes a
+     * <code>Number</code>
+     * <p/>
+     * <dt><code>e</code>
+     * <dd>prints a signed value of the form <i>[-]9.9999e[+|-]999</i>; takes
+     * a <code>Number</code>
+     * <p/>
+     * <dt><code>E</code>
+     * <dd>prints the same way as <code>e</code>, but using <i>E</i> to
+     * introduce the exponent; takes a <code>Number</code>
+     * <p/>
+     * <dt><code>g</code>
+     * <dd>prints a signed value in either <code>f</code> or <code>e</code>
+     * form, based  on given value and precision &emdash; trailing zeros
+     * and the decimal point are printed only if necessary; takes a
+     * <code>Number</code>
+     * <p/>
+     * <dt><code>G</code>
+     * <dd>prints the same way as <code>g</code>, but using <code>E</code>
+     * for the exponent if an exponent is needed; takes a
+     * <code>Number</code>
+     * <p/>
+     * <dt><code>n</code>
+     * <dd>Not supported in the Java implementation, throws an
+     * <code>IllegalArgumentException</code> if used.
+     * <p/>
+     * <dt><code>p</code>
+     * <dd>Not supported in the Java implementation, throws an
+     * <code>IllegalArgumentException</code> if used.
      * </dl>
-     *
-     * <p>
+     * <p/>
+     * </dl>
+     * <p/>
+     * <p/>
      * <b>IMPLEMENTATION NOTES</b>
-     * <p>
+     * <p/>
      * Due to the nature of the Java programming language, neither pointer
      * conversions, nor <code>unsigned</code> and <code>long double</code>
      * conversions are supported.
-     * <p>
+     * <p/>
      * Also the Java implementation only distinguishes between
      * <code>Number</code> and other <code>Object</code> arguments. If a
      * numeric argument is expected as per the <code>format</code>
@@ -1158,267 +1228,271 @@
      * to a <code>String</code>.
      *
      * @param format The format string as known from the POSIX sprintf()
-     * 		C function.
-     * @param args The list of arguments to accomodate the format string. This
-     * 		argument list is supposed to contain at least as much entries as
-     * 		there are formatting options in the format string. If for a
-     * 		numeric option, the entry is not a number an
-     * 		<code>IllegalArgumentException</code> is thrown.
-     *
+     *               C function.
+     * @param args   The list of arguments to accomodate the format string. This
+     *               argument list is supposed to contain at least as much entries as
+     *               there are formatting options in the format string. If for a
+     *               numeric option, the entry is not a number an
+     *               <code>IllegalArgumentException</code> is thrown.
      * @return The formatted <code>String</code>. An empty <code>String</code>
-     * 		is only returned if the <code>format</code> <code>String</code>
-     * 		is empty. A <code>null</code> value is never returned.
-     *
-     * @throws NullPointerException if the formatting string or any of the
-     * 		argument values is <code>null</code>.
+     *         is only returned if the <code>format</code> <code>String</code>
+     *         is empty. A <code>null</code> value is never returned.
+     * @throws NullPointerException     if the formatting string or any of the
+     *                                  argument values is <code>null</code>.
      * @throws IllegalArgumentException if the formatting string has wrong
-     *         	format tags, if the formatting string has an incomplete
-     * 		formatting pattern at the end of the string, if the argument
-     * 		vector has not enough values to satisfy the formatting string
-     * 		or if an argument's type does not match the requirements of the
-     * 		format string.
-     *
+     *                                  format tags, if the formatting string has an incomplete
+     *                                  formatting pattern at the end of the string, if the argument
+     *                                  vector has not enough values to satisfy the formatting string
+     *                                  or if an argument's type does not match the requirements of the
+     *                                  format string.
      */
     public static String sprintf(String format, Object[] args) {
 
-	// Return immediately if we have no arguments ....
-	if (format == null) {
-	    throw new NullPointerException("format");
-	}
-
-	if (format.length() == 0) {
-	    return "";
-	}
-
-	// Get the format string
-	char[] s = format.toCharArray();
-
-	// prepare the result, initial size has no sound basis
-	StringBuffer res = new StringBuffer( s.length * 3 / 2 );
-
-	for (int i=0,j=0, length=format.length(); i < length; ) {
-
-	    int parse_state = PARSE_STATE_NONE;
-	    BitSet flags = new BitSet(16);
-	    int width = 0;
-	    int precision = -1;
-	    char fmt = ' ';
-
-	    // find a start of a formatting ...
-	    while (parse_state == PARSE_STATE_NONE) {
-		if (i >= length) parse_state = PARSE_STATE_TERM;
-		else if (s[i] == '%') {
-		    if (i < length - 1) {
-			if (s[i + 1] == '%') {
-			    res.append('%');
-			    i++;
-			} else {
-			    parse_state = PARSE_STATE_FLAGS;
-			}
-		    } else {
-			throw new java.lang.IllegalArgumentException(
-			    "Incomplete format at end of format string");
-		    }
-		} else {
-		    res.append(s[i]);
-		}
-		i++;
-	    }
-
-	    // Get flags, if any
-	    while (parse_state == PARSE_STATE_FLAGS) {
-		if (i >= length) parse_state = PARSE_STATE_ABORT;
-		else if (s[i] == ' ') flags.set(FLAG_SP);
-		else if (s[i] == '-') flags.set(FLAG_LJ);
-		else if (s[i] == '+') flags.set(FLAG_SI);
-		else if (s[i] == '0') flags.set(FLAG_ZE);
-		else if (s[i] == '#') flags.set(FLAG_AL);
-		else {
-		    parse_state = PARSE_STATE_WIDTH;
-		    i--;
-		}
-		i++;
-	    }
-
-	    // Get width specification
-	    while (parse_state == PARSE_STATE_WIDTH) {
-		if (i >= length) {
-
-		    parse_state = PARSE_STATE_ABORT;
-
-		} else if ('0' <= s[i] && s[i] <= '9') {
-
-		    width = width * 10 + s[i] - '0';
-		    i++;
-
-		} else {
-		    // finished with digits or none at all
-
-		    // if width is a '*' take width from arg
-		    if (s[i] == '*') {
-			// Check whether we have an argument
-			if (j >= args.length) {
-			    throw new IllegalArgumentException("Missing " +
-				"argument for the width");
-			}
-			try {
-			    width = ((Number)(args[j++])).intValue();
-			} catch (ClassCastException cce) {
-			    // something wrong with the arg
-			    throw new IllegalArgumentException("Width " +
-				"argument is not numeric");
-			}
-			i++;
-		    }
-
-		    // if next is a dot, then we have a precision, else a size
-		    if (s[i] == '.') {
-			parse_state = PARSE_STATE_PRECISION;
-			precision = 0;
-			i++;
-		    } else {
-			parse_state = PARSE_STATE_SIZE;
-		    }
-
-		}
-	    }
-
-	    // Get precision
-	    while (parse_state == PARSE_STATE_PRECISION) {
-
-		if (i >= length) {
-
-		    parse_state = PARSE_STATE_ABORT;
-
-		} else if ('0' <= s[i] && s[i] <= '9') {
-
-		    precision = precision * 10 + s[i] - '0';
-		    i++;
-
-		} else {
-		    // finished with digits or none at all
-
-		    // if width is a '*' take precision from arg
-		    if (s[i] == '*') {
-			// Check whether we have an argument
-			if (j >= args.length) {
-			    throw new IllegalArgumentException("Missing " +
-				"argument for the precision");
-			}
-			try {
-			    width = ((Number)(args[j++])).intValue();
-			} catch (ClassCastException cce) {
-			    // something wrong with the arg
-			    throw new IllegalArgumentException("Precision " +
-				"argument is not numeric");
-			}
-			i++;
-		    }
-
-		    parse_state = PARSE_STATE_SIZE;
-
-		}
-
-	    }
-
-	    // Get size character
-	    if (parse_state == PARSE_STATE_SIZE) {
-		if (i >= length) parse_state = 6;
-		else {
-		    if (s[i] == 'h') {
-			flags.set(FLAG_SHORT);
-			i++;
-		    }  else if (s[i] == 'l' || s[i] == 'L') {
-			flags.set(FLAG_LONG);
-			i++;
-		    }
-		    parse_state = PARSE_STATE_TYPE;
-		}
-	    }
-
-	    // Get format character
-	    if (parse_state == PARSE_STATE_TYPE) {
-		if (i >= length) parse_state = PARSE_STATE_ABORT;
-		else {
-		    fmt = s[i];
-		    i++;
-		    parse_state = PARSE_STATE_END;
-		}
-	    }
-
-	    // Now that we have anything, format it ....
-	    if (parse_state == PARSE_STATE_END) {
-
-		// Check whether we have an argument
-		if (j >= args.length) {
-		    throw new IllegalArgumentException("Not enough parameters for the format string");
-		}
-
-		try {
-
-		    // Convert the argument according to the flag
-		    switch (fmt) {
-			case 'd': // decimal - fall through
-			case 'i': // integral - fall through
-			case 'x': // hexadecimal, lower case - fall through
-			case 'X': // hexadecimal, upper case - fall through
-			case 'o': // octal - fall through
-			case 'u': // unsigned (not really supported)
-			    format(res, (Number)args[j], fmt, width, precision,
-				flags);
-			    break;
-
-			case 'f': // float - fall through
-			case 'e': // exponential, lower case - fall through
-			case 'E': // exponential, upper case - fall through
-			case 'g': // float or exp., lower case - fall through
-			case 'G': // float or exp., upper case - fall through
-			    format(res, ((Number)args[j]).doubleValue(), fmt,
-				width, precision, flags);
-			    break;
-
-			case 'c': // character
-			    precision = 1;
-			    // fall through
-
-			case 's': // string
-
-			    String val = args[j].toString();
-			    if (val.length() > precision && precision > 0) {
-				val = val.substring(0, precision);
-			    }
-
-			    flags.clear(FLAG_ZE);
-			    format(res, val, "", width, flags);
-			    break;
-
-			default : // unknown format
-
-			    throw new IllegalArgumentException("Unknown " +
-				"conversion type " + fmt);
-
-		    }
-
-		} catch (ClassCastException cce) {
-		    // something wrong with the arg
-		    throw new IllegalArgumentException("sprintf: Argument #" +
-			j + " of type " + args[j].getClass().getName() +
-			" does not match format " + fmt);
-		}
-
-		// goto the next argument
-		j++;
-	    }
-
-	    // if the format string is not complete
-	    if (parse_state == PARSE_STATE_ABORT) {
-		throw new java.lang.IllegalArgumentException(
-		    "Incomplete format at end of format string");
-	    }
+        // Return immediately if we have no arguments ....
+        if (format == null) {
+            throw new NullPointerException("format");
+        }
+
+        if (format.length() == 0) {
+            return "";
+        }
+
+        // Get the format string
+        char[] s = format.toCharArray();
+
+        // prepare the result, initial size has no sound basis
+        StringBuffer res = new StringBuffer(s.length * 3 / 2);
+
+        for (int i = 0, j = 0, length = format.length(); i < length;) {
+
+            int parse_state = PARSE_STATE_NONE;
+            BitSet flags = new BitSet(16);
+            int width = 0;
+            int precision = -1;
+            char fmt = ' ';
+
+            // find a start of a formatting ...
+            while (parse_state == PARSE_STATE_NONE) {
+                if (i >= length)
+                    parse_state = PARSE_STATE_TERM;
+                else if (s[i] == '%') {
+                    if (i < length - 1) {
+                        if (s[i + 1] == '%') {
+                            res.append('%');
+                            i++;
+                        } else {
+                            parse_state = PARSE_STATE_FLAGS;
+                        }
+                    } else {
+                        throw new java.lang.IllegalArgumentException("Incomplete format at end of format string");
+                    }
+                } else {
+                    res.append(s[i]);
+                }
+                i++;
+            }
+
+            // Get flags, if any
+            while (parse_state == PARSE_STATE_FLAGS) {
+                if (i >= length)
+                    parse_state = PARSE_STATE_ABORT;
+                else if (s[i] == ' ')
+                    flags.set(FLAG_SP);
+                else if (s[i] == '-')
+                    flags.set(FLAG_LJ);
+                else if (s[i] == '+')
+                    flags.set(FLAG_SI);
+                else if (s[i] == '0')
+                    flags.set(FLAG_ZE);
+                else if (s[i] == '#')
+                    flags.set(FLAG_AL);
+                else {
+                    parse_state = PARSE_STATE_WIDTH;
+                    i--;
+                }
+                i++;
+            }
+
+            // Get width specification
+            while (parse_state == PARSE_STATE_WIDTH) {
+                if (i >= length) {
+
+                    parse_state = PARSE_STATE_ABORT;
+
+                } else if ('0' <= s[i] && s[i] <= '9') {
+
+                    width = width * 10 + s[i] - '0';
+                    i++;
+
+                } else {
+                    // finished with digits or none at all
+
+                    // if width is a '*' take width from arg
+                    if (s[i] == '*') {
+                        // Check whether we have an argument
+                        if (j >= args.length) {
+                            throw new IllegalArgumentException("Missing " +
+                                    "argument for the width");
+                        }
+                        try {
+                            width = ((Number) (args[j++])).intValue();
+                        } catch (ClassCastException cce) {
+                            // something wrong with the arg
+                            throw new IllegalArgumentException("Width " +
+                                    "argument is not numeric");
+                        }
+                        i++;
+                    }
+
+                    // if next is a dot, then we have a precision, else a size
+                    if (s[i] == '.') {
+                        parse_state = PARSE_STATE_PRECISION;
+                        precision = 0;
+                        i++;
+                    } else {
+                        parse_state = PARSE_STATE_SIZE;
+                    }
+
+                }
+            }
+
+            // Get precision
+            while (parse_state == PARSE_STATE_PRECISION) {
+
+                if (i >= length) {
+
+                    parse_state = PARSE_STATE_ABORT;
+
+                } else if ('0' <= s[i] && s[i] <= '9') {
+
+                    precision = precision * 10 + s[i] - '0';
+                    i++;
+
+                } else {
+                    // finished with digits or none at all
+
+                    // if width is a '*' take precision from arg
+                    if (s[i] == '*') {
+                        // Check whether we have an argument
+                        if (j >= args.length) {
+                            throw new IllegalArgumentException("Missing " +
+                                    "argument for the precision");
+                        }
+                        try {
+                            width = ((Number) (args[j++])).intValue();
+                        } catch (ClassCastException cce) {
+                            // something wrong with the arg
+                            throw new IllegalArgumentException("Precision " +
+                                    "argument is not numeric");
+                        }
+                        i++;
+                    }
+
+                    parse_state = PARSE_STATE_SIZE;
+
+                }
+
+            }
+
+            // Get size character
+            if (parse_state == PARSE_STATE_SIZE) {
+                if (i >= length)
+                    parse_state = 6;
+                else {
+                    if (s[i] == 'h') {
+                        flags.set(FLAG_SHORT);
+                        i++;
+                    } else if (s[i] == 'l' || s[i] == 'L') {
+                        flags.set(FLAG_LONG);
+                        i++;
+                    }
+                    parse_state = PARSE_STATE_TYPE;
+                }
+            }
+
+            // Get format character
+            if (parse_state == PARSE_STATE_TYPE) {
+                if (i >= length)
+                    parse_state = PARSE_STATE_ABORT;
+                else {
+                    fmt = s[i];
+                    i++;
+                    parse_state = PARSE_STATE_END;
+                }
+            }
+
+            // Now that we have anything, format it ....
+            if (parse_state == PARSE_STATE_END) {
+
+                // Check whether we have an argument
+                if (j >= args.length) {
+                    throw new IllegalArgumentException("Not enough parameters for the format string");
+                }
+
+                try {
+
+                    // Convert the argument according to the flag
+                    switch (fmt) {
+                        case 'd': // decimal - fall through
+                        case 'i': // integral - fall through
+                        case 'x': // hexadecimal, lower case - fall through
+                        case 'X': // hexadecimal, upper case - fall through
+                        case 'o': // octal - fall through
+                        case 'u': // unsigned (not really supported)
+                            format(res, (Number) args[j], fmt, width, precision,
+                                    flags);
+                            break;
+
+                        case 'f': // float - fall through
+                        case 'e': // exponential, lower case - fall through
+                        case 'E': // exponential, upper case - fall through
+                        case 'g': // float or exp., lower case - fall through
+                        case 'G': // float or exp., upper case - fall through
+                            format(res, ((Number) args[j]).doubleValue(), fmt,
+                                    width, precision, flags);
+                            break;
+
+                        case 'c': // character
+                            precision = 1;
+                            // fall through
+
+                        case 's': // string
+
+                            String val = args[j].toString();
+                            if (val.length() > precision && precision > 0) {
+                                val = val.substring(0, precision);
+                            }
+
+                            flags.clear(FLAG_ZE);
+                            format(res, val, "", width, flags);
+                            break;
+
+                        default : // unknown format
+
+                            throw new IllegalArgumentException("Unknown " +
+                                    "conversion type " + fmt);
+
+                    }
+
+                } catch (ClassCastException cce) {
+                    // something wrong with the arg
+                    throw new IllegalArgumentException("sprintf: Argument #" +
+                            j + " of type " + args[j].getClass().getName() +
+                            " does not match format " + fmt);
+                }
+
+                // goto the next argument
+                j++;
+            }
 
-	} // while i
+            // if the format string is not complete
+            if (parse_state == PARSE_STATE_ABORT) {
+                throw new java.lang.IllegalArgumentException("Incomplete format at end of format string");
+            }
+
+        } // while i
 
-	return res.toString();
+        return res.toString();
     }
 
     /**
@@ -1426,10 +1500,8 @@
      * supports string formats. See {@link #sprintf(String, Object[])} for details.
      *
      * @param format The format string
-     * @param a0 The single parameter
-     *
+     * @param a0     The single parameter
      * @return the result from <code>sprintf(format, new Object[]{ a0 })</code>.
-     *
      * @throws IllegalArgumentException from {@link #sprintf(String, Object[])}.
      */
     public static String sprintf(String format, Object a0) {
@@ -1441,11 +1513,9 @@
      * supports string formats. See {@link #sprintf(String, Object[])} for details.
      *
      * @param format The format string
-     * @param a0 The first parameter
-     * @param a1 The second parameter
-     *
+     * @param a0     The first parameter
+     * @param a1     The second parameter
      * @return the result from <code>sprintf(format, new Object[]{ ... })</code>.
-     *
      * @throws IllegalArgumentException from {@link #sprintf(String, Object[])}.
      */
     public static String sprintf(String format, Object a0, Object a1) {
@@ -1457,16 +1527,14 @@
      * supports string formats. See {@link #sprintf(String, Object[])} for details.
      *
      * @param format The format string
-     * @param a0 The first parameter
-     * @param a1 The second parameter
-     * @param a2 The thrid parameter
-     *
+     * @param a0     The first parameter
+     * @param a1     The second parameter
+     * @param a2     The thrid parameter
      * @return the result from <code>sprintf(format, new Object[]{ ... })</code>.
-     *
      * @throws IllegalArgumentException from {@link #sprintf(String, Object[])}.
      */
     public static String sprintf(String format, Object a0, Object a1,
-        Object a2) {
+                                 Object a2) {
 
         return sprintf(format, new Object[]{a0, a1, a2});
     }
@@ -1476,17 +1544,15 @@
      * supports string formats. See {@link #sprintf(String, Object[])} for details.
      *
      * @param format The format string
-     * @param a0 The first parameter
-     * @param a1 The second parameter
-     * @param a2 The thrid parameter
-     * @param a3 The fourth parameter
-     *
+     * @param a0     The first parameter
+     * @param a1     The second parameter
+     * @param a2     The thrid parameter
+     * @param a3     The fourth parameter
      * @return the result from <code>sprintf(format, new Object[]{ ... })</code>.
-     *
      * @throws IllegalArgumentException from {@link #sprintf(String, Object[])}.
      */
     public static String sprintf(String format, Object a0, Object a1,
-        Object a2, Object a3) {
+                                 Object a2, Object a3) {
 
         return sprintf(format, new Object[]{a0, a1, a2, a3});
     }
@@ -1496,18 +1562,16 @@
      * supports string formats. See {@link #sprintf(String, Object[])} for details.
      *
      * @param format The format string
-     * @param a0 The first parameter
-     * @param a1 The second parameter
-     * @param a2 The thrid parameter
-     * @param a3 The fourth parameter
-     * @param a4 The fifth parameter
-     *
+     * @param a0     The first parameter
+     * @param a1     The second parameter
+     * @param a2     The thrid parameter
+     * @param a3     The fourth parameter
+     * @param a4     The fifth parameter
      * @return the result from <code>sprintf(format, new Object[]{ ... })</code>.
-     *
      * @throws IllegalArgumentException from {@link #sprintf(String, Object[])}.
      */
     public static String sprintf(String format, Object a0, Object a1,
-        Object a2, Object a3, Object a4) {
+                                 Object a2, Object a3, Object a4) {
         return sprintf(format, new Object[]{a0, a1, a2, a3, a4});
     }
 
@@ -1516,10 +1580,10 @@
     /**
      * Convert a Date formatting string in POSIX strftime() format to the
      * pattern format used by the Java SimpleDateFormat class.
-     *
+     * <p/>
      * These are the symbols used in SimpleDateFormat to which we convert
      * our strftime() symbols.
-     *
+     * <p/>
      * <table>
      * <tr><th>Symbol<th>Meaning<th>Presentation<th>Example</tr>
      * <tr><td>G<td>era designator      <td>(Text)     <td>AD</tr>
@@ -1546,205 +1610,205 @@
      *
      * @param posixFormat The formatting pattern in POSIX strftime() format.
      * @return The Date formatting pattern in SimpleDateFormat pattern format.
-     *
-     * todo: Check for the more or less complete support of all pattern tags.
+     *         <p/>
+     *         todo: Check for the more or less complete support of all pattern tags.
      */
     private static String convertFormat(String posixFormat) {
-	char[] format = posixFormat.toCharArray();
-	StringBuffer jFormat = new StringBuffer(format.length);
-	boolean inString = false;
-
-	for (int i=0; i<format.length; i++) {
-
-	    if (format[i] == '\'') {
-
-		// insert a second tick
-		jFormat.append('\'');
-
-	    } else if (format[i] == '%') {
-
-		if (inString) {
-		    jFormat.append('\'');
-		    inString = false;
-		}
-
-		switch(format[++i]) {
-		    case '%':
-			// just a single '%'
-			jFormat.append('%');
-			break;
-
-		    case 'a':
-			// locale's abbreviated weekday name
-			jFormat.append("EEE");
-			break;
-
-		    case 'A':
-			// locale's full weekday name
-			jFormat.append("EEEE");
-			break;
-
-		    case 'b':
-			// locale's abbreviated month name
-			jFormat.append("MMM");
-			break;
-
-		    case 'B':
-			// locale's full month name
-			jFormat.append("MMMM");
-			break;
-
-		    case 'c':
-			// locale's appropriate date and time representation
-			break;
-
-		    case 'C':
-			// century number as a decimal number (00-99)
-			// Not supported
-			break;
-
-		    case 'd':
-			// day of month (01-31)
-			jFormat.append("dd");
-			break;
-
-		    case 'D':
-			// date as %m/%d/%y
-			jFormat.append("MM/dd/yy");
-			break;
-
-		    case 'e':
-			// day of month ( 1-31)
-			jFormat.append("d");
-			break;
-
-		    case 'h':
-			// locale's abbreviated month name
-			jFormat.append("MMM");
-			break;
-
-		    case 'H':
-			// hour (00-23)
-			jFormat.append("HH");
-			break;
-
-		    case 'I':
-			// hour (01-12)
-			jFormat.append("hh");
-			break;
-
-		    case 'j':
-			// day number of year (001-366)
-			jFormat.append("DDD");
-			break;
-
-		    case 'K':
-			// plus C !!!
-			if (format[++i] == 'C') {
-			    // locale's appropriate date and time representation
-			}
-			break;
-
-		    case 'm':
-			// month number (01-12)
-			jFormat.append("MM");
-			break;
-
-		    case 'M':
-			// minute (00-59)
-			jFormat.append("mm");
-			break;
-
-		    case 'n':
-			// new line
-			jFormat.append( System.getProperty("line.separator", "\n") );
-			break;
-
-		    case 'p':
-			// locale's equivalent of either AM and PM
-			jFormat.append("aa");
-			break;
-
-		    case 'r':
-			// locale's 12-hour time representation, default %I:%M:%S [AM|PM]
-			jFormat.append("hh:mm:ss aa");
-			break;
-
-		    case 'R':
-			// time as %H:%M
-			jFormat.append("hh:mm");
-			break;
-
-		    case 'S':
-			// seconds (00-61) [ leap seconds ;-) ]
-			jFormat.append("ss");
-			break;
-
-		    case 't':
-			// tab character
-			jFormat.append( '\t' );
-			break;
-
-		    case 'T':
-			// time as %H:%M:%S
-			jFormat.append("HH:mm:ss");
-			break;
-
-		    case 'U':
-			// week number of year (00-53), sunday is first day of week
-			jFormat.append("ww");
-			break;
-
-		    case 'w':
-			// weekday number (0-6, 0=sunday)
-			jFormat.append("E");
-			break;
-
-		    case 'W':
-			// week number of year (00-53), monday is first day of week
-			jFormat.append("ww");
-			break;
-
-		    case 'x':
-			// locale's appropriate date representation
-			break;
-
-		    case 'X':
-			// locale's appropriate time representation
-			break;
-
-		    case 'y':
-			// year within century (00-99)
-			jFormat.append("yy");
-			break;
-
-		    case 'Y':
-			// year as %c%y (e.g. 1986)
-			jFormat.append("yyyy");
-			break;
-
-		    case 'Z':
-			// time zone name or no characters if no time zone exists
-			jFormat.append("zzz");
-			break;
-
-		    default:
-			// ignore and ...
-			continue;
-		}
-
-	    } else {
-
-		if (!inString) {
-		    inString = true;
-		    jFormat.append('\'');
-		}
-
-		jFormat.append(format[i]);
-	    }
-	}
+        char[] format = posixFormat.toCharArray();
+        StringBuffer jFormat = new StringBuffer(format.length);
+        boolean inString = false;
+
+        for (int i = 0; i < format.length; i++) {
+
+            if (format[i] == '\'') {
+
+                // insert a second tick
+                jFormat.append('\'');
+
+            } else if (format[i] == '%') {
+
+                if (inString) {
+                    jFormat.append('\'');
+                    inString = false;
+                }
+
+                switch (format[++i]) {
+                    case '%':
+                        // just a single '%'
+                        jFormat.append('%');
+                        break;
+
+                    case 'a':
+                        // locale's abbreviated weekday name
+                        jFormat.append("EEE");
+                        break;
+
+                    case 'A':
+                        // locale's full weekday name
+                        jFormat.append("EEEE");
+                        break;
+
+                    case 'b':
+                        // locale's abbreviated month name
+                        jFormat.append("MMM");
+                        break;
+
+                    case 'B':
+                        // locale's full month name
+                        jFormat.append("MMMM");
+                        break;
+
+                    case 'c':
+                        // locale's appropriate date and time representation
+                        break;
+
+                    case 'C':
+                        // century number as a decimal number (00-99)
+                        // Not supported
+                        break;
+
+                    case 'd':
+                        // day of month (01-31)
+                        jFormat.append("dd");
+                        break;
+
+                    case 'D':
+                        // date as %m/%d/%y
+                        jFormat.append("MM/dd/yy");
+                        break;
+
+                    case 'e':
+                        // day of month ( 1-31)
+                        jFormat.append("d");
+                        break;
+
+                    case 'h':
+                        // locale's abbreviated month name
+                        jFormat.append("MMM");
+                        break;
+
+                    case 'H':
+                        // hour (00-23)
+                        jFormat.append("HH");
+                        break;
+
+                    case 'I':
+                        // hour (01-12)
+                        jFormat.append("hh");
+                        break;
+
+                    case 'j':
+                        // day number of year (001-366)
+                        jFormat.append("DDD");
+                        break;
+
+                    case 'K':
+                        // plus C !!!
+                        if (format[++i] == 'C') {
+                            // locale's appropriate date and time representation
+                        }
+                        break;
+
+                    case 'm':
+                        // month number (01-12)
+                        jFormat.append("MM");
+                        break;
+
+                    case 'M':
+                        // minute (00-59)
+                        jFormat.append("mm");
+                        break;
+
+                    case 'n':
+                        // new line
+                        jFormat.append(System.getProperty("line.separator", "\n"));
+                        break;
+
+                    case 'p':
+                        // locale's equivalent of either AM and PM
+                        jFormat.append("aa");
+                        break;
+
+                    case 'r':
+                        // locale's 12-hour time representation, default %I:%M:%S [AM|PM]
+                        jFormat.append("hh:mm:ss aa");
+                        break;
+
+                    case 'R':
+                        // time as %H:%M
+                        jFormat.append("hh:mm");
+                        break;
+
+                    case 'S':
+                        // seconds (00-61) [ leap seconds ;-) ]
+                        jFormat.append("ss");
+                        break;
+
+                    case 't':
+                        // tab character
+                        jFormat.append('\t');
+                        break;
+
+                    case 'T':
+                        // time as %H:%M:%S
+                        jFormat.append("HH:mm:ss");
+                        break;
+
+                    case 'U':
+                        // week number of year (00-53), sunday is first day of week
+                        jFormat.append("ww");
+                        break;
+
+                    case 'w':
+                        // weekday number (0-6, 0=sunday)
+                        jFormat.append("E");
+                        break;
+
+                    case 'W':
+                        // week number of year (00-53), monday is first day of week
+                        jFormat.append("ww");
+                        break;
+
+                    case 'x':
+                        // locale's appropriate date representation
+                        break;
+
+                    case 'X':
+                        // locale's appropriate time representation
+                        break;
+
+                    case 'y':
+                        // year within century (00-99)
+                        jFormat.append("yy");
+                        break;
+
+                    case 'Y':
+                        // year as %c%y (e.g. 1986)
+                        jFormat.append("yyyy");
+                        break;
+
+                    case 'Z':
+                        // time zone name or no characters if no time zone exists
+                        jFormat.append("zzz");
+                        break;
+
+                    default:
+                        // ignore and ...
+                        continue;
+                }
+
+            } else {
+
+                if (!inString) {
+                    inString = true;
+                    jFormat.append('\'');
+                }
+
+                jFormat.append(format[i]);
+            }
+        }
 
-	return jFormat.toString();
+        return jFormat.toString();
     }
 
     /**
@@ -1752,93 +1816,91 @@
      * <code>sprintf()</code> method, that is, this method handles d, i, o, u,
      * x, and X formatting characters.
      *
-     * @param buf The formatted number is appended to this string buffer
-     * @param num The number object to format
-     * @param fmt The format character defining the radix of the number
-     * @param width The minimum field width for the number
+     * @param buf       The formatted number is appended to this string buffer
+     * @param num       The number object to format
+     * @param fmt       The format character defining the radix of the number
+     * @param width     The minimum field width for the number
      * @param precision The minimum number of digits to print for the number,
-     * 		this does not include any signs or prefix characters
-     * @param flags The flags governing the formatting. This is a combination
-     * 		of the FLAG_* constants above.
-     *
+     *                  this does not include any signs or prefix characters
+     * @param flags     The flags governing the formatting. This is a combination
+     *                  of the FLAG_* constants above.
      * @return The formatted string
-     *
      * @see <a href="sprintf.html"><code>sprintf()</code></a>
      */
     private static StringBuffer format(StringBuffer buf, Number num,
-	char fmt, int width, int precision, BitSet flags) {
+                                       char fmt, int width, int precision, BitSet flags) {
 
-	String numStr;
-	String prefStr = "";
-	boolean toUpper = (fmt == 'X');
-
-	// Check precision and make default
-	if (precision >= 0) {
-	    flags.clear(FLAG_ZE);
-	} else {
-	    precision = 1;
-	}
-
-	// Get the value and adjust size interpretation
-	long val;
-	long sizeMask;
-	if (flags.get(FLAG_SHORT)) {
-	    val = num.shortValue();
-	    sizeMask = 0xffffL;
-	} else if (flags.get(FLAG_LONG)) {
-	    val = num.longValue();

[... 488 lines stripped ...]