parent
							
								
									9035394d3d
								
							
						
					
					
						commit
						ef813e371f
					
				| @ -1,279 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * This provides static methods to convert comma delimited text into a |  | ||||||
|  * JSONArray, and to covert a JSONArray into comma delimited text. Comma |  | ||||||
|  * delimited text is a very popular format for data interchange. It is |  | ||||||
|  * understood by most database, spreadsheet, and organizer programs. |  | ||||||
|  * <p> |  | ||||||
|  * Each row of text represents a row in a table or a data record. Each row |  | ||||||
|  * ends with a NEWLINE character. Each row contains one or more values. |  | ||||||
|  * Values are separated by commas. A value can contain any character except |  | ||||||
|  * for comma, unless is is wrapped in single quotes or double quotes. |  | ||||||
|  * <p> |  | ||||||
|  * The first row usually contains the names of the columns. |  | ||||||
|  * <p> |  | ||||||
|  * A comma delimited list can be converted into a JSONArray of JSONObjects. |  | ||||||
|  * The names for the elements in the JSONObjects can be taken from the names |  | ||||||
|  * in the first row. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2010-12-24 |  | ||||||
|  */ |  | ||||||
| public class CDL { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Get the next value. The value can be wrapped in quotes. The value can |  | ||||||
|      * be empty. |  | ||||||
|      * @param x A JSONTokener of the source text. |  | ||||||
|      * @return The value string, or null if empty. |  | ||||||
|      * @throws JSONException if the quoted string is badly formed. |  | ||||||
|      */ |  | ||||||
|     private static String getValue(JSONTokener x) throws JSONException { |  | ||||||
|         char c; |  | ||||||
|         char q; |  | ||||||
|         StringBuffer sb; |  | ||||||
|         do { |  | ||||||
|             c = x.next(); |  | ||||||
|         } while (c == ' ' || c == '\t'); |  | ||||||
|         switch (c) { |  | ||||||
|         case 0: |  | ||||||
|             return null; |  | ||||||
|         case '"': |  | ||||||
|         case '\'': |  | ||||||
|             q = c; |  | ||||||
|             sb = new StringBuffer(); |  | ||||||
|             for (;;) { |  | ||||||
|                 c = x.next(); |  | ||||||
|                 if (c == q) { |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 if (c == 0 || c == '\n' || c == '\r') { |  | ||||||
|                     throw x.syntaxError("Missing close quote '" + q + "'."); |  | ||||||
|                 } |  | ||||||
|                 sb.append(c); |  | ||||||
|             } |  | ||||||
|             return sb.toString(); |  | ||||||
|         case ',': |  | ||||||
|             x.back(); |  | ||||||
|             return ""; |  | ||||||
|         default: |  | ||||||
|             x.back(); |  | ||||||
|             return x.nextTo(','); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a JSONArray of strings from a row of comma delimited values. |  | ||||||
|      * @param x A JSONTokener of the source text. |  | ||||||
|      * @return A JSONArray of strings. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { |  | ||||||
|         JSONArray ja = new JSONArray(); |  | ||||||
|         for (;;) { |  | ||||||
|             String value = getValue(x); |  | ||||||
|             char c = x.next(); |  | ||||||
|             if (value == null ||  |  | ||||||
|                     (ja.length() == 0 && value.length() == 0 && c != ',')) { |  | ||||||
|                 return null; |  | ||||||
|             } |  | ||||||
|             ja.put(value); |  | ||||||
|             for (;;) {                 |  | ||||||
|                 if (c == ',') { |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 if (c != ' ') { |  | ||||||
|                     if (c == '\n' || c == '\r' || c == 0) { |  | ||||||
|                         return ja; |  | ||||||
|                     } |  | ||||||
|                     throw x.syntaxError("Bad character '" + c + "' (" + |  | ||||||
|                             (int)c + ")."); |  | ||||||
|                 } |  | ||||||
|                 c = x.next(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a JSONObject from a row of comma delimited text, using a |  | ||||||
|      * parallel JSONArray of strings to provides the names of the elements. |  | ||||||
|      * @param names A JSONArray of names. This is commonly obtained from the |  | ||||||
|      *  first row of a comma delimited text file using the rowToJSONArray |  | ||||||
|      *  method. |  | ||||||
|      * @param x A JSONTokener of the source text. |  | ||||||
|      * @return A JSONObject combining the names and values. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) |  | ||||||
|             throws JSONException { |  | ||||||
|         JSONArray ja = rowToJSONArray(x); |  | ||||||
|         return ja != null ? ja.toJSONObject(names) :  null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a comma delimited text row from a JSONArray. Values containing |  | ||||||
|      * the comma character will be quoted. Troublesome characters may be  |  | ||||||
|      * removed. |  | ||||||
|      * @param ja A JSONArray of strings. |  | ||||||
|      * @return A string ending in NEWLINE. |  | ||||||
|      */ |  | ||||||
|     public static String rowToString(JSONArray ja) { |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         for (int i = 0; i < ja.length(); i += 1) { |  | ||||||
|             if (i > 0) { |  | ||||||
|                 sb.append(','); |  | ||||||
|             } |  | ||||||
|             Object object = ja.opt(i); |  | ||||||
|             if (object != null) { |  | ||||||
|                 String string = object.toString(); |  | ||||||
|                 if (string.length() > 0 && (string.indexOf(',') >= 0 ||  |  | ||||||
|                         string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 ||  |  | ||||||
|                         string.indexOf(0) >= 0 || string.charAt(0) == '"')) { |  | ||||||
|                     sb.append('"'); |  | ||||||
|                     int length = string.length(); |  | ||||||
|                     for (int j = 0; j < length; j += 1) { |  | ||||||
|                         char c = string.charAt(j); |  | ||||||
|                         if (c >= ' ' && c != '"') { |  | ||||||
|                             sb.append(c); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     sb.append('"'); |  | ||||||
|                 } else { |  | ||||||
|                     sb.append(string); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         sb.append('\n'); |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a JSONArray of JSONObjects from a comma delimited text string, |  | ||||||
|      * using the first row as a source of names. |  | ||||||
|      * @param string The comma delimited text. |  | ||||||
|      * @return A JSONArray of JSONObjects. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONArray toJSONArray(String string) throws JSONException { |  | ||||||
|         return toJSONArray(new JSONTokener(string)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a JSONArray of JSONObjects from a comma delimited text string, |  | ||||||
|      * using the first row as a source of names. |  | ||||||
|      * @param x The JSONTokener containing the comma delimited text. |  | ||||||
|      * @return A JSONArray of JSONObjects. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONArray toJSONArray(JSONTokener x) throws JSONException { |  | ||||||
|         return toJSONArray(rowToJSONArray(x), x); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a JSONArray of JSONObjects from a comma delimited text string |  | ||||||
|      * using a supplied JSONArray as the source of element names. |  | ||||||
|      * @param names A JSONArray of strings. |  | ||||||
|      * @param string The comma delimited text. |  | ||||||
|      * @return A JSONArray of JSONObjects. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONArray toJSONArray(JSONArray names, String string) |  | ||||||
|             throws JSONException { |  | ||||||
|         return toJSONArray(names, new JSONTokener(string)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a JSONArray of JSONObjects from a comma delimited text string |  | ||||||
|      * using a supplied JSONArray as the source of element names. |  | ||||||
|      * @param names A JSONArray of strings. |  | ||||||
|      * @param x A JSONTokener of the source text. |  | ||||||
|      * @return A JSONArray of JSONObjects. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONArray toJSONArray(JSONArray names, JSONTokener x) |  | ||||||
|             throws JSONException { |  | ||||||
|         if (names == null || names.length() == 0) { |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
|         JSONArray ja = new JSONArray(); |  | ||||||
|         for (;;) { |  | ||||||
|             JSONObject jo = rowToJSONObject(names, x); |  | ||||||
|             if (jo == null) { |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|             ja.put(jo); |  | ||||||
|         } |  | ||||||
|         if (ja.length() == 0) { |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
|         return ja; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a comma delimited text from a JSONArray of JSONObjects. The |  | ||||||
|      * first row will be a list of names obtained by inspecting the first |  | ||||||
|      * JSONObject. |  | ||||||
|      * @param ja A JSONArray of JSONObjects. |  | ||||||
|      * @return A comma delimited text. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static String toString(JSONArray ja) throws JSONException { |  | ||||||
|         JSONObject jo = ja.optJSONObject(0); |  | ||||||
|         if (jo != null) { |  | ||||||
|             JSONArray names = jo.names(); |  | ||||||
|             if (names != null) { |  | ||||||
|                 return rowToString(names) + toString(names, ja); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a comma delimited text from a JSONArray of JSONObjects using |  | ||||||
|      * a provided list of names. The list of names is not included in the |  | ||||||
|      * output. |  | ||||||
|      * @param names A JSONArray of strings. |  | ||||||
|      * @param ja A JSONArray of JSONObjects. |  | ||||||
|      * @return A comma delimited text. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static String toString(JSONArray names, JSONArray ja) |  | ||||||
|             throws JSONException { |  | ||||||
|         if (names == null || names.length() == 0) { |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         for (int i = 0; i < ja.length(); i += 1) { |  | ||||||
|             JSONObject jo = ja.optJSONObject(i); |  | ||||||
|             if (jo != null) { |  | ||||||
|                 sb.append(rowToString(jo.toJSONArray(names))); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,169 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Convert a web browser cookie specification to a JSONObject and back. |  | ||||||
|  * JSON and Cookies are both notations for name/value pairs. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2010-12-24 |  | ||||||
|  */ |  | ||||||
| public class Cookie { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Produce a copy of a string in which the characters '+', '%', '=', ';' |  | ||||||
|      * and control characters are replaced with "%hh". This is a gentle form |  | ||||||
|      * of URL encoding, attempting to cause as little distortion to the |  | ||||||
|      * string as possible. The characters '=' and ';' are meta characters in |  | ||||||
|      * cookies. By convention, they are escaped using the URL-encoding. This is |  | ||||||
|      * only a convention, not a standard. Often, cookies are expected to have |  | ||||||
|      * encoded values. We encode '=' and ';' because we must. We encode '%' and |  | ||||||
|      * '+' because they are meta characters in URL encoding. |  | ||||||
|      * @param string The source string. |  | ||||||
|      * @return       The escaped result. |  | ||||||
|      */ |  | ||||||
|     public static String escape(String string) { |  | ||||||
|         char         c; |  | ||||||
|         String       s = string.trim(); |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         int          length = s.length(); |  | ||||||
|         for (int i = 0; i < length; i += 1) { |  | ||||||
|             c = s.charAt(i); |  | ||||||
|             if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { |  | ||||||
|                 sb.append('%'); |  | ||||||
|                 sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); |  | ||||||
|                 sb.append(Character.forDigit((char)(c & 0x0f), 16)); |  | ||||||
|             } else { |  | ||||||
|                 sb.append(c); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Convert a cookie specification string into a JSONObject. The string |  | ||||||
|      * will contain a name value pair separated by '='. The name and the value |  | ||||||
|      * will be unescaped, possibly converting '+' and '%' sequences. The |  | ||||||
|      * cookie properties may follow, separated by ';', also represented as |  | ||||||
|      * name=value (except the secure property, which does not have a value). |  | ||||||
|      * The name will be stored under the key "name", and the value will be |  | ||||||
|      * stored under the key "value". This method does not do checking or |  | ||||||
|      * validation of the parameters. It only converts the cookie string into |  | ||||||
|      * a JSONObject. |  | ||||||
|      * @param string The cookie specification string. |  | ||||||
|      * @return A JSONObject containing "name", "value", and possibly other |  | ||||||
|      *  members. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONObject toJSONObject(String string) throws JSONException { |  | ||||||
|         String         name; |  | ||||||
|         JSONObject     jo = new JSONObject(); |  | ||||||
|         Object         value; |  | ||||||
|         JSONTokener x = new JSONTokener(string); |  | ||||||
|         jo.put("name", x.nextTo('=')); |  | ||||||
|         x.next('='); |  | ||||||
|         jo.put("value", x.nextTo(';')); |  | ||||||
|         x.next(); |  | ||||||
|         while (x.more()) { |  | ||||||
|             name = unescape(x.nextTo("=;")); |  | ||||||
|             if (x.next() != '=') { |  | ||||||
|                 if (name.equals("secure")) { |  | ||||||
|                     value = Boolean.TRUE; |  | ||||||
|                 } else { |  | ||||||
|                     throw x.syntaxError("Missing '=' in cookie parameter."); |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 value = unescape(x.nextTo(';')); |  | ||||||
|                 x.next(); |  | ||||||
|             } |  | ||||||
|             jo.put(name, value); |  | ||||||
|         } |  | ||||||
|         return jo; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Convert a JSONObject into a cookie specification string. The JSONObject |  | ||||||
|      * must contain "name" and "value" members. |  | ||||||
|      * If the JSONObject contains "expires", "domain", "path", or "secure" |  | ||||||
|      * members, they will be appended to the cookie specification string. |  | ||||||
|      * All other members are ignored. |  | ||||||
|      * @param jo A JSONObject |  | ||||||
|      * @return A cookie specification string |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static String toString(JSONObject jo) throws JSONException { |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
| 
 |  | ||||||
|         sb.append(escape(jo.getString("name"))); |  | ||||||
|         sb.append("="); |  | ||||||
|         sb.append(escape(jo.getString("value"))); |  | ||||||
|         if (jo.has("expires")) { |  | ||||||
|             sb.append(";expires="); |  | ||||||
|             sb.append(jo.getString("expires")); |  | ||||||
|         } |  | ||||||
|         if (jo.has("domain")) { |  | ||||||
|             sb.append(";domain="); |  | ||||||
|             sb.append(escape(jo.getString("domain"))); |  | ||||||
|         } |  | ||||||
|         if (jo.has("path")) { |  | ||||||
|             sb.append(";path="); |  | ||||||
|             sb.append(escape(jo.getString("path"))); |  | ||||||
|         } |  | ||||||
|         if (jo.optBoolean("secure")) { |  | ||||||
|             sb.append(";secure"); |  | ||||||
|         } |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Convert <code>%</code><i>hh</i> sequences to single characters, and |  | ||||||
|      * convert plus to space. |  | ||||||
|      * @param string A string that may contain |  | ||||||
|      *      <code>+</code> <small>(plus)</small> and |  | ||||||
|      *      <code>%</code><i>hh</i> sequences. |  | ||||||
|      * @return The unescaped string. |  | ||||||
|      */ |  | ||||||
|     public static String unescape(String string) { |  | ||||||
|         int length = string.length(); |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         for (int i = 0; i < length; ++i) { |  | ||||||
|             char c = string.charAt(i); |  | ||||||
|             if (c == '+') { |  | ||||||
|                 c = ' '; |  | ||||||
|             } else if (c == '%' && i + 2 < length) { |  | ||||||
|                 int d = JSONTokener.dehexchar(string.charAt(i + 1)); |  | ||||||
|                 int e = JSONTokener.dehexchar(string.charAt(i + 2)); |  | ||||||
|                 if (d >= 0 && e >= 0) { |  | ||||||
|                     c = (char)(d * 16 + e); |  | ||||||
|                     i += 2; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             sb.append(c); |  | ||||||
|         } |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,90 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| import java.util.Iterator; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Convert a web browser cookie list string to a JSONObject and back. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2010-12-24 |  | ||||||
|  */ |  | ||||||
| public class CookieList { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Convert a cookie list into a JSONObject. A cookie list is a sequence |  | ||||||
|      * of name/value pairs. The names are separated from the values by '='. |  | ||||||
|      * The pairs are separated by ';'. The names and the values |  | ||||||
|      * will be unescaped, possibly converting '+' and '%' sequences. |  | ||||||
|      * |  | ||||||
|      * To add a cookie to a cooklist, |  | ||||||
|      * cookielistJSONObject.put(cookieJSONObject.getString("name"), |  | ||||||
|      *     cookieJSONObject.getString("value")); |  | ||||||
|      * @param string  A cookie list string |  | ||||||
|      * @return A JSONObject |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONObject toJSONObject(String string) throws JSONException { |  | ||||||
|         JSONObject jo = new JSONObject(); |  | ||||||
|         JSONTokener x = new JSONTokener(string); |  | ||||||
|         while (x.more()) { |  | ||||||
|             String name = Cookie.unescape(x.nextTo('=')); |  | ||||||
|             x.next('='); |  | ||||||
|             jo.put(name, Cookie.unescape(x.nextTo(';'))); |  | ||||||
|             x.next(); |  | ||||||
|         } |  | ||||||
|         return jo; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Convert a JSONObject into a cookie list. A cookie list is a sequence |  | ||||||
|      * of name/value pairs. The names are separated from the values by '='. |  | ||||||
|      * The pairs are separated by ';'. The characters '%', '+', '=', and ';' |  | ||||||
|      * in the names and values are replaced by "%hh". |  | ||||||
|      * @param jo A JSONObject |  | ||||||
|      * @return A cookie list string |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static String toString(JSONObject jo) throws JSONException { |  | ||||||
|         boolean      b = false; |  | ||||||
|         Iterator     keys = jo.keys(); |  | ||||||
|         String       string; |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         while (keys.hasNext()) { |  | ||||||
|             string = keys.next().toString(); |  | ||||||
|             if (!jo.isNull(string)) { |  | ||||||
|                 if (b) { |  | ||||||
|                     sb.append(';'); |  | ||||||
|                 } |  | ||||||
|                 sb.append(Cookie.escape(string)); |  | ||||||
|                 sb.append("="); |  | ||||||
|                 sb.append(Cookie.escape(jo.getString(string))); |  | ||||||
|                 b = true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,163 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| import java.util.Iterator; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Convert an HTTP header to a JSONObject and back. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2010-12-24 |  | ||||||
|  */ |  | ||||||
| public class HTTP { |  | ||||||
| 
 |  | ||||||
|     /** Carriage return/line feed. */ |  | ||||||
|     public static final String CRLF = "\r\n"; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Convert an HTTP header string into a JSONObject. It can be a request |  | ||||||
|      * header or a response header. A request header will contain |  | ||||||
|      * <pre>{ |  | ||||||
|      *    Method: "POST" (for example), |  | ||||||
|      *    "Request-URI": "/" (for example), |  | ||||||
|      *    "HTTP-Version": "HTTP/1.1" (for example) |  | ||||||
|      * }</pre> |  | ||||||
|      * A response header will contain |  | ||||||
|      * <pre>{ |  | ||||||
|      *    "HTTP-Version": "HTTP/1.1" (for example), |  | ||||||
|      *    "Status-Code": "200" (for example), |  | ||||||
|      *    "Reason-Phrase": "OK" (for example) |  | ||||||
|      * }</pre> |  | ||||||
|      * In addition, the other parameters in the header will be captured, using |  | ||||||
|      * the HTTP field names as JSON names, so that <pre> |  | ||||||
|      *    Date: Sun, 26 May 2002 18:06:04 GMT |  | ||||||
|      *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s |  | ||||||
|      *    Cache-Control: no-cache</pre> |  | ||||||
|      * become |  | ||||||
|      * <pre>{... |  | ||||||
|      *    Date: "Sun, 26 May 2002 18:06:04 GMT", |  | ||||||
|      *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s", |  | ||||||
|      *    "Cache-Control": "no-cache", |  | ||||||
|      * ...}</pre> |  | ||||||
|      * It does no further checking or conversion. It does not parse dates. |  | ||||||
|      * It does not do '%' transforms on URLs. |  | ||||||
|      * @param string An HTTP header string. |  | ||||||
|      * @return A JSONObject containing the elements and attributes |  | ||||||
|      * of the XML string. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public static JSONObject toJSONObject(String string) throws JSONException { |  | ||||||
|         JSONObject     jo = new JSONObject(); |  | ||||||
|         HTTPTokener    x = new HTTPTokener(string); |  | ||||||
|         String         token; |  | ||||||
| 
 |  | ||||||
|         token = x.nextToken(); |  | ||||||
|         if (token.toUpperCase().startsWith("HTTP")) { |  | ||||||
| 
 |  | ||||||
| // Response
 |  | ||||||
| 
 |  | ||||||
|             jo.put("HTTP-Version", token); |  | ||||||
|             jo.put("Status-Code", x.nextToken()); |  | ||||||
|             jo.put("Reason-Phrase", x.nextTo('\0')); |  | ||||||
|             x.next(); |  | ||||||
| 
 |  | ||||||
|         } else { |  | ||||||
| 
 |  | ||||||
| // Request
 |  | ||||||
| 
 |  | ||||||
|             jo.put("Method", token); |  | ||||||
|             jo.put("Request-URI", x.nextToken()); |  | ||||||
|             jo.put("HTTP-Version", x.nextToken()); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| // Fields
 |  | ||||||
| 
 |  | ||||||
|         while (x.more()) { |  | ||||||
|             String name = x.nextTo(':'); |  | ||||||
|             x.next(':'); |  | ||||||
|             jo.put(name, x.nextTo('\0')); |  | ||||||
|             x.next(); |  | ||||||
|         } |  | ||||||
|         return jo; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Convert a JSONObject into an HTTP header. A request header must contain |  | ||||||
|      * <pre>{ |  | ||||||
|      *    Method: "POST" (for example), |  | ||||||
|      *    "Request-URI": "/" (for example), |  | ||||||
|      *    "HTTP-Version": "HTTP/1.1" (for example) |  | ||||||
|      * }</pre> |  | ||||||
|      * A response header must contain |  | ||||||
|      * <pre>{ |  | ||||||
|      *    "HTTP-Version": "HTTP/1.1" (for example), |  | ||||||
|      *    "Status-Code": "200" (for example), |  | ||||||
|      *    "Reason-Phrase": "OK" (for example) |  | ||||||
|      * }</pre> |  | ||||||
|      * Any other members of the JSONObject will be output as HTTP fields. |  | ||||||
|      * The result will end with two CRLF pairs. |  | ||||||
|      * @param jo A JSONObject |  | ||||||
|      * @return An HTTP header string. |  | ||||||
|      * @throws JSONException if the object does not contain enough |  | ||||||
|      *  information. |  | ||||||
|      */ |  | ||||||
|     public static String toString(JSONObject jo) throws JSONException { |  | ||||||
|         Iterator     keys = jo.keys(); |  | ||||||
|         String       string; |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { |  | ||||||
|             sb.append(jo.getString("HTTP-Version")); |  | ||||||
|             sb.append(' '); |  | ||||||
|             sb.append(jo.getString("Status-Code")); |  | ||||||
|             sb.append(' '); |  | ||||||
|             sb.append(jo.getString("Reason-Phrase")); |  | ||||||
|         } else if (jo.has("Method") && jo.has("Request-URI")) { |  | ||||||
|             sb.append(jo.getString("Method")); |  | ||||||
|             sb.append(' '); |  | ||||||
|             sb.append('"'); |  | ||||||
|             sb.append(jo.getString("Request-URI")); |  | ||||||
|             sb.append('"'); |  | ||||||
|             sb.append(' '); |  | ||||||
|             sb.append(jo.getString("HTTP-Version")); |  | ||||||
|         } else { |  | ||||||
|             throw new JSONException("Not enough material for an HTTP header."); |  | ||||||
|         } |  | ||||||
|         sb.append(CRLF); |  | ||||||
|         while (keys.hasNext()) { |  | ||||||
|             string = keys.next().toString(); |  | ||||||
|             if (!"HTTP-Version".equals(string)      && !"Status-Code".equals(string) && |  | ||||||
|                     !"Reason-Phrase".equals(string) && !"Method".equals(string) && |  | ||||||
|                     !"Request-URI".equals(string)   && !jo.isNull(string)) { |  | ||||||
|                 sb.append(string); |  | ||||||
|                 sb.append(": "); |  | ||||||
|                 sb.append(jo.getString(string)); |  | ||||||
|                 sb.append(CRLF); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         sb.append(CRLF); |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,77 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * The HTTPTokener extends the JSONTokener to provide additional methods |  | ||||||
|  * for the parsing of HTTP headers. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2010-12-24 |  | ||||||
|  */ |  | ||||||
| public class HTTPTokener extends JSONTokener { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Construct an HTTPTokener from a string. |  | ||||||
|      * @param string A source string. |  | ||||||
|      */ |  | ||||||
|     public HTTPTokener(String string) { |  | ||||||
|         super(string); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Get the next token or string. This is used in parsing HTTP headers. |  | ||||||
|      * @throws JSONException |  | ||||||
|      * @return A String. |  | ||||||
|      */ |  | ||||||
|     public String nextToken() throws JSONException { |  | ||||||
|         char c; |  | ||||||
|         char q; |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         do { |  | ||||||
|             c = next(); |  | ||||||
|         } while (Character.isWhitespace(c)); |  | ||||||
|         if (c == '"' || c == '\'') { |  | ||||||
|             q = c; |  | ||||||
|             for (;;) { |  | ||||||
|                 c = next(); |  | ||||||
|                 if (c < ' ') { |  | ||||||
|                     throw syntaxError("Unterminated string."); |  | ||||||
|                 } |  | ||||||
|                 if (c == q) { |  | ||||||
|                     return sb.toString(); |  | ||||||
|                 } |  | ||||||
|                 sb.append(c); |  | ||||||
|             } |  | ||||||
|         }  |  | ||||||
|         for (;;) { |  | ||||||
|             if (c == 0 || Character.isWhitespace(c)) { |  | ||||||
|                 return sb.toString(); |  | ||||||
|             } |  | ||||||
|             sb.append(c); |  | ||||||
|             c = next(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,920 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| import java.io.IOException; |  | ||||||
| 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> <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> <small>(comma)</small> elision.</li> |  | ||||||
|  * <li>Strings may be quoted with <code>'</code> <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 2011-12-19 |  | ||||||
|  */ |  | ||||||
| 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> <small>(left bracket)</small> |  | ||||||
|      *  and ends with <code>]</code> <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> <small>(left bracket)</small> and ending |  | ||||||
|      *  with <code>]</code> <small>(right bracket)</small>. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public String toString(int indentFactor) throws JSONException { |  | ||||||
|         return this.toString(indentFactor, 0); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 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. |  | ||||||
|      * @param indent The indention of the top level. |  | ||||||
|      * @return a printable, displayable, transmittable |  | ||||||
|      *  representation of the array. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     String toString(int indentFactor, int indent) throws JSONException { |  | ||||||
|         int len = this.length(); |  | ||||||
|         if (len == 0) { |  | ||||||
|             return "[]"; |  | ||||||
|         } |  | ||||||
|         int i; |  | ||||||
|         StringBuffer sb = new StringBuffer("["); |  | ||||||
|         if (len == 1) { |  | ||||||
|             sb.append(JSONObject.valueToString(this.myArrayList.get(0), |  | ||||||
|                     indentFactor, indent)); |  | ||||||
|         } else { |  | ||||||
|             int newindent = indent + indentFactor; |  | ||||||
|             sb.append('\n'); |  | ||||||
|             for (i = 0; i < len; i += 1) { |  | ||||||
|                 if (i > 0) { |  | ||||||
|                     sb.append(",\n"); |  | ||||||
|                 } |  | ||||||
|                 for (int j = 0; j < newindent; j += 1) { |  | ||||||
|                     sb.append(' '); |  | ||||||
|                 } |  | ||||||
|                 sb.append(JSONObject.valueToString(this.myArrayList.get(i), |  | ||||||
|                         indentFactor, newindent)); |  | ||||||
|             } |  | ||||||
|             sb.append('\n'); |  | ||||||
|             for (i = 0; i < indent; i += 1) { |  | ||||||
|                 sb.append(' '); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         sb.append(']'); |  | ||||||
|         return sb.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 { |  | ||||||
|         try { |  | ||||||
|             boolean b = false; |  | ||||||
|             int     len = this.length(); |  | ||||||
| 
 |  | ||||||
|             writer.write('['); |  | ||||||
| 
 |  | ||||||
|             for (int i = 0; i < len; i += 1) { |  | ||||||
|                 if (b) { |  | ||||||
|                     writer.write(','); |  | ||||||
|                 } |  | ||||||
|                 Object v = this.myArrayList.get(i); |  | ||||||
|                 if (v instanceof JSONObject) { |  | ||||||
|                     ((JSONObject)v).write(writer); |  | ||||||
|                 } else if (v instanceof JSONArray) { |  | ||||||
|                     ((JSONArray)v).write(writer); |  | ||||||
|                 } else { |  | ||||||
|                     writer.write(JSONObject.valueToString(v)); |  | ||||||
|                 } |  | ||||||
|                 b = true; |  | ||||||
|             } |  | ||||||
|             writer.write(']'); |  | ||||||
|             return writer; |  | ||||||
|         } catch (IOException e) { |  | ||||||
|            throw new JSONException(e); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| package org.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; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,465 +0,0 @@ | |||||||
| package org.json; |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| Copyright (c) 2008 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 JSONArray or |  | ||||||
|  * JSONObject, and to covert a JSONArray or JSONObject into an XML text using |  | ||||||
|  * the JsonML transform. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2011-11-24 |  | ||||||
|  */ |  | ||||||
| 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("-->"); |  | ||||||
|                             } |  | ||||||
|                             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 && (attribute == "tagName" || attribute == "childNode")) { |  | ||||||
|                             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><[ [ ]]></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><[ [ ]]></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><[ [ ]]></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><[ [ ]]></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(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -1,18 +0,0 @@ | |||||||
| package org.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. |  | ||||||
|  */ |  | ||||||
| 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(); |  | ||||||
| } |  | ||||||
| @ -1,78 +0,0 @@ | |||||||
| package org.json; |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| 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: |  | ||||||
| 
 |  | ||||||
| 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.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. |  | ||||||
|  * <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("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. |  | ||||||
|  * <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()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 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; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,441 +0,0 @@ | |||||||
| package org.json; |  | ||||||
| 
 |  | ||||||
| import java.io.*; |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| 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. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2011-11-24 |  | ||||||
|  */ |  | ||||||
| public class JSONTokener { |  | ||||||
| 
 |  | ||||||
|     private int     character; |  | ||||||
|     private boolean eof; |  | ||||||
|     private int     index; |  | ||||||
|     private int     line; |  | ||||||
|     private char     previous; |  | ||||||
|     private final 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> <small>(double quote)</small> or |  | ||||||
|      *      <code>'</code> <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 { |  | ||||||
|             int startIndex = this.index; |  | ||||||
|             int startCharacter = this.character; |  | ||||||
|             int startLine = this.line; |  | ||||||
|             this.reader.mark(Integer.MAX_VALUE); |  | ||||||
|             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 + "]"; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,327 +0,0 @@ | |||||||
| package org.json; |  | ||||||
| 
 |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.io.Writer; |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| 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: |  | ||||||
| 
 |  | ||||||
| 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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 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("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. |  | ||||||
|  * <p> |  | ||||||
|  * This can sometimes be easier than using a JSONObject to build a string. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2011-11-24 |  | ||||||
|  */ |  | ||||||
| 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 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 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; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 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 (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 (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."); |  | ||||||
|         } |  | ||||||
|         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 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 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 (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 (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 (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 (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 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 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 this.append(JSONObject.valueToString(object)); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,508 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| 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. |  | ||||||
|  * @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> |  | ||||||
|      * & <small>(ampersand)</small> is replaced by &amp; |  | ||||||
|      * < <small>(less than)</small> is replaced by &lt; |  | ||||||
|      * > <small>(greater than)</small> is replaced by &gt; |  | ||||||
|      * " <small>(double quote)</small> is replaced by &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("&"); |  | ||||||
|                 break; |  | ||||||
|             case '<': |  | ||||||
|                 sb.append("<"); |  | ||||||
|                 break; |  | ||||||
|             case '>': |  | ||||||
|                 sb.append(">"); |  | ||||||
|                 break; |  | ||||||
|             case '"': |  | ||||||
|                 sb.append("""); |  | ||||||
|                 break; |  | ||||||
|             case '\'': |  | ||||||
|                 sb.append("'"); |  | ||||||
|                 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(); |  | ||||||
| 
 |  | ||||||
| // <!
 |  | ||||||
| 
 |  | ||||||
|         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) { |  | ||||||
| 
 |  | ||||||
| // 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"); |  | ||||||
| 
 |  | ||||||
| // Open tag <
 |  | ||||||
| 
 |  | ||||||
|         } 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, ""); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
| // 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; |  | ||||||
| 
 |  | ||||||
| // 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)); |  | ||||||
|                             } |  | ||||||
| 
 |  | ||||||
| // 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 ("".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><[ [ ]]></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('>'); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
| // 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; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
| // Emit content in body
 |  | ||||||
| 
 |  | ||||||
|                 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 ("".equals(value)) { |  | ||||||
|                     sb.append('<'); |  | ||||||
|                     sb.append(key); |  | ||||||
|                     sb.append("/>"); |  | ||||||
| 
 |  | ||||||
| // Emit a new tag <k>
 |  | ||||||
| 
 |  | ||||||
|                 } else { |  | ||||||
|                     sb.append(toString(value, key)); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if (tagName != null) { |  | ||||||
| 
 |  | ||||||
| // Emit the </tagname> close tag
 |  | ||||||
| 
 |  | ||||||
|                 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 + ">"; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,365 +0,0 @@ | |||||||
| package org.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. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * The XMLTokener extends the JSONTokener to provide additional methods |  | ||||||
|  * for the parsing of XML texts. |  | ||||||
|  * @author JSON.org |  | ||||||
|  * @version 2010-12-24 |  | ||||||
|  */ |  | ||||||
| public class XMLTokener extends JSONTokener { |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|    /** The table of entity values. It initially contains Character values for |  | ||||||
|     * amp, apos, gt, lt, quot. |  | ||||||
|     */ |  | ||||||
|    public static final java.util.HashMap entity; |  | ||||||
| 
 |  | ||||||
|    static { |  | ||||||
|        entity = new java.util.HashMap(8); |  | ||||||
|        entity.put("amp",  XML.AMP); |  | ||||||
|        entity.put("apos", XML.APOS); |  | ||||||
|        entity.put("gt",   XML.GT); |  | ||||||
|        entity.put("lt",   XML.LT); |  | ||||||
|        entity.put("quot", XML.QUOT); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Construct an XMLTokener from a string. |  | ||||||
|      * @param s A source string. |  | ||||||
|      */ |  | ||||||
|     public XMLTokener(String s) { |  | ||||||
|         super(s); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Get the text in the CDATA block. |  | ||||||
|      * @return The string up to the <code>]]></code>. |  | ||||||
|      * @throws JSONException If the <code>]]></code> is not found. |  | ||||||
|      */ |  | ||||||
|     public String nextCDATA() throws JSONException { |  | ||||||
|         char         c; |  | ||||||
|         int          i; |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         for (;;) { |  | ||||||
|             c = next(); |  | ||||||
|             if (end()) { |  | ||||||
|                 throw syntaxError("Unclosed CDATA"); |  | ||||||
|             } |  | ||||||
|             sb.append(c); |  | ||||||
|             i = sb.length() - 3; |  | ||||||
|             if (i >= 0 && sb.charAt(i) == ']' && |  | ||||||
|                           sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { |  | ||||||
|                 sb.setLength(i); |  | ||||||
|                 return sb.toString(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Get the next XML outer token, trimming whitespace. There are two kinds |  | ||||||
|      * of tokens: the '<' character which begins a markup tag, and the content |  | ||||||
|      * text between markup tags. |  | ||||||
|      * |  | ||||||
|      * @return  A string, or a '<' Character, or null if there is no more |  | ||||||
|      * source text. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public Object nextContent() throws JSONException { |  | ||||||
|         char         c; |  | ||||||
|         StringBuffer sb; |  | ||||||
|         do { |  | ||||||
|             c = next(); |  | ||||||
|         } while (Character.isWhitespace(c)); |  | ||||||
|         if (c == 0) { |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
|         if (c == '<') { |  | ||||||
|             return XML.LT; |  | ||||||
|         } |  | ||||||
|         sb = new StringBuffer(); |  | ||||||
|         for (;;) { |  | ||||||
|             if (c == '<' || c == 0) { |  | ||||||
|                 back(); |  | ||||||
|                 return sb.toString().trim(); |  | ||||||
|             } |  | ||||||
|             if (c == '&') { |  | ||||||
|                 sb.append(nextEntity(c)); |  | ||||||
|             } else { |  | ||||||
|                 sb.append(c); |  | ||||||
|             } |  | ||||||
|             c = next(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Return the next entity. These entities are translated to Characters: |  | ||||||
|      *     <code>&  '  >  <  "</code>. |  | ||||||
|      * @param ampersand An ampersand character. |  | ||||||
|      * @return  A Character or an entity String if the entity is not recognized. |  | ||||||
|      * @throws JSONException If missing ';' in XML entity. |  | ||||||
|      */ |  | ||||||
|     public Object nextEntity(char ampersand) throws JSONException { |  | ||||||
|         StringBuffer sb = new StringBuffer(); |  | ||||||
|         for (;;) { |  | ||||||
|             char c = next(); |  | ||||||
|             if (Character.isLetterOrDigit(c) || c == '#') { |  | ||||||
|                 sb.append(Character.toLowerCase(c)); |  | ||||||
|             } else if (c == ';') { |  | ||||||
|                 break; |  | ||||||
|             } else { |  | ||||||
|                 throw syntaxError("Missing ';' in XML entity: &" + sb); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         String string = sb.toString(); |  | ||||||
|         Object object = entity.get(string); |  | ||||||
|         return object != null ? object : ampersand + string + ";"; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns the next XML meta token. This is used for skipping over <!...> |  | ||||||
|      * and <?...?> structures. |  | ||||||
|      * @return Syntax characters (<code>< > / = ! ?</code>) are returned as |  | ||||||
|      *  Character, and strings and names are returned as Boolean. We don't care |  | ||||||
|      *  what the values actually are. |  | ||||||
|      * @throws JSONException If a string is not properly closed or if the XML |  | ||||||
|      *  is badly structured. |  | ||||||
|      */ |  | ||||||
|     public Object nextMeta() throws JSONException { |  | ||||||
|         char c; |  | ||||||
|         char q; |  | ||||||
|         do { |  | ||||||
|             c = next(); |  | ||||||
|         } while (Character.isWhitespace(c)); |  | ||||||
|         switch (c) { |  | ||||||
|         case 0: |  | ||||||
|             throw syntaxError("Misshaped meta tag"); |  | ||||||
|         case '<': |  | ||||||
|             return XML.LT; |  | ||||||
|         case '>': |  | ||||||
|             return XML.GT; |  | ||||||
|         case '/': |  | ||||||
|             return XML.SLASH; |  | ||||||
|         case '=': |  | ||||||
|             return XML.EQ; |  | ||||||
|         case '!': |  | ||||||
|             return XML.BANG; |  | ||||||
|         case '?': |  | ||||||
|             return XML.QUEST; |  | ||||||
|         case '"': |  | ||||||
|         case '\'': |  | ||||||
|             q = c; |  | ||||||
|             for (;;) { |  | ||||||
|                 c = next(); |  | ||||||
|                 if (c == 0) { |  | ||||||
|                     throw syntaxError("Unterminated string"); |  | ||||||
|                 } |  | ||||||
|                 if (c == q) { |  | ||||||
|                     return Boolean.TRUE; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         default: |  | ||||||
|             for (;;) { |  | ||||||
|                 c = next(); |  | ||||||
|                 if (Character.isWhitespace(c)) { |  | ||||||
|                     return Boolean.TRUE; |  | ||||||
|                 } |  | ||||||
|                 switch (c) { |  | ||||||
|                 case 0: |  | ||||||
|                 case '<': |  | ||||||
|                 case '>': |  | ||||||
|                 case '/': |  | ||||||
|                 case '=': |  | ||||||
|                 case '!': |  | ||||||
|                 case '?': |  | ||||||
|                 case '"': |  | ||||||
|                 case '\'': |  | ||||||
|                     back(); |  | ||||||
|                     return Boolean.TRUE; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Get the next XML Token. These tokens are found inside of angle |  | ||||||
|      * brackets. It may be one of these characters: <code>/ > = ! ?</code> or it |  | ||||||
|      * may be a string wrapped in single quotes or double quotes, or it may be a |  | ||||||
|      * name. |  | ||||||
|      * @return a String or a Character. |  | ||||||
|      * @throws JSONException If the XML is not well formed. |  | ||||||
|      */ |  | ||||||
|     public Object nextToken() throws JSONException { |  | ||||||
|         char c; |  | ||||||
|         char q; |  | ||||||
|         StringBuffer sb; |  | ||||||
|         do { |  | ||||||
|             c = next(); |  | ||||||
|         } while (Character.isWhitespace(c)); |  | ||||||
|         switch (c) { |  | ||||||
|         case 0: |  | ||||||
|             throw syntaxError("Misshaped element"); |  | ||||||
|         case '<': |  | ||||||
|             throw syntaxError("Misplaced '<'"); |  | ||||||
|         case '>': |  | ||||||
|             return XML.GT; |  | ||||||
|         case '/': |  | ||||||
|             return XML.SLASH; |  | ||||||
|         case '=': |  | ||||||
|             return XML.EQ; |  | ||||||
|         case '!': |  | ||||||
|             return XML.BANG; |  | ||||||
|         case '?': |  | ||||||
|             return XML.QUEST; |  | ||||||
| 
 |  | ||||||
| // Quoted string
 |  | ||||||
| 
 |  | ||||||
|         case '"': |  | ||||||
|         case '\'': |  | ||||||
|             q = c; |  | ||||||
|             sb = new StringBuffer(); |  | ||||||
|             for (;;) { |  | ||||||
|                 c = next(); |  | ||||||
|                 if (c == 0) { |  | ||||||
|                     throw syntaxError("Unterminated string"); |  | ||||||
|                 } |  | ||||||
|                 if (c == q) { |  | ||||||
|                     return sb.toString(); |  | ||||||
|                 } |  | ||||||
|                 if (c == '&') { |  | ||||||
|                     sb.append(nextEntity(c)); |  | ||||||
|                 } else { |  | ||||||
|                     sb.append(c); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         default: |  | ||||||
| 
 |  | ||||||
| // Name
 |  | ||||||
| 
 |  | ||||||
|             sb = new StringBuffer(); |  | ||||||
|             for (;;) { |  | ||||||
|                 sb.append(c); |  | ||||||
|                 c = next(); |  | ||||||
|                 if (Character.isWhitespace(c)) { |  | ||||||
|                     return sb.toString(); |  | ||||||
|                 } |  | ||||||
|                 switch (c) { |  | ||||||
|                 case 0: |  | ||||||
|                     return sb.toString(); |  | ||||||
|                 case '>': |  | ||||||
|                 case '/': |  | ||||||
|                 case '=': |  | ||||||
|                 case '!': |  | ||||||
|                 case '?': |  | ||||||
|                 case '[': |  | ||||||
|                 case ']': |  | ||||||
|                     back(); |  | ||||||
|                     return sb.toString(); |  | ||||||
|                 case '<': |  | ||||||
|                 case '"': |  | ||||||
|                 case '\'': |  | ||||||
|                     throw syntaxError("Bad character in a name"); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|      |  | ||||||
|     /** |  | ||||||
|      * Skip characters until past the requested string. |  | ||||||
|      * If it is not found, we are left at the end of the source with a result of false. |  | ||||||
|      * @param to A string to skip past. |  | ||||||
|      * @throws JSONException |  | ||||||
|      */ |  | ||||||
|     public boolean skipPast(String to) throws JSONException { |  | ||||||
|         boolean b; |  | ||||||
|         char c; |  | ||||||
|         int i; |  | ||||||
|         int j; |  | ||||||
|         int offset = 0; |  | ||||||
|         int length = to.length(); |  | ||||||
|         char[] circle = new char[length]; |  | ||||||
|          |  | ||||||
|         /* |  | ||||||
|          * First fill the circle buffer with as many characters as are in the |  | ||||||
|          * to string. If we reach an early end, bail. |  | ||||||
|          */ |  | ||||||
|          |  | ||||||
|         for (i = 0; i < length; i += 1) { |  | ||||||
|             c = next(); |  | ||||||
|             if (c == 0) { |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|             circle[i] = c; |  | ||||||
|         } |  | ||||||
|         /* |  | ||||||
|          * We will loop, possibly for all of the remaining characters. |  | ||||||
|          */ |  | ||||||
|         for (;;) { |  | ||||||
|             j = offset; |  | ||||||
|             b = true; |  | ||||||
|             /* |  | ||||||
|              * Compare the circle buffer with the to string.  |  | ||||||
|              */ |  | ||||||
|             for (i = 0; i < length; i += 1) { |  | ||||||
|                 if (circle[j] != to.charAt(i)) { |  | ||||||
|                     b = false; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 j += 1; |  | ||||||
|                 if (j >= length) { |  | ||||||
|                     j -= length; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             /* |  | ||||||
|              * If we exit the loop with b intact, then victory is ours. |  | ||||||
|              */ |  | ||||||
|             if (b) { |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
|             /* |  | ||||||
|              * Get the next character. If there isn't one, then defeat is ours. |  | ||||||
|              */ |  | ||||||
|             c = next(); |  | ||||||
|             if (c == 0) { |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|             /* |  | ||||||
|              * Shove the character in the circle buffer and advance the  |  | ||||||
|              * circle offset. The offset is mod n. |  | ||||||
|              */ |  | ||||||
|             circle[offset] = c; |  | ||||||
|             offset += 1; |  | ||||||
|             if (offset >= length) { |  | ||||||
|                 offset -= length; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,45 +0,0 @@ | |||||||
| /* |  | ||||||
|  This file is part of Libresonic. |  | ||||||
| 
 |  | ||||||
|  Libresonic is free software: you can redistribute it and/or modify |  | ||||||
|  it under the terms of the GNU General Public License as published by |  | ||||||
|  the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  (at your option) any later version. |  | ||||||
| 
 |  | ||||||
|  Libresonic is distributed in the hope that it will be useful, |  | ||||||
|  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  GNU General Public License for more details. |  | ||||||
| 
 |  | ||||||
|  You should have received a copy of the GNU General Public License |  | ||||||
|  along with Libresonic.  If not, see <http://www.gnu.org/licenses/>.
 |  | ||||||
| 
 |  | ||||||
|  Copyright 2016 (C) Libresonic Authors |  | ||||||
|  Based upon Subsonic, Copyright 2009 (C) Sindre Mehus |  | ||||||
|  */ |  | ||||||
| package org.libresonic.player.service; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Provides services for generating ads. |  | ||||||
|  * |  | ||||||
|  * @author Sindre Mehus |  | ||||||
|  */ |  | ||||||
| public class AdService { |  | ||||||
| 
 |  | ||||||
|     private int adInterval; |  | ||||||
|     private int pageCount; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns whether an ad should be displayed. |  | ||||||
|      */ |  | ||||||
|     public boolean showAd() { |  | ||||||
|         return pageCount++ % adInterval == 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Set by Spring. |  | ||||||
|      */ |  | ||||||
|     public void setAdInterval(int adInterval) { |  | ||||||
|         this.adInterval = adInterval; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,49 +0,0 @@ | |||||||
| /** |  | ||||||
|  * This file is part of Libresonic. |  | ||||||
|  * |  | ||||||
|  *  Libresonic is free software: you can redistribute it and/or modify |  | ||||||
|  *  it under the terms of the GNU General Public License as published by |  | ||||||
|  *  the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  *  (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  Libresonic is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with Libresonic.  If not, see <http://www.gnu.org/licenses/>.
 |  | ||||||
|  * |  | ||||||
|  *  Copyright 2014 (C) Sindre Mehus |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package org.libresonic.player.service; |  | ||||||
| 
 |  | ||||||
| import de.umass.lastfm.cache.ExpirationPolicy; |  | ||||||
| 
 |  | ||||||
| import java.util.LinkedHashMap; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Artist and album info is cached permanently. Everything else is cached one year. |  | ||||||
|  * |  | ||||||
|  * @author Sindre Mehus |  | ||||||
|  * @version $Id$ |  | ||||||
|  */ |  | ||||||
| public class LastFmExpirationPolicy implements ExpirationPolicy { |  | ||||||
| 
 |  | ||||||
|     private final static long ONE_YEAR = 12 * 30 * 24 * 3600 * 1000L; |  | ||||||
| 
 |  | ||||||
|     private final Map<String, Long> methodToExpirationTime = new LinkedHashMap<String, Long>() {{ |  | ||||||
|         put("artist.getInfo", Long.MAX_VALUE);  // Cache forever
 |  | ||||||
|         put("album.getInfo", Long.MAX_VALUE);   // Cache forever
 |  | ||||||
|         put("album.search", -1L);               // Don't cache
 |  | ||||||
|     }}; |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public long getExpirationTime(String method, Map<String, String> params) { |  | ||||||
|         Long expirationTime = methodToExpirationTime.get(method); |  | ||||||
|         return expirationTime == null ? ONE_YEAR : expirationTime; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @ -1,143 +0,0 @@ | |||||||
| /* |  | ||||||
|  This file is part of Libresonic. |  | ||||||
| 
 |  | ||||||
|  Libresonic is free software: you can redistribute it and/or modify |  | ||||||
|  it under the terms of the GNU General Public License as published by |  | ||||||
|  the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  (at your option) any later version. |  | ||||||
| 
 |  | ||||||
|  Libresonic is distributed in the hope that it will be useful, |  | ||||||
|  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  GNU General Public License for more details. |  | ||||||
| 
 |  | ||||||
|  You should have received a copy of the GNU General Public License |  | ||||||
|  along with Libresonic.  If not, see <http://www.gnu.org/licenses/>.
 |  | ||||||
| 
 |  | ||||||
|  Copyright 2016 (C) Libresonic Authors |  | ||||||
|  Based upon Subsonic, Copyright 2009 (C) Sindre Mehus |  | ||||||
|  */ |  | ||||||
| package org.libresonic.player.service.upnp; |  | ||||||
| 
 |  | ||||||
| import org.fourthline.cling.UpnpService; |  | ||||||
| import org.fourthline.cling.model.action.ActionInvocation; |  | ||||||
| import org.fourthline.cling.model.message.UpnpResponse; |  | ||||||
| import org.fourthline.cling.model.meta.Device; |  | ||||||
| import org.fourthline.cling.model.meta.Service; |  | ||||||
| import org.fourthline.cling.support.igd.PortMappingListener; |  | ||||||
| import org.fourthline.cling.support.igd.callback.PortMappingAdd; |  | ||||||
| import org.fourthline.cling.support.igd.callback.PortMappingDelete; |  | ||||||
| import org.fourthline.cling.support.model.PortMapping; |  | ||||||
| import org.libresonic.player.service.UPnPService; |  | ||||||
| 
 |  | ||||||
| import java.net.InetAddress; |  | ||||||
| import java.net.UnknownHostException; |  | ||||||
| import java.util.Collection; |  | ||||||
| import java.util.concurrent.Semaphore; |  | ||||||
| import java.util.concurrent.atomic.AtomicReference; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * @author Sindre Mehus |  | ||||||
| * @version $Id$ |  | ||||||
| */ |  | ||||||
| public class ClingRouter implements Router { |  | ||||||
| 
 |  | ||||||
|     private final Service connectionService; |  | ||||||
|     private final UpnpService upnpService; |  | ||||||
| 
 |  | ||||||
|     public static ClingRouter findRouter(UPnPService upnpService) { |  | ||||||
|         final Service connectionService = findConnectionService(upnpService.getUpnpService()); |  | ||||||
|         if (connectionService == null) { |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
|         return new ClingRouter(connectionService, upnpService.getUpnpService()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns the UPnP service used for port mapping. |  | ||||||
|      */ |  | ||||||
|     private static Service findConnectionService(UpnpService upnpService) { |  | ||||||
| 
 |  | ||||||
|         class ConnectionServiceDiscoverer extends PortMappingListener { |  | ||||||
|             ConnectionServiceDiscoverer() { |  | ||||||
|                 super(new PortMapping[0]); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public Service discoverConnectionService(Device device) { |  | ||||||
|                 return super.discoverConnectionService(device); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ConnectionServiceDiscoverer discoverer = new ConnectionServiceDiscoverer(); |  | ||||||
|         Collection<Device> devices = upnpService.getRegistry().getDevices(); |  | ||||||
|         for (Device device : devices) { |  | ||||||
|             Service service = discoverer.discoverConnectionService(device); |  | ||||||
|             if (service != null) { |  | ||||||
|                 return service; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public ClingRouter(Service connectionService, UpnpService upnpService) { |  | ||||||
|         this.connectionService = connectionService; |  | ||||||
|         this.upnpService = upnpService; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void addPortMapping(int externalPort, int internalPort, int leaseDuration) throws Exception { |  | ||||||
|         addPortMappingImpl(connectionService, internalPort); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void deletePortMapping(int externalPort, int internalPort) throws Exception { |  | ||||||
|         deletePortMappingImpl(connectionService, internalPort); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void addPortMappingImpl(Service connectionService, int port) throws Exception { |  | ||||||
|         final Semaphore gotReply = new Semaphore(0); |  | ||||||
|         final AtomicReference<String> error = new AtomicReference<String>(); |  | ||||||
|         upnpService.getControlPoint().execute( |  | ||||||
|                 new PortMappingAdd(connectionService, createPortMapping(port)) { |  | ||||||
| 
 |  | ||||||
|                     @Override |  | ||||||
|                     public void success(ActionInvocation invocation) { |  | ||||||
|                         gotReply.release(); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     @Override |  | ||||||
|                     public void failure(ActionInvocation invocation, UpnpResponse response, String defaultMsg) { |  | ||||||
|                         error.set(String.valueOf(response) + ": " + defaultMsg); |  | ||||||
|                         gotReply.release(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|         ); |  | ||||||
|         gotReply.acquire(); |  | ||||||
|         if (error.get() != null) { |  | ||||||
|             throw new Exception(error.get()); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void deletePortMappingImpl(Service connectionService, int port) throws Exception { |  | ||||||
|         final Semaphore gotReply = new Semaphore(0); |  | ||||||
|         upnpService.getControlPoint().execute( |  | ||||||
|                 new PortMappingDelete(connectionService, createPortMapping(port)) { |  | ||||||
| 
 |  | ||||||
|                     @Override |  | ||||||
|                     public void success(ActionInvocation invocation) { |  | ||||||
|                         gotReply.release(); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     @Override |  | ||||||
|                     public void failure(ActionInvocation invocation, UpnpResponse response, String defaultMsg) { |  | ||||||
|                         gotReply.release(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|         ); |  | ||||||
|         gotReply.acquire(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private PortMapping createPortMapping(int port) throws UnknownHostException { |  | ||||||
|         String localIp = InetAddress.getLocalHost().getHostAddress(); |  | ||||||
|         return new PortMapping(port, localIp, PortMapping.Protocol.TCP, "Libresonic"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
					Loading…
					
					
				
		Reference in new issue