You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2012/05/18 13:39:32 UTC

[5/7] Update JSON2 classes

http://git-wip-us.apache.org/repos/asf/wicket/blob/0c01d793/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONString.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONString.java b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONString.java
index 61a91b0..00f24d6 100755
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONString.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONString.java
@@ -1,18 +1,19 @@
 package org.apache.wicket.ajax.json;
 
 /**
- * The <code>JSONString</code> interface allows a <code>toJSONString()</code> method so that a class
- * can change the behavior of <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
- * and <code>JSONWriter.value(</code>Object<code>)</code>. The <code>toJSONString</code> method will
- * be used instead of the default behavior of using the Object's <code>toString()</code> method and
- * quoting the result.
+ * The <code>JSONString</code> interface allows a <code>toJSONString()</code> 
+ * method so that a class can change the behavior of 
+ * <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
+ * and <code>JSONWriter.value(</code>Object<code>)</code>. The 
+ * <code>toJSONString</code> method will be used instead of the default behavior 
+ * of using the Object's <code>toString()</code> method and quoting the result.
  */
-public interface JSONString
-{
-	/**
-	 * The <code>toJSONString</code> method allows a class to produce its own JSON serialization.
-	 * 
-	 * @return A strictly syntactically correct JSON text.
-	 */
-	public String toJSONString();
+public interface JSONString {
+    /**
+     * The <code>toJSONString</code> method allows a class to produce its own JSON 
+     * serialization. 
+     * 
+     * @return A strictly syntactically correct JSON text.
+     */
+    public String toJSONString();
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/0c01d793/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONStringer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONStringer.java b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONStringer.java
index 178e6a6..15eb62b 100755
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONStringer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONStringer.java
@@ -1,82 +1,78 @@
 package org.apache.wicket.ajax.json;
 
 /*
- Copyright (c) 2006 JSON.org
+Copyright (c) 2006 JSON.org
 
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
 
- The Software shall be used for Good, not Evil.
+The Software shall be used for Good, not Evil.
 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
 
 import java.io.StringWriter;
 
 /**
- * JSONStringer provides a quick and convenient way of producing JSON text. The texts produced
- * strictly conform to JSON syntax rules. No whitespace is added, so the results are ready for
- * transmission or storage. Each instance of JSONStringer can produce one JSON text.
+ * JSONStringer provides a quick and convenient way of producing JSON text.
+ * The texts produced strictly conform to JSON syntax rules. No whitespace is
+ * added, so the results are ready for transmission or storage. Each instance of
+ * JSONStringer can produce one JSON text.
  * <p>
- * A JSONStringer instance provides a <code>value</code> method for appending values to the text,
- * and a <code>key</code> method for adding keys before values in objects. There are
- * <code>array</code> and <code>endArray</code> methods that make and bound array values, and
- * <code>object</code> and <code>endObject</code> methods which make and bound object values. All of
- * these methods return the JSONWriter instance, permitting cascade style. For example,
- * 
- * <pre>
- * myString = new JSONStringer().object().key(&quot;JSON&quot;).value(&quot;Hello, World!&quot;).endObject().toString();
- * </pre>
- * 
- * which produces the string
- * 
- * <pre>
- * {"JSON":"Hello, World!"}
- * </pre>
+ * A JSONStringer instance provides a <code>value</code> method for appending
+ * values to the
+ * text, and a <code>key</code>
+ * method for adding keys before values in objects. There are <code>array</code>
+ * and <code>endArray</code> methods that make and bound array values, and
+ * <code>object</code> and <code>endObject</code> methods which make and bound
+ * object values. All of these methods return the JSONWriter instance,
+ * permitting cascade style. For example, <pre>
+ * myString = new JSONStringer()
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject()
+ *     .toString();</pre> which produces the string <pre>
+ * {"JSON":"Hello, World!"}</pre>
  * <p>
- * The first method called must be <code>array</code> or <code>object</code>. There are no methods
- * for adding commas or colons. JSONStringer adds them for you. Objects and arrays can be nested up
- * to 20 levels deep.
+ * The first method called must be <code>array</code> or <code>object</code>.
+ * There are no methods for adding commas or colons. JSONStringer adds them for
+ * you. Objects and arrays can be nested up to 20 levels deep.
  * <p>
  * This can sometimes be easier than using a JSONObject to build a string.
- * 
  * @author JSON.org
  * @version 2008-09-18
  */
-public class JSONStringer extends JSONWriter
-{
-	/**
-	 * Make a fresh JSONStringer. It can be used to build one JSON text.
-	 */
-	public JSONStringer()
-	{
-		super(new StringWriter());
-	}
+public class JSONStringer extends JSONWriter {
+    /**
+     * Make a fresh JSONStringer. It can be used to build one JSON text.
+     */
+    public JSONStringer() {
+        super(new StringWriter());
+    }
 
-	/**
-	 * Return the JSON text. This method is used to obtain the product of the JSONStringer instance.
-	 * It will return <code>null</code> if there was a problem in the construction of the JSON text
-	 * (such as the calls to <code>array</code> were not properly balanced with calls to
-	 * <code>endArray</code>).
-	 * 
-	 * @return The JSON text.
-	 */
-	@Override
-	public String toString()
-	{
-		return mode == 'd' ? writer.toString() : null;
-	}
+    /**
+     * Return the JSON text. This method is used to obtain the product of the
+     * JSONStringer instance. It will return <code>null</code> if there was a
+     * problem in the construction of the JSON text (such as the calls to
+     * <code>array</code> were not properly balanced with calls to
+     * <code>endArray</code>).
+     * @return The JSON text.
+     */
+    public String toString() {
+        return this.mode == 'd' ? this.writer.toString() : null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/0c01d793/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONTokener.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONTokener.java b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONTokener.java
index 5717bdf..16c7542 100755
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONTokener.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONTokener.java
@@ -8,510 +8,439 @@ import java.io.Reader;
 import java.io.StringReader;
 
 /*
- Copyright (c) 2002 JSON.org
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- The Software shall be used for Good, not Evil.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
 
 /**
- * A JSONTokener takes a source string and extracts characters and tokens from it. It is used by the
- * JSONObject and JSONArray constructors to parse JSON source strings.
- * 
+ * A JSONTokener takes a source string and extracts characters and tokens from
+ * it. It is used by the JSONObject and JSONArray constructors to parse
+ * JSON source strings.
  * @author JSON.org
- * @version 2010-12-24
+ * @version 2012-02-16
  */
-public class JSONTokener
-{
-
-	private int character;
-	private boolean eof;
-	private int index;
-	private int line;
-	private char previous;
-	private Reader reader;
-	private boolean usePrevious;
-
-
-	/**
-	 * Construct a JSONTokener from a Reader.
-	 * 
-	 * @param reader
-	 *            A reader.
-	 */
-	public JSONTokener(Reader reader)
-	{
-		this.reader = reader.markSupported() ? reader : new BufferedReader(reader);
-		eof = false;
-		usePrevious = false;
-		previous = 0;
-		index = 0;
-		character = 1;
-		line = 1;
-	}
-
-
-	/**
-	 * Construct a JSONTokener from an InputStream.
-	 */
-	public JSONTokener(InputStream inputStream) throws JSONException
-	{
-		this(new InputStreamReader(inputStream));
-	}
-
-
-	/**
-	 * Construct a JSONTokener from a string.
-	 * 
-	 * @param s
-	 *            A source string.
-	 */
-	public JSONTokener(String s)
-	{
-		this(new StringReader(s));
-	}
-
-
-	/**
-	 * Back up one character. This provides a sort of lookahead capability, so that you can test for
-	 * a digit or letter before attempting to parse the next number or identifier.
-	 */
-	public void back() throws JSONException
-	{
-		if (usePrevious || index <= 0)
-		{
-			throw new JSONException("Stepping back two steps is not supported");
-		}
-		index -= 1;
-		character -= 1;
-		usePrevious = true;
-		eof = false;
-	}
-
-
-	/**
-	 * Get the hex value of a character (base16).
-	 * 
-	 * @param c
-	 *            A character between '0' and '9' or between 'A' and 'F' or between 'a' and 'f'.
-	 * @return An int between 0 and 15, or -1 if c was not a hex digit.
-	 */
-	public static int dehexchar(char c)
-	{
-		if (c >= '0' && c <= '9')
-		{
-			return c - '0';
-		}
-		if (c >= 'A' && c <= 'F')
-		{
-			return c - ('A' - 10);
-		}
-		if (c >= 'a' && c <= 'f')
-		{
-			return c - ('a' - 10);
-		}
-		return -1;
-	}
-
-	public boolean end()
-	{
-		return eof && !usePrevious;
-	}
-
-
-	/**
-	 * Determine if the source string still contains characters that next() can consume.
-	 * 
-	 * @return true if not yet at the end of the source.
-	 */
-	public boolean more() throws JSONException
-	{
-		next();
-		if (end())
-		{
-			return false;
-		}
-		back();
-		return true;
-	}
-
-
-	/**
-	 * Get the next character in the source string.
-	 * 
-	 * @return The next character, or 0 if past the end of the source string.
-	 */
-	public char next() throws JSONException
-	{
-		int c;
-		if (usePrevious)
-		{
-			usePrevious = false;
-			c = previous;
-		}
-		else
-		{
-			try
-			{
-				c = reader.read();
-			}
-			catch (IOException exception)
-			{
-				throw new JSONException(exception);
-			}
-
-			if (c <= 0)
-			{ // End of stream
-				eof = true;
-				c = 0;
-			}
-		}
-		index += 1;
-		if (previous == '\r')
-		{
-			line += 1;
-			character = c == '\n' ? 0 : 1;
-		}
-		else if (c == '\n')
-		{
-			line += 1;
-			character = 0;
-		}
-		else
-		{
-			character += 1;
-		}
-		previous = (char)c;
-		return previous;
-	}
-
-
-	/**
-	 * Consume the next character, and check that it matches a specified character.
-	 * 
-	 * @param c
-	 *            The character to match.
-	 * @return The character.
-	 * @throws JSONException
-	 *             if the character does not match.
-	 */
-	public char next(char c) throws JSONException
-	{
-		char n = next();
-		if (n != c)
-		{
-			throw syntaxError("Expected '" + c + "' and instead saw '" + n + "'");
-		}
-		return n;
-	}
-
-
-	/**
-	 * Get the next n characters.
-	 * 
-	 * @param n
-	 *            The number of characters to take.
-	 * @return A string of n characters.
-	 * @throws JSONException
-	 *             Substring bounds error if there are not n characters remaining in the source
-	 *             string.
-	 */
-	public String next(int n) throws JSONException
-	{
-		if (n == 0)
-		{
-			return "";
-		}
-
-		char[] chars = new char[n];
-		int pos = 0;
-
-		while (pos < n)
-		{
-			chars[pos] = next();
-			if (end())
-			{
-				throw syntaxError("Substring bounds error");
-			}
-			pos += 1;
-		}
-		return new String(chars);
-	}
-
-
-	/**
-	 * Get the next char in the string, skipping whitespace.
-	 * 
-	 * @throws JSONException
-	 * @return A character, or 0 if there are no more characters.
-	 */
-	public char nextClean() throws JSONException
-	{
-		for (;;)
-		{
-			char c = next();
-			if (c == 0 || c > ' ')
-			{
-				return c;
-			}
-		}
-	}
-
-
-	/**
-	 * Return the characters up to the next close quote character. Backslash processing is done. The
-	 * formal JSON format does not allow strings in single quotes, but an implementation is allowed
-	 * to accept them.
-	 * 
-	 * @param quote
-	 *            The quoting character, either <code>"</code>&nbsp;<small>(double quote)</small> or
-	 *            <code>'</code>&nbsp;<small>(single quote)</small>.
-	 * @return A String.
-	 * @throws JSONException
-	 *             Unterminated string.
-	 */
-	public String nextString(char quote) throws JSONException
-	{
-		char c;
-		StringBuffer sb = new StringBuffer();
-		for (;;)
-		{
-			c = next();
-			switch (c)
-			{
-				case 0 :
-				case '\n' :
-				case '\r' :
-					throw syntaxError("Unterminated string");
-				case '\\' :
-					c = next();
-					switch (c)
-					{
-						case 'b' :
-							sb.append('\b');
-							break;
-						case 't' :
-							sb.append('\t');
-							break;
-						case 'n' :
-							sb.append('\n');
-							break;
-						case 'f' :
-							sb.append('\f');
-							break;
-						case 'r' :
-							sb.append('\r');
-							break;
-						case 'u' :
-							sb.append((char)Integer.parseInt(next(4), 16));
-							break;
-						case '"' :
-						case '\'' :
-						case '\\' :
-						case '/' :
-							sb.append(c);
-							break;
-						default :
-							throw syntaxError("Illegal escape.");
-					}
-					break;
-				default :
-					if (c == quote)
-					{
-						return sb.toString();
-					}
-					sb.append(c);
-			}
-		}
-	}
-
-
-	/**
-	 * Get the text up but not including the specified character or the end of line, whichever comes
-	 * first.
-	 * 
-	 * @param delimiter
-	 *            A delimiter character.
-	 * @return A string.
-	 */
-	public String nextTo(char delimiter) throws JSONException
-	{
-		StringBuffer sb = new StringBuffer();
-		for (;;)
-		{
-			char c = next();
-			if (c == delimiter || c == 0 || c == '\n' || c == '\r')
-			{
-				if (c != 0)
-				{
-					back();
-				}
-				return sb.toString().trim();
-			}
-			sb.append(c);
-		}
-	}
-
-
-	/**
-	 * Get the text up but not including one of the specified delimiter characters or the end of
-	 * line, whichever comes first.
-	 * 
-	 * @param delimiters
-	 *            A set of delimiter characters.
-	 * @return A string, trimmed.
-	 */
-	public String nextTo(String delimiters) throws JSONException
-	{
-		char c;
-		StringBuffer sb = new StringBuffer();
-		for (;;)
-		{
-			c = next();
-			if (delimiters.indexOf(c) >= 0 || c == 0 || c == '\n' || c == '\r')
-			{
-				if (c != 0)
-				{
-					back();
-				}
-				return sb.toString().trim();
-			}
-			sb.append(c);
-		}
-	}
-
-
-	/**
-	 * Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long,
-	 * or String, or the JSONObject.NULL object.
-	 * 
-	 * @throws JSONException
-	 *             If syntax error.
-	 * 
-	 * @return An object.
-	 */
-	public Object nextValue() throws JSONException
-	{
-		char c = nextClean();
-		String string;
-
-		switch (c)
-		{
-			case '"' :
-			case '\'' :
-				return nextString(c);
-			case '{' :
-				back();
-				return new JSONObject(this);
-			case '[' :
-				back();
-				return new JSONArray(this);
-		}
-
-		/*
-		 * Handle unquoted text. This could be the values true, false, or null, or it can be a
-		 * number. An implementation (such as this one) is allowed to also accept non-standard
-		 * forms.
-		 * 
-		 * Accumulate characters until we reach the end of the text or a formatting character.
-		 */
-
-		StringBuffer sb = new StringBuffer();
-		while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0)
-		{
-			sb.append(c);
-			c = next();
-		}
-		back();
-
-		string = sb.toString().trim();
-		if (string.equals(""))
-		{
-			throw syntaxError("Missing value");
-		}
-		return JSONObject.stringToValue(string);
-	}
-
-
-	/**
-	 * Skip characters until the next character is the requested character. If the requested
-	 * character is not found, no characters are skipped.
-	 * 
-	 * @param to
-	 *            A character to skip to.
-	 * @return The requested character, or zero if the requested character is not found.
-	 */
-	public char skipTo(char to) throws JSONException
-	{
-		char c;
-		try
-		{
-			int startIndex = index;
-			int startCharacter = character;
-			int startLine = line;
-			reader.mark(Integer.MAX_VALUE);
-			do
-			{
-				c = next();
-				if (c == 0)
-				{
-					reader.reset();
-					index = startIndex;
-					character = startCharacter;
-					line = startLine;
-					return c;
-				}
-			}
-			while (c != to);
-		}
-		catch (IOException exc)
-		{
-			throw new JSONException(exc);
-		}
-
-		back();
-		return c;
-	}
-
-
-	/**
-	 * Make a JSONException to signal a syntax error.
-	 * 
-	 * @param message
-	 *            The error message.
-	 * @return A JSONException object, suitable for throwing
-	 */
-	public JSONException syntaxError(String message)
-	{
-		return new JSONException(message + toString());
-	}
-
-
-	/**
-	 * Make a printable string of this JSONTokener.
-	 * 
-	 * @return " at {index} [character {character} line {line}]"
-	 */
-	@Override
-	public String toString()
-	{
-		return " at " + index + " [character " + character + " line " + line + "]";
-	}
-}
\ No newline at end of file
+public class JSONTokener {
+
+    private long    character;
+    private boolean eof;
+    private long    index;
+    private long    line;
+    private char    previous;
+    private Reader  reader;
+    private boolean usePrevious;
+
+
+    /**
+     * Construct a JSONTokener from a Reader.
+     *
+     * @param reader     A reader.
+     */
+    public JSONTokener(Reader reader) {
+        this.reader = reader.markSupported()
+            ? reader
+            : new BufferedReader(reader);
+        this.eof = false;
+        this.usePrevious = false;
+        this.previous = 0;
+        this.index = 0;
+        this.character = 1;
+        this.line = 1;
+    }
+
+
+    /**
+     * Construct a JSONTokener from an InputStream.
+     */
+    public JSONTokener(InputStream inputStream) throws JSONException {
+        this(new InputStreamReader(inputStream));
+    }
+
+
+    /**
+     * Construct a JSONTokener from a string.
+     *
+     * @param s     A source string.
+     */
+    public JSONTokener(String s) {
+        this(new StringReader(s));
+    }
+
+
+    /**
+     * Back up one character. This provides a sort of lookahead capability,
+     * so that you can test for a digit or letter before attempting to parse
+     * the next number or identifier.
+     */
+    public void back() throws JSONException {
+        if (this.usePrevious || this.index <= 0) {
+            throw new JSONException("Stepping back two steps is not supported");
+        }
+        this.index -= 1;
+        this.character -= 1;
+        this.usePrevious = true;
+        this.eof = false;
+    }
+
+
+    /**
+     * Get the hex value of a character (base16).
+     * @param c A character between '0' and '9' or between 'A' and 'F' or
+     * between 'a' and 'f'.
+     * @return  An int between 0 and 15, or -1 if c was not a hex digit.
+     */
+    public static int dehexchar(char c) {
+        if (c >= '0' && c <= '9') {
+            return c - '0';
+        }
+        if (c >= 'A' && c <= 'F') {
+            return c - ('A' - 10);
+        }
+        if (c >= 'a' && c <= 'f') {
+            return c - ('a' - 10);
+        }
+        return -1;
+    }
+
+    public boolean end() {
+        return this.eof && !this.usePrevious;
+    }
+
+
+    /**
+     * Determine if the source string still contains characters that next()
+     * can consume.
+     * @return true if not yet at the end of the source.
+     */
+    public boolean more() throws JSONException {
+        this.next();
+        if (this.end()) {
+            return false;
+        }
+        this.back();
+        return true;
+    }
+
+
+    /**
+     * Get the next character in the source string.
+     *
+     * @return The next character, or 0 if past the end of the source string.
+     */
+    public char next() throws JSONException {
+        int c;
+        if (this.usePrevious) {
+            this.usePrevious = false;
+            c = this.previous;
+        } else {
+            try {
+                c = this.reader.read();
+            } catch (IOException exception) {
+                throw new JSONException(exception);
+            }
+
+            if (c <= 0) { // End of stream
+                this.eof = true;
+                c = 0;
+            }
+        }
+        this.index += 1;
+        if (this.previous == '\r') {
+            this.line += 1;
+            this.character = c == '\n' ? 0 : 1;
+        } else if (c == '\n') {
+            this.line += 1;
+            this.character = 0;
+        } else {
+            this.character += 1;
+        }
+        this.previous = (char) c;
+        return this.previous;
+    }
+
+
+    /**
+     * Consume the next character, and check that it matches a specified
+     * character.
+     * @param c The character to match.
+     * @return The character.
+     * @throws JSONException if the character does not match.
+     */
+    public char next(char c) throws JSONException {
+        char n = this.next();
+        if (n != c) {
+            throw this.syntaxError("Expected '" + c + "' and instead saw '" +
+                    n + "'");
+        }
+        return n;
+    }
+
+
+    /**
+     * Get the next n characters.
+     *
+     * @param n     The number of characters to take.
+     * @return      A string of n characters.
+     * @throws JSONException
+     *   Substring bounds error if there are not
+     *   n characters remaining in the source string.
+     */
+     public String next(int n) throws JSONException {
+         if (n == 0) {
+             return "";
+         }
+
+         char[] chars = new char[n];
+         int pos = 0;
+
+         while (pos < n) {
+             chars[pos] = this.next();
+             if (this.end()) {
+                 throw this.syntaxError("Substring bounds error");
+             }
+             pos += 1;
+         }
+         return new String(chars);
+     }
+
+
+    /**
+     * Get the next char in the string, skipping whitespace.
+     * @throws JSONException
+     * @return  A character, or 0 if there are no more characters.
+     */
+    public char nextClean() throws JSONException {
+        for (;;) {
+            char c = this.next();
+            if (c == 0 || c > ' ') {
+                return c;
+            }
+        }
+    }
+
+
+    /**
+     * Return the characters up to the next close quote character.
+     * Backslash processing is done. The formal JSON format does not
+     * allow strings in single quotes, but an implementation is allowed to
+     * accept them.
+     * @param quote The quoting character, either
+     *      <code>"</code>&nbsp;<small>(double quote)</small> or
+     *      <code>'</code>&nbsp;<small>(single quote)</small>.
+     * @return      A String.
+     * @throws JSONException Unterminated string.
+     */
+    public String nextString(char quote) throws JSONException {
+        char c;
+        StringBuffer sb = new StringBuffer();
+        for (;;) {
+            c = this.next();
+            switch (c) {
+            case 0:
+            case '\n':
+            case '\r':
+                throw this.syntaxError("Unterminated string");
+            case '\\':
+                c = this.next();
+                switch (c) {
+                case 'b':
+                    sb.append('\b');
+                    break;
+                case 't':
+                    sb.append('\t');
+                    break;
+                case 'n':
+                    sb.append('\n');
+                    break;
+                case 'f':
+                    sb.append('\f');
+                    break;
+                case 'r':
+                    sb.append('\r');
+                    break;
+                case 'u':
+                    sb.append((char)Integer.parseInt(this.next(4), 16));
+                    break;
+                case '"':
+                case '\'':
+                case '\\':
+                case '/':
+                    sb.append(c);
+                    break;
+                default:
+                    throw this.syntaxError("Illegal escape.");
+                }
+                break;
+            default:
+                if (c == quote) {
+                    return sb.toString();
+                }
+                sb.append(c);
+            }
+        }
+    }
+
+
+    /**
+     * Get the text up but not including the specified character or the
+     * end of line, whichever comes first.
+     * @param  delimiter A delimiter character.
+     * @return   A string.
+     */
+    public String nextTo(char delimiter) throws JSONException {
+        StringBuffer sb = new StringBuffer();
+        for (;;) {
+            char c = this.next();
+            if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
+                if (c != 0) {
+                    this.back();
+                }
+                return sb.toString().trim();
+            }
+            sb.append(c);
+        }
+    }
+
+
+    /**
+     * Get the text up but not including one of the specified delimiter
+     * characters or the end of line, whichever comes first.
+     * @param delimiters A set of delimiter characters.
+     * @return A string, trimmed.
+     */
+    public String nextTo(String delimiters) throws JSONException {
+        char c;
+        StringBuffer sb = new StringBuffer();
+        for (;;) {
+            c = this.next();
+            if (delimiters.indexOf(c) >= 0 || c == 0 ||
+                    c == '\n' || c == '\r') {
+                if (c != 0) {
+                    this.back();
+                }
+                return sb.toString().trim();
+            }
+            sb.append(c);
+        }
+    }
+
+
+    /**
+     * Get the next value. The value can be a Boolean, Double, Integer,
+     * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
+     * @throws JSONException If syntax error.
+     *
+     * @return An object.
+     */
+    public Object nextValue() throws JSONException {
+        char c = this.nextClean();
+        String string;
+
+        switch (c) {
+            case '"':
+            case '\'':
+                return this.nextString(c);
+            case '{':
+                this.back();
+                return new JSONObject(this);
+            case '[':
+                this.back();
+                return new JSONArray(this);
+        }
+
+        /*
+         * Handle unquoted text. This could be the values true, false, or
+         * null, or it can be a number. An implementation (such as this one)
+         * is allowed to also accept non-standard forms.
+         *
+         * Accumulate characters until we reach the end of the text or a
+         * formatting character.
+         */
+
+        StringBuffer sb = new StringBuffer();
+        while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
+            sb.append(c);
+            c = this.next();
+        }
+        this.back();
+
+        string = sb.toString().trim();
+        if ("".equals(string)) {
+            throw this.syntaxError("Missing value");
+        }
+        return JSONObject.stringToValue(string);
+    }
+
+
+    /**
+     * Skip characters until the next character is the requested character.
+     * If the requested character is not found, no characters are skipped.
+     * @param to A character to skip to.
+     * @return The requested character, or zero if the requested character
+     * is not found.
+     */
+    public char skipTo(char to) throws JSONException {
+        char c;
+        try {
+            long startIndex = this.index;
+            long startCharacter = this.character;
+            long startLine = this.line;
+            this.reader.mark(1000000);
+            do {
+                c = this.next();
+                if (c == 0) {
+                    this.reader.reset();
+                    this.index = startIndex;
+                    this.character = startCharacter;
+                    this.line = startLine;
+                    return c;
+                }
+            } while (c != to);
+        } catch (IOException exc) {
+            throw new JSONException(exc);
+        }
+
+        this.back();
+        return c;
+    }
+
+
+    /**
+     * Make a JSONException to signal a syntax error.
+     *
+     * @param message The error message.
+     * @return  A JSONException object, suitable for throwing
+     */
+    public JSONException syntaxError(String message) {
+        return new JSONException(message + this.toString());
+    }
+
+
+    /**
+     * Make a printable string of this JSONTokener.
+     *
+     * @return " at {index} [character {character} line {line}]"
+     */
+    public String toString() {
+        return " at " + this.index + " [character " + this.character + " line " +
+            this.line + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/0c01d793/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONWriter.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONWriter.java b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONWriter.java
index 2ebece6..7762383 100755
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONWriter.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/json/JSONWriter.java
@@ -4,380 +4,324 @@ import java.io.IOException;
 import java.io.Writer;
 
 /*
- Copyright (c) 2006 JSON.org
+Copyright (c) 2006 JSON.org
 
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
 
- The Software shall be used for Good, not Evil.
+The Software shall be used for Good, not Evil.
 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
 
 /**
- * JSONWriter provides a quick and convenient way of producing JSON text. The texts produced
- * strictly conform to JSON syntax rules. No whitespace is added, so the results are ready for
- * transmission or storage. Each instance of JSONWriter can produce one JSON text.
+ * JSONWriter provides a quick and convenient way of producing JSON text.
+ * The texts produced strictly conform to JSON syntax rules. No whitespace is
+ * added, so the results are ready for transmission or storage. Each instance of
+ * JSONWriter can produce one JSON text.
  * <p>
- * A JSONWriter instance provides a <code>value</code> method for appending values to the text, and
- * a <code>key</code> method for adding keys before values in objects. There are <code>array</code>
- * and <code>endArray</code> methods that make and bound array values, and <code>object</code> and
- * <code>endObject</code> methods which make and bound object values. All of these methods return
- * the JSONWriter instance, permitting a cascade style. For example,
- * 
- * <pre>
- * new JSONWriter(myWriter).object().key(&quot;JSON&quot;).value(&quot;Hello, World!&quot;).endObject();
- * </pre>
- * 
- * which writes
- * 
- * <pre>
- * {"JSON":"Hello, World!"}
- * </pre>
+ * A JSONWriter instance provides a <code>value</code> method for appending
+ * values to the
+ * text, and a <code>key</code>
+ * method for adding keys before values in objects. There are <code>array</code>
+ * and <code>endArray</code> methods that make and bound array values, and
+ * <code>object</code> and <code>endObject</code> methods which make and bound
+ * object values. All of these methods return the JSONWriter instance,
+ * permitting a cascade style. For example, <pre>
+ * new JSONWriter(myWriter)
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject();</pre> which writes <pre>
+ * {"JSON":"Hello, World!"}</pre>
  * <p>
- * The first method called must be <code>array</code> or <code>object</code>. There are no methods
- * for adding commas or colons. JSONWriter adds them for you. Objects and arrays can be nested up to
- * 20 levels deep.
+ * The first method called must be <code>array</code> or <code>object</code>.
+ * There are no methods for adding commas or colons. JSONWriter adds them for
+ * you. Objects and arrays can be nested up to 20 levels deep.
  * <p>
  * This can sometimes be easier than using a JSONObject to build a string.
- * 
  * @author JSON.org
- * @version 2011-11-14
+ * @version 2011-11-24
  */
-public class JSONWriter
-{
-	private static final int maxdepth = 200;
+public class JSONWriter {
+    private static final int maxdepth = 200;
 
-	/**
-	 * The comma flag determines if a comma should be output before the next value.
-	 */
-	private boolean comma;
+    /**
+     * The comma flag determines if a comma should be output before the next
+     * value.
+     */
+    private boolean comma;
 
-	/**
-	 * The current mode. Values: 'a' (array), 'd' (done), 'i' (initial), 'k' (key), 'o' (object).
-	 */
-	protected char mode;
+    /**
+     * The current mode. Values:
+     * 'a' (array),
+     * 'd' (done),
+     * 'i' (initial),
+     * 'k' (key),
+     * 'o' (object).
+     */
+    protected char mode;
 
-	/**
-	 * The object/array stack.
-	 */
-	private final JSONObject stack[];
+    /**
+     * The object/array stack.
+     */
+    private final JSONObject stack[];
 
-	/**
-	 * The stack top index. A value of 0 indicates that the stack is empty.
-	 */
-	private int top;
+    /**
+     * The stack top index. A value of 0 indicates that the stack is empty.
+     */
+    private int top;
 
-	/**
-	 * The writer that will receive the output.
-	 */
-	protected Writer writer;
+    /**
+     * The writer that will receive the output.
+     */
+    protected Writer writer;
 
-	/**
-	 * Make a fresh JSONWriter. It can be used to build one JSON text.
-	 */
-	public JSONWriter(Writer w)
-	{
-		comma = false;
-		mode = 'i';
-		stack = new JSONObject[maxdepth];
-		top = 0;
-		writer = w;
-	}
+    /**
+     * Make a fresh JSONWriter. It can be used to build one JSON text.
+     */
+    public JSONWriter(Writer w) {
+        this.comma = false;
+        this.mode = 'i';
+        this.stack = new JSONObject[maxdepth];
+        this.top = 0;
+        this.writer = w;
+    }
 
-	/**
-	 * Append a value.
-	 * 
-	 * @param string
-	 *            A string value.
-	 * @return this
-	 * @throws JSONException
-	 *             If the value is out of sequence.
-	 */
-	private JSONWriter append(String string) throws JSONException
-	{
-		if (string == null)
-		{
-			throw new JSONException("Null pointer");
-		}
-		if (mode == 'o' || mode == 'a')
-		{
-			try
-			{
-				if (comma && mode == 'a')
-				{
-					writer.write(',');
-				}
-				writer.write(string);
-			}
-			catch (IOException e)
-			{
-				throw new JSONException(e);
-			}
-			if (mode == 'o')
-			{
-				mode = 'k';
-			}
-			comma = true;
-			return this;
-		}
-		throw new JSONException("Value out of sequence.");
-	}
+    /**
+     * Append a value.
+     * @param string A string value.
+     * @return this
+     * @throws JSONException If the value is out of sequence.
+     */
+    private JSONWriter append(String string) throws JSONException {
+        if (string == null) {
+            throw new JSONException("Null pointer");
+        }
+        if (this.mode == 'o' || this.mode == 'a') {
+            try {
+                if (this.comma && this.mode == 'a') {
+                    this.writer.write(',');
+                }
+                this.writer.write(string);
+            } catch (IOException e) {
+                throw new JSONException(e);
+            }
+            if (this.mode == 'o') {
+                this.mode = 'k';
+            }
+            this.comma = true;
+            return this;
+        }
+        throw new JSONException("Value out of sequence.");
+    }
 
-	/**
-	 * Begin appending a new array. All values until the balancing <code>endArray</code> will be
-	 * appended to this array. The <code>endArray</code> method must be called to mark the array's
-	 * end.
-	 * 
-	 * @return this
-	 * @throws JSONException
-	 *             If the nesting is too deep, or if the object is started in the wrong place (for
-	 *             example as a key or after the end of the outermost array or object).
-	 */
-	public JSONWriter array() throws JSONException
-	{
-		if (mode == 'i' || mode == 'o' || mode == 'a')
-		{
-			push(null);
-			append("[");
-			comma = false;
-			return this;
-		}
-		throw new JSONException("Misplaced array.");
-	}
+    /**
+     * Begin appending a new array. All values until the balancing
+     * <code>endArray</code> will be appended to this array. The
+     * <code>endArray</code> method must be called to mark the array's end.
+     * @return this
+     * @throws JSONException If the nesting is too deep, or if the object is
+     * started in the wrong place (for example as a key or after the end of the
+     * outermost array or object).
+     */
+    public JSONWriter array() throws JSONException {
+        if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
+            this.push(null);
+            this.append("[");
+            this.comma = false;
+            return this;
+        }
+        throw new JSONException("Misplaced array.");
+    }
 
-	/**
-	 * End something.
-	 * 
-	 * @param mode
-	 *            Mode
-	 * @param c
-	 *            Closing character
-	 * @return this
-	 * @throws JSONException
-	 *             If unbalanced.
-	 */
-	private JSONWriter end(char mode, char c) throws JSONException
-	{
-		if (this.mode != mode)
-		{
-			throw new JSONException(mode == 'a' ? "Misplaced endArray." : "Misplaced endObject.");
-		}
-		pop(mode);
-		try
-		{
-			writer.write(c);
-		}
-		catch (IOException e)
-		{
-			throw new JSONException(e);
-		}
-		comma = true;
-		return this;
-	}
+    /**
+     * End something.
+     * @param mode Mode
+     * @param c Closing character
+     * @return this
+     * @throws JSONException If unbalanced.
+     */
+    private JSONWriter end(char mode, char c) throws JSONException {
+        if (this.mode != mode) {
+            throw new JSONException(mode == 'a'
+                ? "Misplaced endArray."
+                : "Misplaced endObject.");
+        }
+        this.pop(mode);
+        try {
+            this.writer.write(c);
+        } catch (IOException e) {
+            throw new JSONException(e);
+        }
+        this.comma = true;
+        return this;
+    }
 
-	/**
-	 * End an array. This method most be called to balance calls to <code>array</code>.
-	 * 
-	 * @return this
-	 * @throws JSONException
-	 *             If incorrectly nested.
-	 */
-	public JSONWriter endArray() throws JSONException
-	{
-		return end('a', ']');
-	}
+    /**
+     * End an array. This method most be called to balance calls to
+     * <code>array</code>.
+     * @return this
+     * @throws JSONException If incorrectly nested.
+     */
+    public JSONWriter endArray() throws JSONException {
+        return this.end('a', ']');
+    }
 
-	/**
-	 * End an object. This method most be called to balance calls to <code>object</code>.
-	 * 
-	 * @return this
-	 * @throws JSONException
-	 *             If incorrectly nested.
-	 */
-	public JSONWriter endObject() throws JSONException
-	{
-		return end('k', '}');
-	}
+    /**
+     * End an object. This method most be called to balance calls to
+     * <code>object</code>.
+     * @return this
+     * @throws JSONException If incorrectly nested.
+     */
+    public JSONWriter endObject() throws JSONException {
+        return this.end('k', '}');
+    }
 
-	/**
-	 * Append a key. The key will be associated with the next value. In an object, every value must
-	 * be preceded by a key.
-	 * 
-	 * @param string
-	 *            A key string.
-	 * @return this
-	 * @throws JSONException
-	 *             If the key is out of place. For example, keys do not belong in arrays or if the
-	 *             key is null.
-	 */
-	public JSONWriter key(String string) throws JSONException
-	{
-		if (string == null)
-		{
-			throw new JSONException("Null key.");
-		}
-		if (mode == 'k')
-		{
-			try
-			{
-				stack[top - 1].putOnce(string, Boolean.TRUE);
-				if (comma)
-				{
-					writer.write(',');
-				}
-				writer.write(JSONObject.quote(string));
-				writer.write(':');
-				comma = false;
-				mode = 'o';
-				return this;
-			}
-			catch (IOException e)
-			{
-				throw new JSONException(e);
-			}
-		}
-		throw new JSONException("Misplaced key.");
-	}
+    /**
+     * Append a key. The key will be associated with the next value. In an
+     * object, every value must be preceded by a key.
+     * @param string A key string.
+     * @return this
+     * @throws JSONException If the key is out of place. For example, keys
+     *  do not belong in arrays or if the key is null.
+     */
+    public JSONWriter key(String string) throws JSONException {
+        if (string == null) {
+            throw new JSONException("Null key.");
+        }
+        if (this.mode == 'k') {
+            try {
+                this.stack[this.top - 1].putOnce(string, Boolean.TRUE);
+                if (this.comma) {
+                    this.writer.write(',');
+                }
+                this.writer.write(JSONObject.quote(string));
+                this.writer.write(':');
+                this.comma = false;
+                this.mode = 'o';
+                return this;
+            } catch (IOException e) {
+                throw new JSONException(e);
+            }
+        }
+        throw new JSONException("Misplaced key.");
+    }
 
 
-	/**
-	 * Begin appending a new object. All keys and values until the balancing <code>endObject</code>
-	 * will be appended to this object. The <code>endObject</code> method must be called to mark the
-	 * object's end.
-	 * 
-	 * @return this
-	 * @throws JSONException
-	 *             If the nesting is too deep, or if the object is started in the wrong place (for
-	 *             example as a key or after the end of the outermost array or object).
-	 */
-	public JSONWriter object() throws JSONException
-	{
-		if (mode == 'i')
-		{
-			mode = 'o';
-		}
-		if (mode == 'o' || mode == 'a')
-		{
-			append("{");
-			push(new JSONObject());
-			comma = false;
-			return this;
-		}
-		throw new JSONException("Misplaced object.");
+    /**
+     * Begin appending a new object. All keys and values until the balancing
+     * <code>endObject</code> will be appended to this object. The
+     * <code>endObject</code> method must be called to mark the object's end.
+     * @return this
+     * @throws JSONException If the nesting is too deep, or if the object is
+     * started in the wrong place (for example as a key or after the end of the
+     * outermost array or object).
+     */
+    public JSONWriter object() throws JSONException {
+        if (this.mode == 'i') {
+            this.mode = 'o';
+        }
+        if (this.mode == 'o' || this.mode == 'a') {
+            this.append("{");
+            this.push(new JSONObject());
+            this.comma = false;
+            return this;
+        }
+        throw new JSONException("Misplaced object.");
 
-	}
+    }
 
 
-	/**
-	 * Pop an array or object scope.
-	 * 
-	 * @param c
-	 *            The scope to close.
-	 * @throws JSONException
-	 *             If nesting is wrong.
-	 */
-	private void pop(char c) throws JSONException
-	{
-		if (top <= 0)
-		{
-			throw new JSONException("Nesting error.");
-		}
-		char m = stack[top - 1] == null ? 'a' : 'k';
-		if (m != c)
-		{
-			throw new JSONException("Nesting error.");
-		}
-		top -= 1;
-		mode = top == 0 ? 'd' : stack[top - 1] == null ? 'a' : 'k';
-	}
+    /**
+     * Pop an array or object scope.
+     * @param c The scope to close.
+     * @throws JSONException If nesting is wrong.
+     */
+    private void pop(char c) throws JSONException {
+        if (this.top <= 0) {
+            throw new JSONException("Nesting error.");
+        }
+        char m = this.stack[this.top - 1] == null ? 'a' : 'k';
+        if (m != c) {
+            throw new JSONException("Nesting error.");
+        }
+        this.top -= 1;
+        this.mode = this.top == 0
+            ? 'd'
+            : this.stack[this.top - 1] == null
+            ? 'a'
+            : 'k';
+    }
 
-	/**
-	 * Push an array or object scope.
-	 * 
-	 * @param c
-	 *            The scope to open.
-	 * @throws JSONException
-	 *             If nesting is too deep.
-	 */
-	private void push(JSONObject jo) throws JSONException
-	{
-		if (top >= maxdepth)
-		{
-			throw new JSONException("Nesting too deep.");
-		}
-		stack[top] = jo;
-		mode = jo == null ? 'a' : 'k';
-		top += 1;
-	}
+    /**
+     * Push an array or object scope.
+     * @param c The scope to open.
+     * @throws JSONException If nesting is too deep.
+     */
+    private void push(JSONObject jo) throws JSONException {
+        if (this.top >= maxdepth) {
+            throw new JSONException("Nesting too deep.");
+        }
+        this.stack[this.top] = jo;
+        this.mode = jo == null ? 'a' : 'k';
+        this.top += 1;
+    }
 
 
-	/**
-	 * Append either the value <code>true</code> or the value <code>false</code>.
-	 * 
-	 * @param b
-	 *            A boolean.
-	 * @return this
-	 * @throws JSONException
-	 */
-	public JSONWriter value(boolean b) throws JSONException
-	{
-		return append(b ? "true" : "false");
-	}
+    /**
+     * Append either the value <code>true</code> or the value
+     * <code>false</code>.
+     * @param b A boolean.
+     * @return this
+     * @throws JSONException
+     */
+    public JSONWriter value(boolean b) throws JSONException {
+        return this.append(b ? "true" : "false");
+    }
 
-	/**
-	 * Append a double value.
-	 * 
-	 * @param d
-	 *            A double.
-	 * @return this
-	 * @throws JSONException
-	 *             If the number is not finite.
-	 */
-	public JSONWriter value(double d) throws JSONException
-	{
-		return this.value(new Double(d));
-	}
+    /**
+     * Append a double value.
+     * @param d A double.
+     * @return this
+     * @throws JSONException If the number is not finite.
+     */
+    public JSONWriter value(double d) throws JSONException {
+        return this.value(new Double(d));
+    }
 
-	/**
-	 * Append a long value.
-	 * 
-	 * @param l
-	 *            A long.
-	 * @return this
-	 * @throws JSONException
-	 */
-	public JSONWriter value(long l) throws JSONException
-	{
-		return append(Long.toString(l));
-	}
+    /**
+     * Append a long value.
+     * @param l A long.
+     * @return this
+     * @throws JSONException
+     */
+    public JSONWriter value(long l) throws JSONException {
+        return this.append(Long.toString(l));
+    }
 
 
-	/**
-	 * Append an object value.
-	 * 
-	 * @param object
-	 *            The object to append. It can be null, or a Boolean, Number, String, JSONObject, or
-	 *            JSONArray, or an object that implements JSONString.
-	 * @return this
-	 * @throws JSONException
-	 *             If the value is out of sequence.
-	 */
-	public JSONWriter value(Object object) throws JSONException
-	{
-		return append(JSONObject.valueToString(object));
-	}
+    /**
+     * Append an object value.
+     * @param object The object to append. It can be null, or a Boolean, Number,
+     *   String, JSONObject, or JSONArray, or an object that implements JSONString.
+     * @return this
+     * @throws JSONException If the value is out of sequence.
+     */
+    public JSONWriter value(Object object) throws JSONException {
+        return this.append(JSONObject.valueToString(object));
+    }
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/0c01d793/wicket-core/src/main/java/org/apache/wicket/ajax/json/README
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/json/README b/wicket-core/src/main/java/org/apache/wicket/ajax/json/README
new file mode 100644
index 0000000..6a06271
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/json/README
@@ -0,0 +1,2 @@
+These classes are copied from https://github.com/douglascrockford/JSON-java.
+Last update: May 18 2012
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/0c01d793/wicket-core/src/main/java/org/apache/wicket/ajax/json/XML.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/json/XML.java b/wicket-core/src/main/java/org/apache/wicket/ajax/json/XML.java
index 19ff462..b8705d6 100755
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/json/XML.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/json/XML.java
@@ -1,636 +1,508 @@
 package org.apache.wicket.ajax.json;
 
 /*
- Copyright (c) 2002 JSON.org
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- The Software shall be used for Good, not Evil.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
 
 import java.util.Iterator;
 
 
 /**
- * This provides static methods to convert an XML text into a JSONObject, and to covert a JSONObject
- * into an XML text.
- * 
+ * This provides static methods to convert an XML text into a JSONObject,
+ * and to covert a JSONObject into an XML text.
  * @author JSON.org
  * @version 2011-02-11
  */
-public class XML
-{
-
-	/** The Character '&'. */
-	public static final Character AMP = new Character('&');
-
-	/** The Character '''. */
-	public static final Character APOS = new Character('\'');
-
-	/** The Character '!'. */
-	public static final Character BANG = new Character('!');
-
-	/** The Character '='. */
-	public static final Character EQ = new Character('=');
-
-	/** The Character '>'. */
-	public static final Character GT = new Character('>');
-
-/** The Character '<'. */
-	public static final Character LT = new Character('<');
-
-	/** The Character '?'. */
-	public static final Character QUEST = new Character('?');
-
-	/** The Character '"'. */
-	public static final Character QUOT = new Character('"');
-
-	/** The Character '/'. */
-	public static final Character SLASH = new Character('/');
-
-	/**
-	 * Replace special characters with XML escapes:
-	 * 
-	 * <pre>
-	 * &amp; <small>(ampersand)</small> is replaced by &amp;amp;
-	 * &lt; <small>(less than)</small> is replaced by &amp;lt;
-	 * &gt; <small>(greater than)</small> is replaced by &amp;gt;
-	 * &quot; <small>(double quote)</small> is replaced by &amp;quot;
-	 * </pre>
-	 * 
-	 * @param string
-	 *            The string to be escaped.
-	 * @return The escaped string.
-	 */
-	public static String escape(String string)
-	{
-		StringBuffer sb = new StringBuffer();
-		for (int i = 0, length = string.length(); i < length; i++)
-		{
-			char c = string.charAt(i);
-			switch (c)
-			{
-				case '&' :
-					sb.append("&amp;");
-					break;
-				case '<' :
-					sb.append("&lt;");
-					break;
-				case '>' :
-					sb.append("&gt;");
-					break;
-				case '"' :
-					sb.append("&quot;");
-					break;
-				case '\'' :
-					sb.append("&apos;");
-					break;
-				default :
-					sb.append(c);
-			}
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * Throw an exception if the string contains whitespace. Whitespace is not allowed in tagNames
-	 * and attributes.
-	 * 
-	 * @param string
-	 * @throws JSONException
-	 */
-	public static void noSpace(String string) throws JSONException
-	{
-		int i, length = string.length();
-		if (length == 0)
-		{
-			throw new JSONException("Empty string.");
-		}
-		for (i = 0; i < length; i += 1)
-		{
-			if (Character.isWhitespace(string.charAt(i)))
-			{
-				throw new JSONException("'" + string + "' contains a space character.");
-			}
-		}
-	}
-
-	/**
-	 * Scan the content following the named tag, attaching it to the context.
-	 * 
-	 * @param x
-	 *            The XMLTokener containing the source string.
-	 * @param context
-	 *            The JSONObject that will include the new material.
-	 * @param name
-	 *            The tag name.
-	 * @return true if the close tag is processed.
-	 * @throws JSONException
-	 */
-	private static boolean parse(XMLTokener x, JSONObject context, String name)
-		throws JSONException
-	{
-		char c;
-		int i;
-		JSONObject jsonobject = null;
-		String string;
-		String tagName;
-		Object token;
+public class XML {
+
+    /** The Character '&'. */
+    public static final Character AMP   = new Character('&');
+
+    /** The Character '''. */
+    public static final Character APOS  = new Character('\'');
+
+    /** The Character '!'. */
+    public static final Character BANG  = new Character('!');
+
+    /** The Character '='. */
+    public static final Character EQ    = new Character('=');
+
+    /** The Character '>'. */
+    public static final Character GT    = new Character('>');
+
+    /** The Character '<'. */
+    public static final Character LT    = new Character('<');
+
+    /** The Character '?'. */
+    public static final Character QUEST = new Character('?');
+
+    /** The Character '"'. */
+    public static final Character QUOT  = new Character('"');
+
+    /** The Character '/'. */
+    public static final Character SLASH = new Character('/');
+
+    /**
+     * Replace special characters with XML escapes:
+     * <pre>
+     * &amp; <small>(ampersand)</small> is replaced by &amp;amp;
+     * &lt; <small>(less than)</small> is replaced by &amp;lt;
+     * &gt; <small>(greater than)</small> is replaced by &amp;gt;
+     * &quot; <small>(double quote)</small> is replaced by &amp;quot;
+     * </pre>
+     * @param string The string to be escaped.
+     * @return The escaped string.
+     */
+    public static String escape(String string) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0, length = string.length(); i < length; i++) {
+            char c = string.charAt(i);
+            switch (c) {
+            case '&':
+                sb.append("&amp;");
+                break;
+            case '<':
+                sb.append("&lt;");
+                break;
+            case '>':
+                sb.append("&gt;");
+                break;
+            case '"':
+                sb.append("&quot;");
+                break;
+            case '\'':
+                sb.append("&apos;");
+                break;
+            default:
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+    
+    /**
+     * Throw an exception if the string contains whitespace. 
+     * Whitespace is not allowed in tagNames and attributes.
+     * @param string
+     * @throws JSONException
+     */
+    public static void noSpace(String string) throws JSONException {
+        int i, length = string.length();
+        if (length == 0) {
+            throw new JSONException("Empty string.");
+        }
+        for (i = 0; i < length; i += 1) {
+            if (Character.isWhitespace(string.charAt(i))) {
+                throw new JSONException("'" + string + 
+                        "' contains a space character.");
+            }
+        }
+    }
+
+    /**
+     * Scan the content following the named tag, attaching it to the context.
+     * @param x       The XMLTokener containing the source string.
+     * @param context The JSONObject that will include the new material.
+     * @param name    The tag name.
+     * @return true if the close tag is processed.
+     * @throws JSONException
+     */
+    private static boolean parse(XMLTokener x, JSONObject context,
+                                 String name) throws JSONException {
+        char       c;
+        int        i;
+        JSONObject jsonobject = null;
+        String     string;
+        String     tagName;
+        Object     token;
 
 // Test for and skip past these forms:
-// <!-- ... -->
-// <! ... >
-// <![ ... ]]>
-// <? ... ?>
+//      <!-- ... -->
+//      <!   ...   >
+//      <![  ... ]]>
+//      <?   ...  ?>
 // Report errors for these forms:
-// <>
-// <=
-// <<
+//      <>
+//      <=
+//      <<
 
-		token = x.nextToken();
+        token = x.nextToken();
 
 // <!
 
-		if (token == BANG)
-		{
-			c = x.next();
-			if (c == '-')
-			{
-				if (x.next() == '-')
-				{
-					x.skipPast("-->");
-					return false;
-				}
-				x.back();
-			}
-			else if (c == '[')
-			{
-				token = x.nextToken();
-				if (token.equals("CDATA"))
-				{
-					if (x.next() == '[')
-					{
-						string = x.nextCDATA();
-						if (string.length() > 0)
-						{
-							context.accumulate("content", string);
-						}
-						return false;
-					}
-				}
-				throw x.syntaxError("Expected 'CDATA['");
-			}
-			i = 1;
-			do
-			{
-				token = x.nextMeta();
-				if (token == null)
-				{
-					throw x.syntaxError("Missing '>' after '<!'.");
-				}
-				else if (token == LT)
-				{
-					i += 1;
-				}
-				else if (token == GT)
-				{
-					i -= 1;
-				}
-			}
-			while (i > 0);
-			return false;
-		}
-		else if (token == QUEST)
-		{
+        if (token == BANG) {
+            c = x.next();
+            if (c == '-') {
+                if (x.next() == '-') {
+                    x.skipPast("-->");
+                    return false;
+                }
+                x.back();
+            } else if (c == '[') {
+                token = x.nextToken();
+                if ("CDATA".equals(token)) {
+                    if (x.next() == '[') {
+                        string = x.nextCDATA();
+                        if (string.length() > 0) {
+                            context.accumulate("content", string);
+                        }
+                        return false;
+                    }
+                }
+                throw x.syntaxError("Expected 'CDATA['");
+            }
+            i = 1;
+            do {
+                token = x.nextMeta();
+                if (token == null) {
+                    throw x.syntaxError("Missing '>' after '<!'.");
+                } else if (token == LT) {
+                    i += 1;
+                } else if (token == GT) {
+                    i -= 1;
+                }
+            } while (i > 0);
+            return false;
+        } else if (token == QUEST) {
 
 // <?
 
-			x.skipPast("?>");
-			return false;
-		}
-		else if (token == SLASH)
-		{
+            x.skipPast("?>");
+            return false;
+        } else if (token == SLASH) {
 
 // Close tag </
 
-			token = x.nextToken();
-			if (name == null)
-			{
-				throw x.syntaxError("Mismatched close tag " + token);
-			}
-			if (!token.equals(name))
-			{
-				throw x.syntaxError("Mismatched " + name + " and " + token);
-			}
-			if (x.nextToken() != GT)
-			{
-				throw x.syntaxError("Misshaped close tag");
-			}
-			return true;
-
-		}
-		else if (token instanceof Character)
-		{
-			throw x.syntaxError("Misshaped tag");
+            token = x.nextToken();
+            if (name == null) {
+                throw x.syntaxError("Mismatched close tag " + token);
+            }            
+            if (!token.equals(name)) {
+                throw x.syntaxError("Mismatched " + name + " and " + token);
+            }
+            if (x.nextToken() != GT) {
+                throw x.syntaxError("Misshaped close tag");
+            }
+            return true;
+
+        } else if (token instanceof Character) {
+            throw x.syntaxError("Misshaped tag");
 
 // Open tag <
 
-		}
-		else
-		{
-			tagName = (String)token;
-			token = null;
-			jsonobject = new JSONObject();
-			for (;;)
-			{
-				if (token == null)
-				{
-					token = x.nextToken();
-				}
+        } else {
+            tagName = (String)token;
+            token = null;
+            jsonobject = new JSONObject();
+            for (;;) {
+                if (token == null) {
+                    token = x.nextToken();
+                }
 
 // attribute = value
 
-				if (token instanceof String)
-				{
-					string = (String)token;
-					token = x.nextToken();
-					if (token == EQ)
-					{
-						token = x.nextToken();
-						if (!(token instanceof String))
-						{
-							throw x.syntaxError("Missing value");
-						}
-						jsonobject.accumulate(string, XML.stringToValue((String)token));
-						token = null;
-					}
-					else
-					{
-						jsonobject.accumulate(string, "");
-					}
+                if (token instanceof String) {
+                    string = (String)token;
+                    token = x.nextToken();
+                    if (token == EQ) {
+                        token = x.nextToken();
+                        if (!(token instanceof String)) {
+                            throw x.syntaxError("Missing value");
+                        }
+                        jsonobject.accumulate(string, 
+                                XML.stringToValue((String)token));
+                        token = null;
+                    } else {
+                        jsonobject.accumulate(string, "");
+                    }
 
 // Empty tag <.../>
 
-				}
-				else if (token == SLASH)
-				{
-					if (x.nextToken() != GT)
-					{
-						throw x.syntaxError("Misshaped tag");
-					}
-					if (jsonobject.length() > 0)
-					{
-						context.accumulate(tagName, jsonobject);
-					}
-					else
-					{
-						context.accumulate(tagName, "");
-					}
-					return false;
+                } else if (token == SLASH) {
+                    if (x.nextToken() != GT) {
+                        throw x.syntaxError("Misshaped tag");
+                    }
+                    if (jsonobject.length() > 0) {
+                        context.accumulate(tagName, jsonobject);
+                    } else {
+                        context.accumulate(tagName, "");
+                    }
+                    return false;
 
 // Content, between <...> and </...>
 
-				}
-				else if (token == GT)
-				{
-					for (;;)
-					{
-						token = x.nextContent();
-						if (token == null)
-						{
-							if (tagName != null)
-							{
-								throw x.syntaxError("Unclosed tag " + tagName);
-							}
-							return false;
-						}
-						else if (token instanceof String)
-						{
-							string = (String)token;
-							if (string.length() > 0)
-							{
-								jsonobject.accumulate("content", XML.stringToValue(string));
-							}
+                } else if (token == GT) {
+                    for (;;) {
+                        token = x.nextContent();
+                        if (token == null) {
+                            if (tagName != null) {
+                                throw x.syntaxError("Unclosed tag " + tagName);
+                            }
+                            return false;
+                        } else if (token instanceof String) {
+                            string = (String)token;
+                            if (string.length() > 0) {
+                                jsonobject.accumulate("content", 
+                                        XML.stringToValue(string));
+                            }
 
 // Nested element
 
-						}
-						else if (token == LT)
-						{
-							if (parse(x, jsonobject, tagName))
-							{
-								if (jsonobject.length() == 0)
-								{
-									context.accumulate(tagName, "");
-								}
-								else if (jsonobject.length() == 1 &&
-									jsonobject.opt("content") != null)
-								{
-									context.accumulate(tagName, jsonobject.opt("content"));
-								}
-								else
-								{
-									context.accumulate(tagName, jsonobject);
-								}
-								return false;
-							}
-						}
-					}
-				}
-				else
-				{
-					throw x.syntaxError("Misshaped tag");
-				}
-			}
-		}
-	}
-
-
-	/**
-	 * Try to convert a string into a number, boolean, or null. If the string can't be converted,
-	 * return the string. This is much less ambitious than JSONObject.stringToValue, especially
-	 * because it does not attempt to convert plus forms, octal forms, hex forms, or E forms lacking
-	 * decimal points.
-	 * 
-	 * @param string
-	 *            A String.
-	 * @return A simple JSON value.
-	 */
-	public static Object stringToValue(String string)
-	{
-		if (string.equals(""))
-		{
-			return string;
-		}
-		if (string.equalsIgnoreCase("true"))
-		{
-			return Boolean.TRUE;
-		}
-		if (string.equalsIgnoreCase("false"))
-		{
-			return Boolean.FALSE;
-		}
-		if (string.equalsIgnoreCase("null"))
-		{
-			return JSONObject.NULL;
-		}
-		if (string.equals("0"))
-		{
-			return new Integer(0);
-		}
-
-// If it might be a number, try converting it. If that doesn't work,
+                        } else if (token == LT) {
+                            if (parse(x, jsonobject, tagName)) {
+                                if (jsonobject.length() == 0) {
+                                    context.accumulate(tagName, "");
+                                } else if (jsonobject.length() == 1 &&
+                                       jsonobject.opt("content") != null) {
+                                    context.accumulate(tagName, 
+                                            jsonobject.opt("content"));
+                                } else {
+                                    context.accumulate(tagName, jsonobject);
+                                }
+                                return false;
+                            }
+                        }
+                    }
+                } else {
+                    throw x.syntaxError("Misshaped tag");
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Try to convert a string into a number, boolean, or null. If the string
+     * can't be converted, return the string. This is much less ambitious than
+     * JSONObject.stringToValue, especially because it does not attempt to
+     * convert plus forms, octal forms, hex forms, or E forms lacking decimal 
+     * points.
+     * @param string A String.
+     * @return A simple JSON value.
+     */
+    public static Object stringToValue(String string) {
+        if ("".equals(string)) {
+            return string;
+        }
+        if ("true".equalsIgnoreCase(string)) {
+            return Boolean.TRUE;
+        }
+        if ("false".equalsIgnoreCase(string)) {
+            return Boolean.FALSE;
+        }
+        if ("null".equalsIgnoreCase(string)) {
+            return JSONObject.NULL;
+        }
+        if ("0".equals(string)) {
+            return new Integer(0);
+        }
+
+// If it might be a number, try converting it. If that doesn't work, 
 // return the string.
 
-		try
-		{
-			char initial = string.charAt(0);
-			boolean negative = false;
-			if (initial == '-')
-			{
-				initial = string.charAt(1);
-				negative = true;
-			}
-			if (initial == '0' && string.charAt(negative ? 2 : 1) == '0')
-			{
-				return string;
-			}
-			if ((initial >= '0' && initial <= '9'))
-			{
-				if (string.indexOf('.') >= 0)
-				{
-					return Double.valueOf(string);
-				}
-				else if (string.indexOf('e') < 0 && string.indexOf('E') < 0)
-				{
-					Long myLong = new Long(string);
-					if (myLong.longValue() == myLong.intValue())
-					{
-						return new Integer(myLong.intValue());
-					}
-					else
-					{
-						return myLong;
-					}
-				}
-			}
-		}
-		catch (Exception ignore)
-		{
-		}
-		return string;
-	}
-
-
-	/**
-	 * Convert a well-formed (but not necessarily valid) XML string into a JSONObject. Some
-	 * information may be lost in this transformation because JSON is a data format and XML is a
-	 * document format. XML uses elements, attributes, and content text, while JSON uses unordered
-	 * collections of name/value pairs and arrays of values. JSON does not does not like to
-	 * distinguish between elements and attributes. Sequences of similar elements are represented as
-	 * JSONArrays. Content text may be placed in a "content" member. Comments, prologs, DTDs, and
-	 * <code>&lt;[ [ ]]></code> are ignored.
-	 * 
-	 * @param string
-	 *            The source string.
-	 * @return A JSONObject containing the structured data from the XML string.
-	 * @throws JSONException
-	 */
-	public static JSONObject toJSONObject(String string) throws JSONException
-	{
-		JSONObject jo = new JSONObject();
-		XMLTokener x = new XMLTokener(string);
-		while (x.more() && x.skipPast("<"))
-		{
-			parse(x, jo, null);
-		}
-		return jo;
-	}
-
-
-	/**
-	 * Convert a JSONObject into a well-formed, element-normal XML string.
-	 * 
-	 * @param object
-	 *            A JSONObject.
-	 * @return A string.
-	 * @throws JSONException
-	 */
-	public static String toString(Object object) throws JSONException
-	{
-		return toString(object, null);
-	}
-
-
-	/**
-	 * Convert a JSONObject into a well-formed, element-normal XML string.
-	 * 
-	 * @param object
-	 *            A JSONObject.
-	 * @param tagName
-	 *            The optional name of the enclosing tag.
-	 * @return A string.
-	 * @throws JSONException
-	 */
-	public static String toString(Object object, String tagName) throws JSONException
-	{
-		StringBuffer sb = new StringBuffer();
-		int i;
-		JSONArray ja;
-		JSONObject jo;
-		String key;
-		Iterator keys;
-		int length;
-		String string;
-		Object value;
-		if (object instanceof JSONObject)
-		{
+        try {
+            char initial = string.charAt(0);
+            boolean negative = false;
+            if (initial == '-') {
+                initial = string.charAt(1);
+                negative = true;
+            }
+            if (initial == '0' && string.charAt(negative ? 2 : 1) == '0') {
+                return string;
+            }
+            if ((initial >= '0' && initial <= '9')) {
+                if (string.indexOf('.') >= 0) {
+                    return Double.valueOf(string);
+                } else if (string.indexOf('e') < 0 && string.indexOf('E') < 0) {
+                    Long myLong = new Long(string);
+                    if (myLong.longValue() == myLong.intValue()) {
+                        return new Integer(myLong.intValue());
+                    } else {
+                        return myLong;
+                    }
+                }
+            }
+        }  catch (Exception ignore) {
+        }
+        return string;
+    }
+
+    
+    /**
+     * Convert a well-formed (but not necessarily valid) XML string into a
+     * JSONObject. Some information may be lost in this transformation
+     * because JSON is a data format and XML is a document format. XML uses
+     * elements, attributes, and content text, while JSON uses unordered
+     * collections of name/value pairs and arrays of values. JSON does not
+     * does not like to distinguish between elements and attributes.
+     * Sequences of similar elements are represented as JSONArrays. Content
+     * text may be placed in a "content" member. Comments, prologs, DTDs, and
+     * <code>&lt;[ [ ]]></code> are ignored.
+     * @param string The source string.
+     * @return A JSONObject containing the structured data from the XML string.
+     * @throws JSONException
+     */
+    public static JSONObject toJSONObject(String string) throws JSONException {
+        JSONObject jo = new JSONObject();
+        XMLTokener x = new XMLTokener(string);
+        while (x.more() && x.skipPast("<")) {
+            parse(x, jo, null);
+        }
+        return jo;
+    }
+
+
+    /**
+     * Convert a JSONObject into a well-formed, element-normal XML string.
+     * @param object A JSONObject.
+     * @return  A string.
+     * @throws  JSONException
+     */
+    public static String toString(Object object) throws JSONException {
+        return toString(object, null);
+    }
+
+
+    /**
+     * Convert a JSONObject into a well-formed, element-normal XML string.
+     * @param object A JSONObject.
+     * @param tagName The optional name of the enclosing tag.
+     * @return A string.
+     * @throws JSONException
+     */
+    public static String toString(Object object, String tagName)
+            throws JSONException {
+        StringBuffer sb = new StringBuffer();
+        int          i;
+        JSONArray    ja;
+        JSONObject   jo;
+        String       key;
+        Iterator     keys;
+        int          length;
+        String       string;
+        Object       value;
+        if (object instanceof JSONObject) {
 
 // Emit <tagName>
 
-			if (tagName != null)
-			{
-				sb.append('<');
-				sb.append(tagName);
-				sb.append('>');
-			}
+            if (tagName != null) {
+                sb.append('<');
+                sb.append(tagName);
+                sb.append('>');
+            }
 
 // Loop thru the keys.
 
-			jo = (JSONObject)object;
-			keys = jo.keys();
-			while (keys.hasNext())
-			{
-				key = keys.next().toString();
-				value = jo.opt(key);
-				if (value == null)
-				{
-					value = "";
-				}
-				if (value instanceof String)
-				{
-					string = (String)value;
-				}
-				else
-				{
-					string = null;
-				}
+            jo = (JSONObject)object;
+            keys = jo.keys();
+            while (keys.hasNext()) {
+                key = keys.next().toString();
+                value = jo.opt(key);
+                if (value == null) {
+                    value = "";
+                }
+                if (value instanceof String) {
+                    string = (String)value;
+                } else {
+                    string = null;
+                }
 
 // Emit content in body
 
-				if (key.equals("content"))
-				{
-					if (value instanceof JSONArray)
-					{
-						ja = (JSONArray)value;
-						length = ja.length();
-						for (i = 0; i < length; i += 1)
-						{
-							if (i > 0)
-							{
-								sb.append('\n');
-							}
-							sb.append(escape(ja.get(i).toString()));
-						}
-					}
-					else
-					{
-						sb.append(escape(value.toString()));
-					}
+                if ("content".equals(key)) {
+                    if (value instanceof JSONArray) {
+                        ja = (JSONArray)value;
+                        length = ja.length();
+                        for (i = 0; i < length; i += 1) {
+                            if (i > 0) {
+                                sb.append('\n');
+                            }
+                            sb.append(escape(ja.get(i).toString()));
+                        }
+                    } else {
+                        sb.append(escape(value.toString()));
+                    }
 
 // Emit an array of similar keys
 
-				}
-				else if (value instanceof JSONArray)
-				{
-					ja = (JSONArray)value;
-					length = ja.length();
-					for (i = 0; i < length; i += 1)
-					{
-						value = ja.get(i);
-						if (value instanceof JSONArray)
-						{
-							sb.append('<');
-							sb.append(key);
-							sb.append('>');
-							sb.append(toString(value));
-							sb.append("</");
-							sb.append(key);
-							sb.append('>');
-						}
-						else
-						{
-							sb.append(toString(value, key));
-						}
-					}
-				}
-				else if (value.equals(""))
-				{
-					sb.append('<');
-					sb.append(key);
-					sb.append("/>");
+                } else if (value instanceof JSONArray) {
+                    ja = (JSONArray)value;
+                    length = ja.length();
+                    for (i = 0; i < length; i += 1) {
+                        value = ja.get(i);
+                        if (value instanceof JSONArray) {
+                            sb.append('<');
+                            sb.append(key);
+                            sb.append('>');
+                            sb.append(toString(value));
+                            sb.append("</");
+                            sb.append(key);
+                            sb.append('>');
+                        } else {
+                            sb.append(toString(value, key));
+                        }
+                    }
+                } else if ("".equals(value)) {
+                    sb.append('<');
+                    sb.append(key);
+                    sb.append("/>");
 
 // Emit a new tag <k>
 
-				}
-				else
-				{
-					sb.append(toString(value, key));
-				}
-			}
-			if (tagName != null)
-			{
+                } else {
+                    sb.append(toString(value, key));
+                }
+            }
+            if (tagName != null) {
 
 // Emit the </tagname> close tag
 
-				sb.append("</");
-				sb.append(tagName);
-				sb.append('>');
-			}
-			return sb.toString();
+                sb.append("</");
+                sb.append(tagName);
+                sb.append('>');
+            }
+            return sb.toString();
 
 // XML does not have good support for arrays. If an array appears in a place
 // where XML is lacking, synthesize an <array> element.
 
-		}
-		else
-		{
-			if (object.getClass().isArray())
-			{
-				object = new JSONArray(object);
-			}
-			if (object instanceof JSONArray)
-			{
-				ja = (JSONArray)object;
-				length = ja.length();
-				for (i = 0; i < length; i += 1)
-				{
-					sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName));
-				}
-				return sb.toString();
-			}
-			else
-			{
-				string = (object == null) ? "null" : escape(object.toString());
-				return (tagName == null) ? "\"" + string + "\"" : (string.length() == 0) ? "<" +
-					tagName + "/>" : "<" + tagName + ">" + string + "</" + tagName + ">";
-			}
-		}
-	}
+        } else {
+            if (object.getClass().isArray()) {
+                object = new JSONArray(object);
+            }
+            if (object instanceof JSONArray) {
+                ja = (JSONArray)object;
+                length = ja.length();
+                for (i = 0; i < length; i += 1) {
+                    sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName));
+                }
+                return sb.toString();
+            } else {
+                string = (object == null) ? "null" : escape(object.toString());
+                return (tagName == null) ? "\"" + string + "\"" :
+                    (string.length() == 0) ? "<" + tagName + "/>" :
+                    "<" + tagName + ">" + string + "</" + tagName + ">";
+            }
+        }
+    }
 }
\ No newline at end of file