http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONArray.java
----------------------------------------------------------------------
diff --git 
a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONArray.java
 
b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONArray.java
new file mode 100644
index 0000000..5715db5
--- /dev/null
+++ 
b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONArray.java
@@ -0,0 +1,901 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.vmware.geode.tools.pulse.internal.json;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A JSONArray is an ordered sequence of values. Its external text form is a
+ * string wrapped in square brackets with commas separating the values. The
+ * internal form is an object having <code>get</code> and <code>opt</code>
+ * methods for accessing the values by index, and <code>put</code> methods for
+ * adding or replacing values. The values can be any of these types:
+ * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
+ * <code>Number</code>, <code>String</code>, or the
+ * <code>JSONObject.NULL object</code>.
+ * <p>
+ * The constructor can convert a JSON text into a Java object. The
+ * <code>toString</code> method converts to JSON text.
+ * <p>
+ * A <code>get</code> method returns a value if one can be found, and throws an
+ * exception if one cannot be found. An <code>opt</code> method returns a
+ * default value instead of throwing an exception, and so is useful for
+ * obtaining optional values.
+ * <p>
+ * The generic <code>get()</code> and <code>opt()</code> methods return an
+ * object which you can cast or query for type. There are also typed
+ * <code>get</code> and <code>opt</code> methods that do type checking and type
+ * coercion for you.
+ * <p>
+ * The texts produced by the <code>toString</code> methods strictly conform to
+ * JSON syntax rules. The constructors are more forgiving in the texts they 
will
+ * accept:
+ * <ul>
+ * <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
+ * before the closing bracket.</li>
+ * <li>The <code>null</code> value will be inserted when there is 
<code>,</code>
+ * &nbsp;<small>(comma)</small> elision.</li>
+ * <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single
+ * quote)</small>.</li>
+ * <li>Strings do not need to be quoted at all if they do not begin with a 
quote
+ * or single quote, and if they do not contain leading or trailing spaces, and
+ * if they do not contain any of these characters:
+ * <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers and
+ * if they are not the reserved words <code>true</code>, <code>false</code>, or
+ * <code>null</code>.</li>
+ * <li>Values can be separated by <code>;</code> <small>(semicolon)</small> as
+ * well as by <code>,</code> <small>(comma)</small>.</li>
+ * </ul>
+ *
+ * @author JSON.org
+ * @version 2012-04-20
+ */
+public class JSONArray {
+
+
+    /**
+     * The arrayList where the JSONArray's properties are kept.
+     */
+    private final ArrayList myArrayList;
+
+
+    /**
+     * Construct an empty JSONArray.
+     */
+    public JSONArray() {
+        this.myArrayList = new ArrayList();
+    }
+
+    /**
+     * Construct a JSONArray from a JSONTokener.
+     * @param x A JSONTokener
+     * @throws JSONException If there is a syntax error.
+     */
+    public JSONArray(JSONTokener x) throws JSONException {
+        this();
+        if (x.nextClean() != '[') {
+            throw x.syntaxError("A JSONArray text must start with '['");
+        }
+        if (x.nextClean() != ']') {
+            x.back();
+            for (;;) {
+                if (x.nextClean() == ',') {
+                    x.back();
+                    this.myArrayList.add(JSONObject.NULL);
+                } else {
+                    x.back();
+                    this.myArrayList.add(x.nextValue());
+                }
+                switch (x.nextClean()) {
+                case ';':
+                case ',':
+                    if (x.nextClean() == ']') {
+                        return;
+                    }
+                    x.back();
+                    break;
+                case ']':
+                    return;
+                default:
+                    throw x.syntaxError("Expected a ',' or ']'");
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Construct a JSONArray from a source JSON text.
+     * @param source     A string that begins with
+     * <code>[</code>&nbsp;<small>(left bracket)</small>
+     *  and ends with <code>]</code>&nbsp;<small>(right bracket)</small>.
+     *  @throws JSONException If there is a syntax error.
+     */
+    public JSONArray(String source) throws JSONException {
+        this(new JSONTokener(source));
+    }
+
+
+    /**
+     * Construct a JSONArray from a Collection.
+     * @param collection     A Collection.
+     */
+    public JSONArray(Collection collection) {
+        this.myArrayList = new ArrayList();
+        if (collection != null) {
+            Iterator iter = collection.iterator();
+            while (iter.hasNext()) {
+                this.myArrayList.add(JSONObject.wrap(iter.next()));
+            }
+        }
+    }
+
+
+    /**
+     * Construct a JSONArray from an array
+     * @throws JSONException If not an array.
+     */
+    public JSONArray(Object array) throws JSONException {
+        this();
+        if (array.getClass().isArray()) {
+            int length = Array.getLength(array);
+            for (int i = 0; i < length; i += 1) {
+                this.put(JSONObject.wrap(Array.get(array, i)));
+            }
+        } else {
+            throw new JSONException(
+"JSONArray initial value should be a string or collection or array.");
+        }
+    }
+
+
+    /**
+     * Get the object value associated with an index.
+     * @param index
+     *  The index must be between 0 and length() - 1.
+     * @return An object value.
+     * @throws JSONException If there is no value for the index.
+     */
+    public Object get(int index) throws JSONException {
+        Object object = this.opt(index);
+        if (object == null) {
+            throw new JSONException("JSONArray[" + index + "] not found.");
+        }
+        return object;
+    }
+
+
+    /**
+     * Get the boolean value associated with an index.
+     * The string values "true" and "false" are converted to boolean.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The truth.
+     * @throws JSONException If there is no value for the index or if the
+     *  value is not convertible to boolean.
+     */
+    public boolean getBoolean(int index) throws JSONException {
+        Object object = this.get(index);
+        if (object.equals(Boolean.FALSE) ||
+                (object instanceof String &&
+                ((String)object).equalsIgnoreCase("false"))) {
+            return false;
+        } else if (object.equals(Boolean.TRUE) ||
+                (object instanceof String &&
+                ((String)object).equalsIgnoreCase("true"))) {
+            return true;
+        }
+        throw new JSONException("JSONArray[" + index + "] is not a boolean.");
+    }
+
+
+    /**
+     * Get the double value associated with an index.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The value.
+     * @throws   JSONException If the key is not found or if the value cannot
+     *  be converted to a number.
+     */
+    public double getDouble(int index) throws JSONException {
+        Object object = this.get(index);
+        try {
+            return object instanceof Number
+                ? ((Number)object).doubleValue()
+                : Double.parseDouble((String)object);
+        } catch (Exception e) {
+            throw new JSONException("JSONArray[" + index +
+                "] is not a number.");
+        }
+    }
+
+
+    /**
+     * Get the int value associated with an index.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The value.
+     * @throws   JSONException If the key is not found or if the value is not 
a number.
+     */
+    public int getInt(int index) throws JSONException {
+        Object object = this.get(index);
+        try {
+            return object instanceof Number
+                ? ((Number)object).intValue()
+                : Integer.parseInt((String)object);
+        } catch (Exception e) {
+            throw new JSONException("JSONArray[" + index +
+                "] is not a number.");
+        }
+    }
+
+
+    /**
+     * Get the JSONArray associated with an index.
+     * @param index The index must be between 0 and length() - 1.
+     * @return      A JSONArray value.
+     * @throws JSONException If there is no value for the index. or if the
+     * value is not a JSONArray
+     */
+    public JSONArray getJSONArray(int index) throws JSONException {
+        Object object = this.get(index);
+        if (object instanceof JSONArray) {
+            return (JSONArray)object;
+        }
+        throw new JSONException("JSONArray[" + index +
+                "] is not a JSONArray.");
+    }
+
+
+    /**
+     * Get the JSONObject associated with an index.
+     * @param index subscript
+     * @return      A JSONObject value.
+     * @throws JSONException If there is no value for the index or if the
+     * value is not a JSONObject
+     */
+    public JSONObject getJSONObject(int index) throws JSONException {
+        Object object = this.get(index);
+        if (object instanceof JSONObject) {
+            return (JSONObject)object;
+        }
+        throw new JSONException("JSONArray[" + index +
+            "] is not a JSONObject.");
+    }
+
+
+    /**
+     * Get the long value associated with an index.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The value.
+     * @throws   JSONException If the key is not found or if the value cannot
+     *  be converted to a number.
+     */
+    public long getLong(int index) throws JSONException {
+        Object object = this.get(index);
+        try {
+            return object instanceof Number
+                ? ((Number)object).longValue()
+                : Long.parseLong((String)object);
+        } catch (Exception e) {
+            throw new JSONException("JSONArray[" + index +
+                "] is not a number.");
+        }
+    }
+
+
+    /**
+     * Get the string associated with an index.
+     * @param index The index must be between 0 and length() - 1.
+     * @return      A string value.
+     * @throws JSONException If there is no string value for the index.
+     */
+    public String getString(int index) throws JSONException {
+        Object object = this.get(index);
+        if (object instanceof String) {
+            return (String)object;
+        }
+        throw new JSONException("JSONArray[" + index + "] not a string.");
+    }
+
+
+    /**
+     * Determine if the value is null.
+     * @param index The index must be between 0 and length() - 1.
+     * @return true if the value at the index is null, or if there is no value.
+     */
+    public boolean isNull(int index) {
+        return JSONObject.NULL.equals(this.opt(index));
+    }
+
+
+    /**
+     * Make a string from the contents of this JSONArray. The
+     * <code>separator</code> string is inserted between each element.
+     * Warning: This method assumes that the data structure is acyclical.
+     * @param separator A string that will be inserted between the elements.
+     * @return a string.
+     * @throws JSONException If the array contains an invalid number.
+     */
+    public String join(String separator) throws JSONException {
+        int len = this.length();
+        StringBuffer sb = new StringBuffer();
+
+        for (int i = 0; i < len; i += 1) {
+            if (i > 0) {
+                sb.append(separator);
+            }
+            sb.append(JSONObject.valueToString(this.myArrayList.get(i)));
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * Get the number of elements in the JSONArray, included nulls.
+     *
+     * @return The length (or size).
+     */
+    public int length() {
+        return this.myArrayList.size();
+    }
+
+
+    /**
+     * Get the optional object value associated with an index.
+     * @param index The index must be between 0 and length() - 1.
+     * @return      An object value, or null if there is no
+     *              object at that index.
+     */
+    public Object opt(int index) {
+        return (index < 0 || index >= this.length())
+            ? null
+            : this.myArrayList.get(index);
+    }
+
+
+    /**
+     * Get the optional boolean value associated with an index.
+     * It returns false if there is no value at that index,
+     * or if the value is not Boolean.TRUE or the String "true".
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The truth.
+     */
+    public boolean optBoolean(int index)  {
+        return this.optBoolean(index, false);
+    }
+
+
+    /**
+     * Get the optional boolean value associated with an index.
+     * It returns the defaultValue if there is no value at that index or if
+     * it is not a Boolean or the String "true" or "false" (case insensitive).
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @param defaultValue     A boolean default.
+     * @return      The truth.
+     */
+    public boolean optBoolean(int index, boolean defaultValue)  {
+        try {
+            return this.getBoolean(index);
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+
+
+    /**
+     * Get the optional double value associated with an index.
+     * NaN is returned if there is no value for the index,
+     * or if the value is not a number and cannot be converted to a number.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The value.
+     */
+    public double optDouble(int index) {
+        return this.optDouble(index, Double.NaN);
+    }
+
+
+    /**
+     * Get the optional double value associated with an index.
+     * The defaultValue is returned if there is no value for the index,
+     * or if the value is not a number and cannot be converted to a number.
+     *
+     * @param index subscript
+     * @param defaultValue     The default value.
+     * @return      The value.
+     */
+    public double optDouble(int index, double defaultValue) {
+        try {
+            return this.getDouble(index);
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+
+
+    /**
+     * Get the optional int value associated with an index.
+     * Zero is returned if there is no value for the index,
+     * or if the value is not a number and cannot be converted to a number.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The value.
+     */
+    public int optInt(int index) {
+        return this.optInt(index, 0);
+    }
+
+
+    /**
+     * Get the optional int value associated with an index.
+     * The defaultValue is returned if there is no value for the index,
+     * or if the value is not a number and cannot be converted to a number.
+     * @param index The index must be between 0 and length() - 1.
+     * @param defaultValue     The default value.
+     * @return      The value.
+     */
+    public int optInt(int index, int defaultValue) {
+        try {
+            return this.getInt(index);
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+
+
+    /**
+     * Get the optional JSONArray associated with an index.
+     * @param index subscript
+     * @return      A JSONArray value, or null if the index has no value,
+     * or if the value is not a JSONArray.
+     */
+    public JSONArray optJSONArray(int index) {
+        Object o = this.opt(index);
+        return o instanceof JSONArray ? (JSONArray)o : null;
+    }
+
+
+    /**
+     * Get the optional JSONObject associated with an index.
+     * Null is returned if the key is not found, or null if the index has
+     * no value, or if the value is not a JSONObject.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      A JSONObject value.
+     */
+    public JSONObject optJSONObject(int index) {
+        Object o = this.opt(index);
+        return o instanceof JSONObject ? (JSONObject)o : null;
+    }
+
+
+    /**
+     * Get the optional long value associated with an index.
+     * Zero is returned if there is no value for the index,
+     * or if the value is not a number and cannot be converted to a number.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      The value.
+     */
+    public long optLong(int index) {
+        return this.optLong(index, 0);
+    }
+
+
+    /**
+     * Get the optional long value associated with an index.
+     * The defaultValue is returned if there is no value for the index,
+     * or if the value is not a number and cannot be converted to a number.
+     * @param index The index must be between 0 and length() - 1.
+     * @param defaultValue     The default value.
+     * @return      The value.
+     */
+    public long optLong(int index, long defaultValue) {
+        try {
+            return this.getLong(index);
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+
+
+    /**
+     * Get the optional string value associated with an index. It returns an
+     * empty string if there is no value at that index. If the value
+     * is not a string and is not null, then it is coverted to a string.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @return      A String value.
+     */
+    public String optString(int index) {
+        return this.optString(index, "");
+    }
+
+
+    /**
+     * Get the optional string associated with an index.
+     * The defaultValue is returned if the key is not found.
+     *
+     * @param index The index must be between 0 and length() - 1.
+     * @param defaultValue     The default value.
+     * @return      A String value.
+     */
+    public String optString(int index, String defaultValue) {
+        Object object = this.opt(index);
+        return JSONObject.NULL.equals(object)
+ ? defaultValue : object
+                .toString();
+    }
+
+
+    /**
+     * Append a boolean value. This increases the array's length by one.
+     *
+     * @param value A boolean value.
+     * @return this.
+     */
+    public JSONArray put(boolean value) {
+        this.put(value ? Boolean.TRUE : Boolean.FALSE);
+        return this;
+    }
+
+
+    /**
+     * Put a value in the JSONArray, where the value will be a
+     * JSONArray which is produced from a Collection.
+     * @param value A Collection value.
+     * @return      this.
+     */
+    public JSONArray put(Collection value) {
+        this.put(new JSONArray(value));
+        return this;
+    }
+
+
+    /**
+     * Append a double value. This increases the array's length by one.
+     *
+     * @param value A double value.
+     * @throws JSONException if the value is not finite.
+     * @return this.
+     */
+    public JSONArray put(double value) throws JSONException {
+        Double d = new Double(value);
+        JSONObject.testValidity(d);
+        this.put(d);
+        return this;
+    }
+
+
+    /**
+     * Append an int value. This increases the array's length by one.
+     *
+     * @param value An int value.
+     * @return this.
+     */
+    public JSONArray put(int value) {
+        this.put(new Integer(value));
+        return this;
+    }
+
+
+    /**
+     * Append an long value. This increases the array's length by one.
+     *
+     * @param value A long value.
+     * @return this.
+     */
+    public JSONArray put(long value) {
+        this.put(new Long(value));
+        return this;
+    }
+
+
+    /**
+     * Put a value in the JSONArray, where the value will be a
+     * JSONObject which is produced from a Map.
+     * @param value A Map value.
+     * @return      this.
+     */
+    public JSONArray put(Map value) {
+        this.put(new JSONObject(value));
+        return this;
+    }
+
+
+    /**
+     * Append an object value. This increases the array's length by one.
+     * @param value An object value.  The value should be a
+     *  Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or 
the
+     *  JSONObject.NULL object.
+     * @return this.
+     */
+    public JSONArray put(Object value) {
+        this.myArrayList.add(value);
+        return this;
+    }
+
+
+    /**
+     * Put or replace a boolean value in the JSONArray. If the index is greater
+     * than the length of the JSONArray, then null elements will be added as
+     * necessary to pad it out.
+     * @param index The subscript.
+     * @param value A boolean value.
+     * @return this.
+     * @throws JSONException If the index is negative.
+     */
+    public JSONArray put(int index, boolean value) throws JSONException {
+        this.put(index, value ? Boolean.TRUE : Boolean.FALSE);
+        return this;
+    }
+
+
+    /**
+     * Put a value in the JSONArray, where the value will be a
+     * JSONArray which is produced from a Collection.
+     * @param index The subscript.
+     * @param value A Collection value.
+     * @return      this.
+     * @throws JSONException If the index is negative or if the value is
+     * not finite.
+     */
+    public JSONArray put(int index, Collection value) throws JSONException {
+        this.put(index, new JSONArray(value));
+        return this;
+    }
+
+
+    /**
+     * Put or replace a double value. If the index is greater than the length 
of
+     *  the JSONArray, then null elements will be added as necessary to pad
+     *  it out.
+     * @param index The subscript.
+     * @param value A double value.
+     * @return this.
+     * @throws JSONException If the index is negative or if the value is
+     * not finite.
+     */
+    public JSONArray put(int index, double value) throws JSONException {
+        this.put(index, new Double(value));
+        return this;
+    }
+
+
+    /**
+     * Put or replace an int value. If the index is greater than the length of
+     *  the JSONArray, then null elements will be added as necessary to pad
+     *  it out.
+     * @param index The subscript.
+     * @param value An int value.
+     * @return this.
+     * @throws JSONException If the index is negative.
+     */
+    public JSONArray put(int index, int value) throws JSONException {
+        this.put(index, new Integer(value));
+        return this;
+    }
+
+
+    /**
+     * Put or replace a long value. If the index is greater than the length of
+     *  the JSONArray, then null elements will be added as necessary to pad
+     *  it out.
+     * @param index The subscript.
+     * @param value A long value.
+     * @return this.
+     * @throws JSONException If the index is negative.
+     */
+    public JSONArray put(int index, long value) throws JSONException {
+        this.put(index, new Long(value));
+        return this;
+    }
+
+
+    /**
+     * Put a value in the JSONArray, where the value will be a
+     * JSONObject that is produced from a Map.
+     * @param index The subscript.
+     * @param value The Map value.
+     * @return      this.
+     * @throws JSONException If the index is negative or if the the value is
+     *  an invalid number.
+     */
+    public JSONArray put(int index, Map value) throws JSONException {
+        this.put(index, new JSONObject(value));
+        return this;
+    }
+
+
+    /**
+     * Put or replace an object value in the JSONArray. If the index is greater
+     *  than the length of the JSONArray, then null elements will be added as
+     *  necessary to pad it out.
+     * @param index The subscript.
+     * @param value The value to put into the array. The value should be a
+     *  Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or 
the
+     *  JSONObject.NULL object.
+     * @return this.
+     * @throws JSONException If the index is negative or if the the value is
+     *  an invalid number.
+     */
+    public JSONArray put(int index, Object value) throws JSONException {
+        JSONObject.testValidity(value);
+        if (index < 0) {
+            throw new JSONException("JSONArray[" + index + "] not found.");
+        }
+        if (index < this.length()) {
+            this.myArrayList.set(index, value);
+        } else {
+            while (index != this.length()) {
+                this.put(JSONObject.NULL);
+            }
+            this.put(value);
+        }
+        return this;
+    }
+
+
+    /**
+     * Remove an index and close the hole.
+     * @param index The index of the element to be removed.
+     * @return The value that was associated with the index,
+     * or null if there was no value.
+     */
+    public Object remove(int index) {
+        Object o = this.opt(index);
+        this.myArrayList.remove(index);
+        return o;
+    }
+
+
+    /**
+     * Produce a JSONObject by combining a JSONArray of names with the values
+     * of this JSONArray.
+     * @param names A JSONArray containing a list of key strings. These will be
+     * paired with the values.
+     * @return A JSONObject, or null if there are no names or if this JSONArray
+     * has no values.
+     * @throws JSONException If any of the names are null.
+     */
+    public JSONObject toJSONObject(JSONArray names) throws JSONException {
+        if (names == null || names.length() == 0 || this.length() == 0) {
+            return null;
+        }
+        JSONObject jo = new JSONObject();
+        for (int i = 0; i < names.length(); i += 1) {
+            jo.put(names.getString(i), this.opt(i));
+        }
+        return jo;
+    }
+
+
+    /**
+     * Make a JSON text of this JSONArray. For compactness, no
+     * unnecessary whitespace is added. If it is not possible to produce a
+     * syntactically correct JSON text then null will be returned instead. This
+     * could occur if the array contains an invalid number.
+     * <p>
+     * Warning: This method assumes that the data structure is acyclical.
+     *
+     * @return a printable, displayable, transmittable
+     *  representation of the array.
+     */
+    public String toString() {
+        try {
+            return '[' + this.join(",") + ']';
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+
+    /**
+     * Make a prettyprinted JSON text of this JSONArray.
+     * Warning: This method assumes that the data structure is acyclical.
+     * @param indentFactor The number of spaces to add to each level of
+     *  indentation.
+     * @return a printable, displayable, transmittable
+     *  representation of the object, beginning
+     *  with <code>[</code>&nbsp;<small>(left bracket)</small> and ending
+     *  with <code>]</code>&nbsp;<small>(right bracket)</small>.
+     * @throws JSONException
+     */
+    public String toString(int indentFactor) throws JSONException {
+        StringWriter sw = new StringWriter();
+        synchronized (sw.getBuffer()) {
+            return this.write(sw, indentFactor, 0).toString();
+        }
+    }
+
+    /**
+     * Write the contents of the JSONArray as JSON text to a writer. For
+     * compactness, no whitespace is added.
+     * <p>
+     * Warning: This method assumes that the data structure is acyclical.
+     *
+     * @return The writer.
+     * @throws JSONException
+     */
+    public Writer write(Writer writer) throws JSONException {
+        return this.write(writer, 0, 0);
+    }
+
+    /**
+     * Write the contents of the JSONArray as JSON text to a writer. For
+     * compactness, no whitespace is added.
+     * <p>
+     * Warning: This method assumes that the data structure is acyclical.
+     *
+     * @param indentFactor
+     *            The number of spaces to add to each level of indentation.
+     * @param indent
+     *            The indention of the top level.
+     * @return The writer.
+     * @throws JSONException
+     */
+    Writer write(Writer writer, int indentFactor, int indent)
+            throws JSONException {
+        try {
+            boolean commanate = false;
+            int length = this.length();
+            writer.write('[');
+
+            if (length == 1) {
+                JSONObject.writeValue(writer, this.myArrayList.get(0),
+                        indentFactor, indent);
+            } else if (length != 0) {
+                final int newindent = indent + indentFactor;
+
+                for (int i = 0; i < length; i += 1) {
+                    if (commanate) {
+                        writer.write(',');
+                    }
+                    if (indentFactor > 0) {
+                        writer.write('\n');
+                    }
+                    JSONObject.indent(writer, newindent);
+                    JSONObject.writeValue(writer, this.myArrayList.get(i),
+                            indentFactor, newindent);
+                    commanate = true;
+                }
+                if (indentFactor > 0) {
+                    writer.write('\n');
+                }
+                JSONObject.indent(writer, indent);
+            }
+            writer.write(']');
+            return writer;
+        } catch (IOException e) {
+           throw new JSONException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONException.java
----------------------------------------------------------------------
diff --git 
a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONException.java
 
b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONException.java
new file mode 100644
index 0000000..7533e49
--- /dev/null
+++ 
b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONException.java
@@ -0,0 +1,47 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.vmware.geode.tools.pulse.internal.json;
+
+/**
+ * The JSONException is thrown by the JSON.org classes when things are amiss.
+ * @author JSON.org
+ * @version 2010-12-24
+ */
+public class JSONException extends Exception {
+    private static final long serialVersionUID = 0;
+    private Throwable cause;
+
+    /**
+     * Constructs a JSONException with an explanatory message.
+     * @param message Detail about the reason for the exception.
+     */
+    public JSONException(String message) {
+        super(message);
+    }
+
+    public JSONException(Throwable cause) {
+        super(cause.getMessage());
+        this.cause = cause;
+    }
+
+    public Throwable getCause() {
+        return this.cause;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/9a2b5d7b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONML.java
----------------------------------------------------------------------
diff --git 
a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONML.java
 
b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONML.java
new file mode 100644
index 0000000..3c52063
--- /dev/null
+++ 
b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/json/JSONML.java
@@ -0,0 +1,462 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.vmware.geode.tools.pulse.internal.json;
+
+import java.util.Iterator;
+
+
+/**
+ * This provides static methods to convert an XML text into a JSONArray or
+ * JSONObject, and to covert a JSONArray or JSONObject into an XML text using
+ * the JsonML transform.
+ * 
+ * @author JSON.org
+ * @version 2012-03-28
+ */
+public class JSONML {
+
+    /**
+     * Parse XML values and store them in a JSONArray.
+     * @param x       The XMLTokener containing the source string.
+     * @param arrayForm true if array form, false if object form.
+     * @param ja      The JSONArray that is containing the current tag or null
+     *     if we are at the outermost level.
+     * @return A JSONArray if the value is the outermost tag, otherwise null.
+     * @throws JSONException
+     */
+    private static Object parse(
+        XMLTokener x,
+        boolean    arrayForm,
+        JSONArray  ja
+    ) throws JSONException {
+        String     attribute;
+        char       c;
+        String       closeTag = null;
+        int        i;
+        JSONArray  newja = null;
+        JSONObject newjo = null;
+        Object     token;
+        String       tagName = null;
+
+// Test for and skip past these forms:
+//      <!-- ... -->
+//      <![  ... ]]>
+//      <!   ...   >
+//      <?   ...  ?>
+
+        while (true) {
+            if (!x.more()) {
+                throw x.syntaxError("Bad XML");
+            }
+            token = x.nextContent();
+            if (token == XML.LT) {
+                token = x.nextToken();
+                if (token instanceof Character) {
+                    if (token == XML.SLASH) {
+
+// Close tag </
+
+                        token = x.nextToken();
+                        if (!(token instanceof String)) {
+                            throw new JSONException(
+                                    "Expected a closing name instead of '" +
+                                    token + "'.");
+                        }
+                        if (x.nextToken() != XML.GT) {
+                            throw x.syntaxError("Misshaped close tag");
+                        }
+                        return token;
+                    } else if (token == XML.BANG) {
+
+// <!
+
+                        c = x.next();
+                        if (c == '-') {
+                            if (x.next() == '-') {
+                                x.skipPast("-->");
+                            } else {
+                                x.back();
+                            }
+                        } else if (c == '[') {
+                            token = x.nextToken();
+                            if (token.equals("CDATA") && x.next() == '[') {
+                                if (ja != null) {
+                                    ja.put(x.nextCDATA());
+                                }
+                            } else {
+                                throw x.syntaxError("Expected 'CDATA['");
+                            }
+                        } else {
+                            i = 1;
+                            do {
+                                token = x.nextMeta();
+                                if (token == null) {
+                                    throw x.syntaxError("Missing '>' after 
'<!'.");
+                                } else if (token == XML.LT) {
+                                    i += 1;
+                                } else if (token == XML.GT) {
+                                    i -= 1;
+                                }
+                            } while (i > 0);
+                        }
+                    } else if (token == XML.QUEST) {
+
+// <?
+
+                        x.skipPast("?>");
+                    } else {
+                        throw x.syntaxError("Misshaped tag");
+                    }
+
+// Open tag <
+
+                } else {
+                    if (!(token instanceof String)) {
+                        throw x.syntaxError("Bad tagName '" + token + "'.");
+                    }
+                    tagName = (String)token;
+                    newja = new JSONArray();
+                    newjo = new JSONObject();
+                    if (arrayForm) {
+                        newja.put(tagName);
+                        if (ja != null) {
+                            ja.put(newja);
+                        }
+                    } else {
+                        newjo.put("tagName", tagName);
+                        if (ja != null) {
+                            ja.put(newjo);
+                        }
+                    }
+                    token = null;
+                    for (;;) {
+                        if (token == null) {
+                            token = x.nextToken();
+                        }
+                        if (token == null) {
+                            throw x.syntaxError("Misshaped tag");
+                        }
+                        if (!(token instanceof String)) {
+                            break;
+                        }
+
+// attribute = value
+
+                        attribute = (String)token;
+                        if (!arrayForm && ("tagName".equals(attribute) || 
"childNode".equals(attribute))) {
+                            throw x.syntaxError("Reserved attribute.");
+                        }
+                        token = x.nextToken();
+                        if (token == XML.EQ) {
+                            token = x.nextToken();
+                            if (!(token instanceof String)) {
+                                throw x.syntaxError("Missing value");
+                            }
+                            newjo.accumulate(attribute, 
XML.stringToValue((String)token));
+                            token = null;
+                        } else {
+                            newjo.accumulate(attribute, "");
+                        }
+                    }
+                    if (arrayForm && newjo.length() > 0) {
+                        newja.put(newjo);
+                    }
+
+// Empty tag <.../>
+
+                    if (token == XML.SLASH) {
+                        if (x.nextToken() != XML.GT) {
+                            throw x.syntaxError("Misshaped tag");
+                        }
+                        if (ja == null) {
+                            if (arrayForm) {
+                                return newja;
+                            } else {
+                                return newjo;
+                            }
+                        }
+
+// Content, between <...> and </...>
+
+                    } else {
+                        if (token != XML.GT) {
+                            throw x.syntaxError("Misshaped tag");
+                        }
+                        closeTag = (String)parse(x, arrayForm, newja);
+                        if (closeTag != null) {
+                            if (!closeTag.equals(tagName)) {
+                                throw x.syntaxError("Mismatched '" + tagName +
+                                        "' and '" + closeTag + "'");
+                            }
+                            tagName = null;
+                            if (!arrayForm && newja.length() > 0) {
+                                newjo.put("childNodes", newja);
+                            }
+                            if (ja == null) {
+                                if (arrayForm) {
+                                    return newja;
+                                } else {
+                                    return newjo;
+                                }
+                            }
+                        }
+                    }
+                }
+            } else {
+                if (ja != null) {
+                    ja.put(token instanceof String
+                        ? XML.stringToValue((String)token)
+                        : token);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Convert a well-formed (but not necessarily valid) XML string into a
+     * JSONArray using the JsonML transform. Each XML tag is represented as
+     * a JSONArray in which the first element is the tag name. If the tag has
+     * attributes, then the second element will be JSONObject containing the
+     * name/value pairs. If the tag contains children, then strings and
+     * JSONArrays will represent the child tags.
+     * Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
+     * @param string The source string.
+     * @return A JSONArray containing the structured data from the XML string.
+     * @throws JSONException
+     */
+    public static JSONArray toJSONArray(String string) throws JSONException {
+        return toJSONArray(new XMLTokener(string));
+    }
+
+
+    /**
+     * Convert a well-formed (but not necessarily valid) XML string into a
+     * JSONArray using the JsonML transform. Each XML tag is represented as
+     * a JSONArray in which the first element is the tag name. If the tag has
+     * attributes, then the second element will be JSONObject containing the
+     * name/value pairs. If the tag contains children, then strings and
+     * JSONArrays will represent the child content and tags.
+     * Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
+     * @param x An XMLTokener.
+     * @return A JSONArray containing the structured data from the XML string.
+     * @throws JSONException
+     */
+    public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
+        return (JSONArray)parse(x, true, null);
+    }
+
+
+    /**
+     * Convert a well-formed (but not necessarily valid) XML string into a
+     * JSONObject using the JsonML transform. Each XML tag is represented as
+     * a JSONObject with a "tagName" property. If the tag has attributes, then
+     * the attributes will be in the JSONObject as properties. If the tag
+     * contains children, the object will have a "childNodes" property which
+     * will be an array of strings and JsonML JSONObjects.
+
+     * Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
+     * @param x An XMLTokener of the XML source text.
+     * @return A JSONObject containing the structured data from the XML string.
+     * @throws JSONException
+     */
+    public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
+           return (JSONObject)parse(x, false, null);
+    }
+
+
+    /**
+     * Convert a well-formed (but not necessarily valid) XML string into a
+     * JSONObject using the JsonML transform. Each XML tag is represented as
+     * a JSONObject with a "tagName" property. If the tag has attributes, then
+     * the attributes will be in the JSONObject as properties. If the tag
+     * contains children, the object will have a "childNodes" property which
+     * will be an array of strings and JsonML JSONObjects.
+
+     * Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
+     * @param string The XML source text.
+     * @return A JSONObject containing the structured data from the XML string.
+     * @throws JSONException
+     */
+    public static JSONObject toJSONObject(String string) throws JSONException {
+        return toJSONObject(new XMLTokener(string));
+    }
+
+
+    /**
+     * Reverse the JSONML transformation, making an XML text from a JSONArray.
+     * @param ja A JSONArray.
+     * @return An XML string.
+     * @throws JSONException
+     */
+    public static String toString(JSONArray ja) throws JSONException {
+        int             i;
+        JSONObject   jo;
+        String       key;
+        Iterator     keys;
+        int             length;
+        Object         object;
+        StringBuffer sb = new StringBuffer();
+        String       tagName;
+        String       value;
+
+// Emit <tagName
+
+        tagName = ja.getString(0);
+        XML.noSpace(tagName);
+        tagName = XML.escape(tagName);
+        sb.append('<');
+        sb.append(tagName);
+
+        object = ja.opt(1);
+        if (object instanceof JSONObject) {
+            i = 2;
+            jo = (JSONObject)object;
+
+// Emit the attributes
+
+            keys = jo.keys();
+            while (keys.hasNext()) {
+                key = keys.next().toString();
+                XML.noSpace(key);
+                value = jo.optString(key);
+                if (value != null) {
+                    sb.append(' ');
+                    sb.append(XML.escape(key));
+                    sb.append('=');
+                    sb.append('"');
+                    sb.append(XML.escape(value));
+                    sb.append('"');
+                }
+            }
+        } else {
+            i = 1;
+        }
+
+//Emit content in body
+
+        length = ja.length();
+        if (i >= length) {
+            sb.append('/');
+            sb.append('>');
+        } else {
+            sb.append('>');
+            do {
+                object = ja.get(i);
+                i += 1;
+                if (object != null) {
+                    if (object instanceof String) {
+                        sb.append(XML.escape(object.toString()));
+                    } else if (object instanceof JSONObject) {
+                        sb.append(toString((JSONObject)object));
+                    } else if (object instanceof JSONArray) {
+                        sb.append(toString((JSONArray)object));
+                    }
+                }
+            } while (i < length);
+            sb.append('<');
+            sb.append('/');
+            sb.append(tagName);
+            sb.append('>');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Reverse the JSONML transformation, making an XML text from a JSONObject.
+     * The JSONObject must contain a "tagName" property. If it has children,
+     * then it must have a "childNodes" property containing an array of 
objects.
+     * The other properties are attributes with string values.
+     * @param jo A JSONObject.
+     * @return An XML string.
+     * @throws JSONException
+     */
+    public static String toString(JSONObject jo) throws JSONException {
+        StringBuffer sb = new StringBuffer();
+        int          i;
+        JSONArray    ja;
+        String       key;
+        Iterator     keys;
+        int          length;
+        Object         object;
+        String       tagName;
+        String       value;
+
+//Emit <tagName
+
+        tagName = jo.optString("tagName");
+        if (tagName == null) {
+            return XML.escape(jo.toString());
+        }
+        XML.noSpace(tagName);
+        tagName = XML.escape(tagName);
+        sb.append('<');
+        sb.append(tagName);
+
+//Emit the attributes
+
+        keys = jo.keys();
+        while (keys.hasNext()) {
+            key = keys.next().toString();
+            if (!"tagName".equals(key) && !"childNodes".equals(key)) {
+                XML.noSpace(key);
+                value = jo.optString(key);
+                if (value != null) {
+                    sb.append(' ');
+                    sb.append(XML.escape(key));
+                    sb.append('=');
+                    sb.append('"');
+                    sb.append(XML.escape(value));
+                    sb.append('"');
+                }
+            }
+        }
+
+//Emit content in body
+
+        ja = jo.optJSONArray("childNodes");
+        if (ja == null) {
+            sb.append('/');
+            sb.append('>');
+        } else {
+            sb.append('>');
+            length = ja.length();
+            for (i = 0; i < length; i += 1) {
+                object = ja.get(i);
+                if (object != null) {
+                    if (object instanceof String) {
+                        sb.append(XML.escape(object.toString()));
+                    } else if (object instanceof JSONObject) {
+                        sb.append(toString((JSONObject)object));
+                    } else if (object instanceof JSONArray) {
+                        sb.append(toString((JSONArray)object));
+                    } else {
+                        sb.append(object.toString());
+                    }
+                }
+            }
+            sb.append('<');
+            sb.append('/');
+            sb.append(tagName);
+            sb.append('>');
+        }
+        return sb.toString();
+    }
+}

Reply via email to