Formatted .java files.
This commit is contained in:
@ -3,27 +3,27 @@ package com.thetransactioncompany.jsonrpc2;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 error that occured during the processing of a
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 error that occured during the processing of a
|
||||
* request.
|
||||
*
|
||||
* <p>The protocol expects error objects to be structured like this:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code code} An integer that indicates the error type.
|
||||
* <li>{@code message} A string providing a short description of the
|
||||
* <li>{@code message} A string providing a short description of the
|
||||
* error. The message should be limited to a concise single sentence.
|
||||
* <li>{@code data} Additional information, which may be omitted. Its
|
||||
* <li>{@code data} Additional information, which may be omitted. Its
|
||||
* contents is entirely defined by the application.
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <p>Note that the "Error" word in the class name was put there solely to
|
||||
* comply with the parlance of the JSON-RPC spec. This class doesn't inherit
|
||||
* from {@code java.lang.Error}. It's a regular subclass of
|
||||
* {@code java.lang.Exception} and, if thrown, it's to indicate a condition
|
||||
* comply with the parlance of the JSON-RPC spec. This class doesn't inherit
|
||||
* from {@code java.lang.Error}. It's a regular subclass of
|
||||
* {@code java.lang.Exception} and, if thrown, it's to indicate a condition
|
||||
* that a reasonable application might want to catch.
|
||||
*
|
||||
* <p>This class also includes convenient final static instances for all
|
||||
* <p>This class also includes convenient final static instances for all
|
||||
* standard JSON-RPC 2.0 errors:
|
||||
*
|
||||
* <ul>
|
||||
@ -34,11 +34,11 @@ import org.json.simple.JSONObject;
|
||||
* <li>{@link #INTERNAL_ERROR} Internal error (-32603)
|
||||
* </ul>
|
||||
*
|
||||
* <p>Note that the range -32099..-32000 is reserved for additional server
|
||||
* <p>Note that the range -32099..-32000 is reserved for additional server
|
||||
* errors.
|
||||
*
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <pre>
|
||||
* true|false <---> java.lang.Boolean
|
||||
* number <---> java.lang.Number
|
||||
@ -48,123 +48,123 @@ import org.json.simple.JSONObject;
|
||||
* null <---> null
|
||||
* </pre>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2010-10-04)
|
||||
*/
|
||||
public class JSONRPC2Error extends Exception {
|
||||
|
||||
|
||||
/** JSON parse error (-32700) */
|
||||
public static final JSONRPC2Error PARSE_ERROR = new JSONRPC2Error(-32700, "JSON parse error");
|
||||
|
||||
|
||||
/** Invalid JSON-RPC 2.0 request error (-32600) */
|
||||
public static final JSONRPC2Error INVALID_REQUEST = new JSONRPC2Error(-32600, "Invalid request");
|
||||
|
||||
|
||||
/** Method not found error (-32601) */
|
||||
public static final JSONRPC2Error METHOD_NOT_FOUND = new JSONRPC2Error(-32601, "Method not found");
|
||||
|
||||
|
||||
/** Invalid parameters error (-32602) */
|
||||
public static final JSONRPC2Error INVALID_PARAMS = new JSONRPC2Error(-32602, "Invalid parameters");
|
||||
|
||||
|
||||
/** Internal JSON-RPC 2.0 error (-32603) */
|
||||
public static final JSONRPC2Error INTERNAL_ERROR = new JSONRPC2Error(-32603, "Internal error");
|
||||
|
||||
|
||||
/** The error code */
|
||||
protected int code;
|
||||
|
||||
|
||||
/** The optional error data */
|
||||
protected Object data;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code and
|
||||
* message. The optional data is omitted.
|
||||
*
|
||||
* @param code The error code (standard pre-defined or
|
||||
* application-specific).
|
||||
* @param message The error message.
|
||||
*/
|
||||
public JSONRPC2Error(int code, String message) {
|
||||
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code,
|
||||
* message and data.
|
||||
*
|
||||
* @param code The error code (standard pre-defined or
|
||||
* application-specific).
|
||||
* @param message The error message.
|
||||
* @param data Optional error data, must <a href="#map">map</a>
|
||||
* to a valid JSON type.
|
||||
*/
|
||||
public JSONRPC2Error(int code, String message, Object data) {
|
||||
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 error code.
|
||||
*
|
||||
* @return The error code.
|
||||
*/
|
||||
public int getCode() {
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 error data.
|
||||
*
|
||||
* @return The error data, {@code null} if none was specified.
|
||||
*/
|
||||
public Object getData() {
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of the JSON-RPC 2.0 error.
|
||||
*
|
||||
* @return A JSON object representing this error object.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject out = new JSONObject();
|
||||
|
||||
out.put("code", code);
|
||||
out.put("message", super.getMessage());
|
||||
if (data != null)
|
||||
out.put("data", data);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialises the error object to a JSON string.
|
||||
*
|
||||
* @return A JSON-encoded string representing this error object.
|
||||
*/
|
||||
public String toString() {
|
||||
|
||||
return toJSON().toString();
|
||||
}
|
||||
|
||||
|
||||
/** JSON parse error (-32700) */
|
||||
public static final JSONRPC2Error PARSE_ERROR = new JSONRPC2Error(-32700, "JSON parse error");
|
||||
|
||||
|
||||
/** Invalid JSON-RPC 2.0 request error (-32600) */
|
||||
public static final JSONRPC2Error INVALID_REQUEST = new JSONRPC2Error(-32600, "Invalid request");
|
||||
|
||||
|
||||
/** Method not found error (-32601) */
|
||||
public static final JSONRPC2Error METHOD_NOT_FOUND = new JSONRPC2Error(-32601, "Method not found");
|
||||
|
||||
|
||||
/** Invalid parameters error (-32602) */
|
||||
public static final JSONRPC2Error INVALID_PARAMS = new JSONRPC2Error(-32602, "Invalid parameters");
|
||||
|
||||
|
||||
/** Internal JSON-RPC 2.0 error (-32603) */
|
||||
public static final JSONRPC2Error INTERNAL_ERROR = new JSONRPC2Error(-32603, "Internal error");
|
||||
|
||||
|
||||
/** The error code */
|
||||
protected int code;
|
||||
|
||||
|
||||
/** The optional error data */
|
||||
protected Object data;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code and
|
||||
* message. The optional data is omitted.
|
||||
*
|
||||
* @param code The error code (standard pre-defined or
|
||||
* application-specific).
|
||||
* @param message The error message.
|
||||
*/
|
||||
public JSONRPC2Error(int code, String message) {
|
||||
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code,
|
||||
* message and data.
|
||||
*
|
||||
* @param code The error code (standard pre-defined or
|
||||
* application-specific).
|
||||
* @param message The error message.
|
||||
* @param data Optional error data, must <a href="#map">map</a>
|
||||
* to a valid JSON type.
|
||||
*/
|
||||
public JSONRPC2Error(int code, String message, Object data) {
|
||||
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 error code.
|
||||
*
|
||||
* @return The error code.
|
||||
*/
|
||||
public int getCode() {
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 error data.
|
||||
*
|
||||
* @return The error data, {@code null} if none was specified.
|
||||
*/
|
||||
public Object getData() {
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of the JSON-RPC 2.0 error.
|
||||
*
|
||||
* @return A JSON object representing this error object.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject out = new JSONObject();
|
||||
|
||||
out.put("code", code);
|
||||
out.put("message", super.getMessage());
|
||||
if (data != null)
|
||||
out.put("data", data);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialises the error object to a JSON string.
|
||||
*
|
||||
* @return A JSON-encoded string representing this error object.
|
||||
*/
|
||||
public String toString() {
|
||||
|
||||
return toJSON().toString();
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ import org.json.simple.JSONObject;
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <pre>
|
||||
* true|false <---> java.lang.Boolean
|
||||
* number <---> java.lang.Number
|
||||
@ -46,101 +46,101 @@ import org.json.simple.JSONObject;
|
||||
* null <---> null
|
||||
* </pre>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2011-05-19)
|
||||
*/
|
||||
public abstract class JSONRPC2Message {
|
||||
|
||||
|
||||
/**
|
||||
* Provides common parsing of JSON-RPC 2.0 requests, notifications
|
||||
* and responses. Use this method if you don't know which type of
|
||||
* JSON-RPC message the input string represents.
|
||||
*
|
||||
* <p>This method is thread-safe. Batched requests / notifications
|
||||
* are not supported.
|
||||
*
|
||||
* <p>If you are certain about the message type use the dedicated
|
||||
* {@link JSONRPC2Request#parse}, {@link JSONRPC2Notification#parse}
|
||||
* and {@link JSONRPC2Response#parse} methods. They are more efficient
|
||||
* and would provide you with more detailed parse error reporting.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString A JSON string representing a JSON-RPC 2.0 request,
|
||||
* notification or response, UTF-8 encoded.
|
||||
*
|
||||
* @return An instance of {@link JSONRPC2Request},
|
||||
* {@link JSONRPC2Notification} or {@link JSONRPC2Response}.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Message parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
/**
|
||||
* Provides common parsing of JSON-RPC 2.0 requests, notifications
|
||||
* and responses. Use this method if you don't know which type of
|
||||
* JSON-RPC message the input string represents.
|
||||
*
|
||||
* <p>This method is thread-safe. Batched requests / notifications
|
||||
* are not supported.
|
||||
*
|
||||
* <p>If you are certain about the message type use the dedicated
|
||||
* {@link JSONRPC2Request#parse}, {@link JSONRPC2Notification#parse}
|
||||
* and {@link JSONRPC2Response#parse} methods. They are more efficient
|
||||
* and would provide you with more detailed parse error reporting.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString A JSON string representing a JSON-RPC 2.0 request,
|
||||
* notification or response, UTF-8 encoded.
|
||||
*
|
||||
* @return An instance of {@link JSONRPC2Request},
|
||||
* {@link JSONRPC2Notification} or {@link JSONRPC2Response}.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Message parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides common parsing of JSON-RPC 2.0 requests, notifications
|
||||
* and responses. Use this method if you don't know which type of
|
||||
* JSON-RPC message the input string represents.
|
||||
*
|
||||
* <p>This method is thread-safe. Batched requests / notifications
|
||||
* are not supported.
|
||||
*
|
||||
* <p>If you are certain about the message type use the dedicated
|
||||
* {@link JSONRPC2Request#parse}, {@link JSONRPC2Notification#parse}
|
||||
* and {@link JSONRPC2Response#parse} methods. They are more efficient
|
||||
* and would provide you with more detailed parse error reporting.
|
||||
*
|
||||
* @param jsonString A JSON string representing a JSON-RPC 2.0
|
||||
* request, notification or response, UTF-8
|
||||
* encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters and results will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return An instance of {@link JSONRPC2Request},
|
||||
* {@link JSONRPC2Notification} or {@link JSONRPC2Response}.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Message parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Message(jsonString);
|
||||
}
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON object representing this message.
|
||||
*
|
||||
* @return A JSON object.
|
||||
*/
|
||||
public abstract JSONObject toJSON();
|
||||
|
||||
|
||||
/**
|
||||
* Serialises this message to a JSON string.
|
||||
*
|
||||
* @return A JSON-RPC 2.0 encoded string.
|
||||
*/
|
||||
public String toString() {
|
||||
|
||||
return toJSON().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides common parsing of JSON-RPC 2.0 requests, notifications
|
||||
* and responses. Use this method if you don't know which type of
|
||||
* JSON-RPC message the input string represents.
|
||||
*
|
||||
* <p>This method is thread-safe. Batched requests / notifications
|
||||
* are not supported.
|
||||
*
|
||||
* <p>If you are certain about the message type use the dedicated
|
||||
* {@link JSONRPC2Request#parse}, {@link JSONRPC2Notification#parse}
|
||||
* and {@link JSONRPC2Response#parse} methods. They are more efficient
|
||||
* and would provide you with more detailed parse error reporting.
|
||||
*
|
||||
* @param jsonString A JSON string representing a JSON-RPC 2.0
|
||||
* request, notification or response, UTF-8
|
||||
* encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters and results will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return An instance of {@link JSONRPC2Request},
|
||||
* {@link JSONRPC2Notification} or {@link JSONRPC2Response}.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Message parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Message(jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON object representing this message.
|
||||
*
|
||||
* @return A JSON object.
|
||||
*/
|
||||
public abstract JSONObject toJSON();
|
||||
|
||||
|
||||
/**
|
||||
* Serialises this message to a JSON string.
|
||||
*
|
||||
* @return A JSON-RPC 2.0 encoded string.
|
||||
*/
|
||||
public String toString() {
|
||||
|
||||
return toJSON().toString();
|
||||
}
|
||||
}
|
||||
|
@ -6,27 +6,27 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 notification.
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 notification.
|
||||
*
|
||||
* <p>Notifications provide a mean for calling a remote procedure without
|
||||
* generating a response. Note that notifications are inherently unreliable
|
||||
* <p>Notifications provide a mean for calling a remote procedure without
|
||||
* generating a response. Note that notifications are inherently unreliable
|
||||
* as no confirmation is sent back to the caller.
|
||||
*
|
||||
* <p>Notifications have the same JSON structure as requests, except that they
|
||||
* lack an identifier:
|
||||
* <ul>
|
||||
* <li>{@code method} The name of the remote method to call.
|
||||
* <li>{@code params} The required method parameters (if any), which can
|
||||
* <li>{@code params} The required method parameters (if any), which can
|
||||
* be packed into a JSON array or object.
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol version
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol version
|
||||
* set to "2.0".
|
||||
* </ul>
|
||||
*
|
||||
* <p>Here is a sample JSON-RPC 2.0 notification string:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* {
|
||||
* "method" : "progressNotify",
|
||||
* "params" : ["75%"],
|
||||
* "jsonrpc" : "2.0"
|
||||
@ -35,8 +35,8 @@ import java.util.Map;
|
||||
*
|
||||
* <p>This class provides two methods to obtain a request object:
|
||||
* <ul>
|
||||
* <li>Pass a JSON-RPC 2.0 notification string to the static
|
||||
* {@link #parse} method, or
|
||||
* <li>Pass a JSON-RPC 2.0 notification string to the static
|
||||
* {@link #parse} method, or
|
||||
* <li>Invoke one of the constructors with the appropriate arguments.
|
||||
* </ul>
|
||||
*
|
||||
@ -44,9 +44,9 @@ import java.util.Map;
|
||||
*
|
||||
* <pre>
|
||||
* String jsonString = "{\"method\":\"progressNotify\",\"params\":[\"75%\"],\"jsonrpc\":\"2.0\"}";
|
||||
*
|
||||
*
|
||||
* JSONRPC2Notification notification = null;
|
||||
*
|
||||
*
|
||||
* try {
|
||||
* notification = JSONRPC2Notification.parse(jsonString);
|
||||
*
|
||||
@ -56,7 +56,7 @@ import java.util.Map;
|
||||
* </pre>
|
||||
*
|
||||
* <p>Example 2: Recreating the above request:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* String method = "progressNotify";
|
||||
* List params = new Vector();
|
||||
@ -67,8 +67,8 @@ import java.util.Map;
|
||||
* System.out.println(notification);
|
||||
* </pre>
|
||||
*
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <pre>
|
||||
* true|false <---> java.lang.Boolean
|
||||
* number <---> java.lang.Number
|
||||
@ -78,217 +78,217 @@ import java.util.Map;
|
||||
* null <---> null
|
||||
* </pre>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2011-05-19)
|
||||
*/
|
||||
public class JSONRPC2Notification extends JSONRPC2Message {
|
||||
|
||||
|
||||
/**
|
||||
* The requested method name.
|
||||
*/
|
||||
private String method;
|
||||
/**
|
||||
* The requested method name.
|
||||
*/
|
||||
private String method;
|
||||
|
||||
|
||||
/**
|
||||
* The notification parameters.
|
||||
*/
|
||||
private Object params;
|
||||
|
||||
|
||||
/**
|
||||
* The parameters type constant.
|
||||
*/
|
||||
private JSONRPC2ParamsType paramsType;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 notification string. This method is
|
||||
* thread-safe.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 notification string, UTF-8
|
||||
* encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 notification object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Notification parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 notification string. This method is
|
||||
* thread-safe.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 notification string, UTF-8
|
||||
* encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 notification object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Notification parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Notification(jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 notification with no parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
*/
|
||||
public JSONRPC2Notification(final String method) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 notification with JSON array
|
||||
* parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The notification parameters packed as a JSON array
|
||||
* (<a href="#map">maps</a> to java.util.List).
|
||||
*/
|
||||
public JSONRPC2Notification(final String method, final List params) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 notification JSON object parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The notification parameters packed as a JSON object
|
||||
* (<a href="#map">maps</a> to java.util.Map).
|
||||
*/
|
||||
public JSONRPC2Notification(final String method, final Map params) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the name of the requested method.
|
||||
*
|
||||
* @return The method name.
|
||||
*/
|
||||
public String getMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the requested method.
|
||||
*
|
||||
* @param method The method name.
|
||||
*/
|
||||
public void setMethod(final String method) {
|
||||
|
||||
// The method name is mandatory
|
||||
if (method == null)
|
||||
throw new NullPointerException();
|
||||
/**
|
||||
* The notification parameters.
|
||||
*/
|
||||
private Object params;
|
||||
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parameters type ({@link JSONRPC2ParamsType#ARRAY},
|
||||
* {@link JSONRPC2ParamsType#OBJECT} or
|
||||
* {@link JSONRPC2ParamsType#NO_PARAMS}).
|
||||
*
|
||||
* @return The parameters type.
|
||||
*/
|
||||
public JSONRPC2ParamsType getParamsType() {
|
||||
|
||||
return paramsType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the notification parameters.
|
||||
*
|
||||
* @return The parameters as {@code List} if JSON array, {@code Map}
|
||||
* if JSON object, or {@code null} if none.
|
||||
*/
|
||||
public Object getParams() {
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the notification parameters.
|
||||
*
|
||||
* @param params The parameters. For a JSON array type pass a
|
||||
* {@code List}. For a JSON object pass a {@code Map}.
|
||||
* If there are no parameters pass {@code null}.
|
||||
*/
|
||||
public void setParams(final Object params) {
|
||||
|
||||
if (params == null)
|
||||
paramsType = JSONRPC2ParamsType.NO_PARAMS;
|
||||
|
||||
else if (params instanceof List)
|
||||
paramsType = JSONRPC2ParamsType.ARRAY;
|
||||
|
||||
else if (params instanceof Map)
|
||||
paramsType = JSONRPC2ParamsType.OBJECT;
|
||||
|
||||
else
|
||||
throw new IllegalArgumentException("The notification parameters must be of type List, Map or null");
|
||||
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of this JSON-RPC 2.0 notification.
|
||||
*
|
||||
* @return A JSON object representing the notification.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject notf = new JSONObject();
|
||||
|
||||
notf.put("method", method);
|
||||
|
||||
// the params can be omitted if empty
|
||||
if (params != null && paramsType != JSONRPC2ParamsType.NO_PARAMS)
|
||||
notf.put("params", params);
|
||||
|
||||
notf.put("jsonrpc", "2.0");
|
||||
|
||||
return notf;
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters type constant.
|
||||
*/
|
||||
private JSONRPC2ParamsType paramsType;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 notification string. This method is
|
||||
* thread-safe.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 notification string, UTF-8
|
||||
* encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 notification object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Notification parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 notification string. This method is
|
||||
* thread-safe.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 notification string, UTF-8
|
||||
* encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 notification object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Notification parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Notification(jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 notification with no parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
*/
|
||||
public JSONRPC2Notification(final String method) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 notification with JSON array
|
||||
* parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The notification parameters packed as a JSON array
|
||||
* (<a href="#map">maps</a> to java.util.List).
|
||||
*/
|
||||
public JSONRPC2Notification(final String method, final List params) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 notification JSON object parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The notification parameters packed as a JSON object
|
||||
* (<a href="#map">maps</a> to java.util.Map).
|
||||
*/
|
||||
public JSONRPC2Notification(final String method, final Map params) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the name of the requested method.
|
||||
*
|
||||
* @return The method name.
|
||||
*/
|
||||
public String getMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the requested method.
|
||||
*
|
||||
* @param method The method name.
|
||||
*/
|
||||
public void setMethod(final String method) {
|
||||
|
||||
// The method name is mandatory
|
||||
if (method == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parameters type ({@link JSONRPC2ParamsType#ARRAY},
|
||||
* {@link JSONRPC2ParamsType#OBJECT} or
|
||||
* {@link JSONRPC2ParamsType#NO_PARAMS}).
|
||||
*
|
||||
* @return The parameters type.
|
||||
*/
|
||||
public JSONRPC2ParamsType getParamsType() {
|
||||
|
||||
return paramsType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the notification parameters.
|
||||
*
|
||||
* @return The parameters as {@code List} if JSON array, {@code Map}
|
||||
* if JSON object, or {@code null} if none.
|
||||
*/
|
||||
public Object getParams() {
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the notification parameters.
|
||||
*
|
||||
* @param params The parameters. For a JSON array type pass a
|
||||
* {@code List}. For a JSON object pass a {@code Map}.
|
||||
* If there are no parameters pass {@code null}.
|
||||
*/
|
||||
public void setParams(final Object params) {
|
||||
|
||||
if (params == null)
|
||||
paramsType = JSONRPC2ParamsType.NO_PARAMS;
|
||||
|
||||
else if (params instanceof List)
|
||||
paramsType = JSONRPC2ParamsType.ARRAY;
|
||||
|
||||
else if (params instanceof Map)
|
||||
paramsType = JSONRPC2ParamsType.OBJECT;
|
||||
|
||||
else
|
||||
throw new IllegalArgumentException("The notification parameters must be of type List, Map or null");
|
||||
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of this JSON-RPC 2.0 notification.
|
||||
*
|
||||
* @return A JSON object representing the notification.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject notf = new JSONObject();
|
||||
|
||||
notf.put("method", method);
|
||||
|
||||
// the params can be omitted if empty
|
||||
if (params != null && paramsType != JSONRPC2ParamsType.NO_PARAMS)
|
||||
notf.put("params", params);
|
||||
|
||||
notf.put("jsonrpc", "2.0");
|
||||
|
||||
return notf;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package com.thetransactioncompany.jsonrpc2;
|
||||
|
||||
|
||||
/**
|
||||
* Defines the three parameter types constants for JSON-RPC 2.0 requests and
|
||||
* Defines the three parameter types constants for JSON-RPC 2.0 requests and
|
||||
* notifications.
|
||||
*
|
||||
* <ul>
|
||||
@ -13,154 +13,154 @@ package com.thetransactioncompany.jsonrpc2;
|
||||
* e.g. {@code {"param1":"val1", "param2":"val2", ...}}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2010-08-07)
|
||||
*/
|
||||
public final class JSONRPC2ParamsType {
|
||||
|
||||
/** The integer value for this parameters type. */
|
||||
private final int intValue;
|
||||
|
||||
|
||||
/** The name to use for this parameters type. */
|
||||
private final String name;
|
||||
|
||||
|
||||
/**
|
||||
* The integer constant for the "NO_PARAMS" parameters type.
|
||||
*/
|
||||
public static final int NO_PARAMS_CONST = 0;
|
||||
|
||||
|
||||
/**
|
||||
* No parameters.
|
||||
*/
|
||||
public static final JSONRPC2ParamsType NO_PARAMS =
|
||||
new JSONRPC2ParamsType("NO_PARAMS", NO_PARAMS_CONST);
|
||||
|
||||
|
||||
/**
|
||||
* The integer constant for the "ARRAY" parameters type.
|
||||
*/
|
||||
public static final int ARRAY_CONST = 1;
|
||||
|
||||
|
||||
/**
|
||||
* The parameters are packed as a JSON array.
|
||||
*/
|
||||
public static final JSONRPC2ParamsType ARRAY =
|
||||
new JSONRPC2ParamsType("ARRAY", ARRAY_CONST);
|
||||
|
||||
|
||||
/**
|
||||
* The integer constant for the "OBJECT" parameters type.
|
||||
*/
|
||||
public static final int OBJECT_CONST = 2;
|
||||
|
||||
|
||||
/**
|
||||
* The parameters are packed as a JSON object.
|
||||
*/
|
||||
public static final JSONRPC2ParamsType OBJECT =
|
||||
new JSONRPC2ParamsType("OBJECT", OBJECT_CONST);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parameter type with the specified name and integer
|
||||
* value.
|
||||
*
|
||||
* @param name The name to use for this parameter type.
|
||||
* @param intValue The integer value to use for this parameter type.
|
||||
*/
|
||||
private JSONRPC2ParamsType(final String name, final int intValue) {
|
||||
|
||||
this.name = name;
|
||||
this.intValue = intValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the name for this parameters type.
|
||||
*
|
||||
* @return The parameters type name.
|
||||
*/
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the integer constant for this parameters type.
|
||||
*
|
||||
* @return The parameters integer constant.
|
||||
*/
|
||||
public int intValue() {
|
||||
|
||||
return intValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the parameters type with the specified integer constant.
|
||||
*
|
||||
* @param intValue The integer constant for which to retrieve the
|
||||
* corresponding parameters type.
|
||||
*
|
||||
* @return The parameters type or {@code null} if none matches.
|
||||
*/
|
||||
public static JSONRPC2ParamsType valueOf(final int intValue) {
|
||||
|
||||
switch (intValue) {
|
||||
|
||||
case 0:
|
||||
return NO_PARAMS;
|
||||
case 1:
|
||||
return ARRAY;
|
||||
case 2:
|
||||
return OBJECT;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates wheter the provided object is equal to this parameters type.
|
||||
*
|
||||
* @param o The object for which to make the comparison.
|
||||
*
|
||||
* @return {@code true} if the objects are equal, or {@code false} if
|
||||
* not.
|
||||
*/
|
||||
public boolean equals(final Object o) {
|
||||
|
||||
if (o == null)
|
||||
return false;
|
||||
|
||||
else if (o == this)
|
||||
return true;
|
||||
|
||||
else if (o instanceof JSONRPC2ParamsType)
|
||||
return (intValue == ((JSONRPC2ParamsType) o).intValue);
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a string representing this parameters type.
|
||||
*
|
||||
* @return A string representing this parameters type.
|
||||
*/
|
||||
public String toString() {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/** The integer value for this parameters type. */
|
||||
private final int intValue;
|
||||
|
||||
|
||||
/** The name to use for this parameters type. */
|
||||
private final String name;
|
||||
|
||||
|
||||
/**
|
||||
* The integer constant for the "NO_PARAMS" parameters type.
|
||||
*/
|
||||
public static final int NO_PARAMS_CONST = 0;
|
||||
|
||||
|
||||
/**
|
||||
* No parameters.
|
||||
*/
|
||||
public static final JSONRPC2ParamsType NO_PARAMS =
|
||||
new JSONRPC2ParamsType("NO_PARAMS", NO_PARAMS_CONST);
|
||||
|
||||
|
||||
/**
|
||||
* The integer constant for the "ARRAY" parameters type.
|
||||
*/
|
||||
public static final int ARRAY_CONST = 1;
|
||||
|
||||
|
||||
/**
|
||||
* The parameters are packed as a JSON array.
|
||||
*/
|
||||
public static final JSONRPC2ParamsType ARRAY =
|
||||
new JSONRPC2ParamsType("ARRAY", ARRAY_CONST);
|
||||
|
||||
|
||||
/**
|
||||
* The integer constant for the "OBJECT" parameters type.
|
||||
*/
|
||||
public static final int OBJECT_CONST = 2;
|
||||
|
||||
|
||||
/**
|
||||
* The parameters are packed as a JSON object.
|
||||
*/
|
||||
public static final JSONRPC2ParamsType OBJECT =
|
||||
new JSONRPC2ParamsType("OBJECT", OBJECT_CONST);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parameter type with the specified name and integer
|
||||
* value.
|
||||
*
|
||||
* @param name The name to use for this parameter type.
|
||||
* @param intValue The integer value to use for this parameter type.
|
||||
*/
|
||||
private JSONRPC2ParamsType(final String name, final int intValue) {
|
||||
|
||||
this.name = name;
|
||||
this.intValue = intValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the name for this parameters type.
|
||||
*
|
||||
* @return The parameters type name.
|
||||
*/
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the integer constant for this parameters type.
|
||||
*
|
||||
* @return The parameters integer constant.
|
||||
*/
|
||||
public int intValue() {
|
||||
|
||||
return intValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the parameters type with the specified integer constant.
|
||||
*
|
||||
* @param intValue The integer constant for which to retrieve the
|
||||
* corresponding parameters type.
|
||||
*
|
||||
* @return The parameters type or {@code null} if none matches.
|
||||
*/
|
||||
public static JSONRPC2ParamsType valueOf(final int intValue) {
|
||||
|
||||
switch (intValue) {
|
||||
|
||||
case 0:
|
||||
return NO_PARAMS;
|
||||
case 1:
|
||||
return ARRAY;
|
||||
case 2:
|
||||
return OBJECT;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates wheter the provided object is equal to this parameters type.
|
||||
*
|
||||
* @param o The object for which to make the comparison.
|
||||
*
|
||||
* @return {@code true} if the objects are equal, or {@code false} if
|
||||
* not.
|
||||
*/
|
||||
public boolean equals(final Object o) {
|
||||
|
||||
if (o == null)
|
||||
return false;
|
||||
|
||||
else if (o == this)
|
||||
return true;
|
||||
|
||||
else if (o instanceof JSONRPC2ParamsType)
|
||||
return (intValue == ((JSONRPC2ParamsType) o).intValue);
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a string representing this parameters type.
|
||||
*
|
||||
* @return A string representing this parameters type.
|
||||
*/
|
||||
public String toString() {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,111 +1,111 @@
|
||||
package com.thetransactioncompany.jsonrpc2;
|
||||
|
||||
|
||||
/**
|
||||
* Thrown to indicate an exception during the parsing of a JSON-RPC 2.0
|
||||
/**
|
||||
* Thrown to indicate an exception during the parsing of a JSON-RPC 2.0
|
||||
* message string.
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2010-05-18)
|
||||
*/
|
||||
public class JSONRPC2ParseException extends Exception {
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a parse exception caused by a JSON message not conforming
|
||||
* to the JSON-RPC 2.0 protocol.
|
||||
*/
|
||||
public static int PROTOCOL = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a parse exception caused by invalid JSON.
|
||||
*/
|
||||
public static int JSON = 1;
|
||||
|
||||
|
||||
/**
|
||||
* The parse exception cause type. Default is {@link #PROTOCOL}.
|
||||
*/
|
||||
private int causeType = PROTOCOL;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The string that could't be parsed.
|
||||
*/
|
||||
private String unparsableString = null;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parse exception with the specified message. The cause
|
||||
* type is set to {@link #PROTOCOL}.
|
||||
*
|
||||
* @param message The exception message.
|
||||
*/
|
||||
public JSONRPC2ParseException(final String message) {
|
||||
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parse exception with the specified message and the
|
||||
* original string that didn't parse. The cause type is set to
|
||||
* {@link #PROTOCOL}.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param unparsableString The unparsable string.
|
||||
*/
|
||||
public JSONRPC2ParseException(final String message, final String unparsableString) {
|
||||
|
||||
super(message);
|
||||
this.unparsableString = unparsableString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parse exception with the specified message, cause type
|
||||
* and the original string that didn't parse.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param causeType The exception cause type, either
|
||||
* {@link #PROTOCOL} or {@link #JSON}.
|
||||
* @param unparsableString The unparsable string.
|
||||
*/
|
||||
public JSONRPC2ParseException(final String message, final int causeType, final String unparsableString) {
|
||||
|
||||
super(message);
|
||||
|
||||
if (causeType != PROTOCOL && causeType != JSON)
|
||||
throw new IllegalArgumentException("Cause type must be either PROTOCOL or JSON");
|
||||
|
||||
this.causeType = causeType;
|
||||
this.unparsableString = unparsableString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parse exception cause type.
|
||||
*
|
||||
* @return The cause type, either {@link #PROTOCOL} or {@link #JSON}.
|
||||
*/
|
||||
public int getCauseType() {
|
||||
|
||||
return causeType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets original string that caused the parse exception (if specified).
|
||||
*
|
||||
* @return The string that didn't parse, {@code null} if none.
|
||||
*/
|
||||
public String getUnparsableString() {
|
||||
|
||||
return unparsableString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a parse exception caused by a JSON message not conforming
|
||||
* to the JSON-RPC 2.0 protocol.
|
||||
*/
|
||||
public static int PROTOCOL = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a parse exception caused by invalid JSON.
|
||||
*/
|
||||
public static int JSON = 1;
|
||||
|
||||
|
||||
/**
|
||||
* The parse exception cause type. Default is {@link #PROTOCOL}.
|
||||
*/
|
||||
private int causeType = PROTOCOL;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The string that could't be parsed.
|
||||
*/
|
||||
private String unparsableString = null;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parse exception with the specified message. The cause
|
||||
* type is set to {@link #PROTOCOL}.
|
||||
*
|
||||
* @param message The exception message.
|
||||
*/
|
||||
public JSONRPC2ParseException(final String message) {
|
||||
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parse exception with the specified message and the
|
||||
* original string that didn't parse. The cause type is set to
|
||||
* {@link #PROTOCOL}.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param unparsableString The unparsable string.
|
||||
*/
|
||||
public JSONRPC2ParseException(final String message, final String unparsableString) {
|
||||
|
||||
super(message);
|
||||
this.unparsableString = unparsableString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new parse exception with the specified message, cause type
|
||||
* and the original string that didn't parse.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param causeType The exception cause type, either
|
||||
* {@link #PROTOCOL} or {@link #JSON}.
|
||||
* @param unparsableString The unparsable string.
|
||||
*/
|
||||
public JSONRPC2ParseException(final String message, final int causeType, final String unparsableString) {
|
||||
|
||||
super(message);
|
||||
|
||||
if (causeType != PROTOCOL && causeType != JSON)
|
||||
throw new IllegalArgumentException("Cause type must be either PROTOCOL or JSON");
|
||||
|
||||
this.causeType = causeType;
|
||||
this.unparsableString = unparsableString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parse exception cause type.
|
||||
*
|
||||
* @return The cause type, either {@link #PROTOCOL} or {@link #JSON}.
|
||||
*/
|
||||
public int getCauseType() {
|
||||
|
||||
return causeType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets original string that caused the parse exception (if specified).
|
||||
*
|
||||
* @return The string that didn't parse, {@code null} if none.
|
||||
*/
|
||||
public String getUnparsableString() {
|
||||
|
||||
return unparsableString;
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Parses JSON-RPC 2.0 request, notification and response messages.
|
||||
* Parses JSON-RPC 2.0 request, notification and response messages.
|
||||
*
|
||||
* <p>This class is not thread-safe. A parser instance should not be used by
|
||||
* more than one thread unless properly synchronised. Alternatively, you may
|
||||
* <p>This class is not thread-safe. A parser instance should not be used by
|
||||
* more than one thread unless properly synchronised. Alternatively, you may
|
||||
* use the thread-safe {@link JSONRPC2Message#parse} and sister methods.
|
||||
*
|
||||
* <p>Parsing of batched requests / notifications is not supported.
|
||||
@ -27,22 +27,22 @@ import java.util.Map;
|
||||
* "\"params\":{\"recipient\":\"Penny Adams\",\"amount\":175.05}," +
|
||||
* "\"id\":\"0001\","+
|
||||
* "\"jsonrpc\":\"2.0\"}";
|
||||
*
|
||||
*
|
||||
* JSONRPC2Request req = null;
|
||||
*
|
||||
* JSONRPC2Parser parser = new JSONRPC2Parser();
|
||||
*
|
||||
*
|
||||
* try {
|
||||
* req = parser.parseJSONRPC2Request(jsonString);
|
||||
*
|
||||
*
|
||||
* } catch (JSONRPC2ParseException e) {
|
||||
* // handle exception
|
||||
* }
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <pre>
|
||||
* true|false <---> java.lang.Boolean
|
||||
* number <---> java.lang.Number
|
||||
@ -52,450 +52,450 @@ import java.util.Map;
|
||||
* null <---> null
|
||||
* </pre>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2011-05-19)
|
||||
*/
|
||||
public class JSONRPC2Parser {
|
||||
|
||||
|
||||
/**
|
||||
* Reusable JSON parser.
|
||||
*/
|
||||
private JSONParser parser;
|
||||
|
||||
|
||||
/**
|
||||
* If {@code true} the order of the parsed JSON object members must be
|
||||
* preserved.
|
||||
*/
|
||||
private boolean preserveOrder;
|
||||
|
||||
|
||||
/**
|
||||
* If {@code true} the {@code "jsonrpc":"2.0"} version field in the
|
||||
* JSON-RPC 2.0 message must not be checked.
|
||||
*/
|
||||
private boolean noStrict;
|
||||
|
||||
|
||||
/**
|
||||
* Special container factory for constructing JSON objects in a way
|
||||
* that preserves their original member order.
|
||||
*/
|
||||
private static final ContainerFactory linkedContainerFactory = new ContainerFactory() {
|
||||
|
||||
// Yes, there is a typo here!
|
||||
public List creatArrayContainer() {
|
||||
return new LinkedList();
|
||||
}
|
||||
|
||||
public Map createObjectContainer() {
|
||||
return new LinkedHashMap();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 message parser.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the {@link
|
||||
* #JSONRPC2Parser(boolean,boolean) alternative constructor}.
|
||||
*/
|
||||
public JSONRPC2Parser() {
|
||||
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 message parser.
|
||||
*
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters and results will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*/
|
||||
public JSONRPC2Parser(final boolean preserveOrder, final boolean noStrict) {
|
||||
|
||||
parser = new JSONParser();
|
||||
this.preserveOrder = preserveOrder;
|
||||
this.noStrict = noStrict;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON object string. Provides the initial parsing of JSON-RPC
|
||||
* 2.0 messages. The member order of JSON objects will be preserved if
|
||||
* {@link #preserveOrder} is set to {@code true}.
|
||||
*
|
||||
* @param jsonString The JSON string to parse.
|
||||
*
|
||||
* @return The parsed JSON object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if parsing
|
||||
* failed.
|
||||
*/
|
||||
private Map parseJSONObject(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
if (jsonString == null)
|
||||
throw new JSONRPC2ParseException("Null argument", JSONRPC2ParseException.JSON, null);
|
||||
|
||||
if (jsonString.trim().isEmpty())
|
||||
throw new JSONRPC2ParseException("Invalid JSON: Empty string", JSONRPC2ParseException.JSON, jsonString);
|
||||
|
||||
Object json;
|
||||
|
||||
// Parse the JSON string
|
||||
try {
|
||||
if (preserveOrder)
|
||||
json = parser.parse(jsonString, linkedContainerFactory);
|
||||
else
|
||||
json = parser.parse(jsonString);
|
||||
|
||||
} catch (ParseException e) {
|
||||
// JSON.simple provides no error message
|
||||
throw new JSONRPC2ParseException("Invalid JSON", JSONRPC2ParseException.JSON, jsonString);
|
||||
}
|
||||
|
||||
if (json instanceof List)
|
||||
throw new JSONRPC2ParseException("JSON-RPC 2.0 batch requests/notifications not supported", jsonString);
|
||||
|
||||
if (! (json instanceof Map))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 message: Message must be a JSON object", jsonString);
|
||||
|
||||
return (Map)json;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensures the specified parameter is a {@code String} object set to
|
||||
* "2.0". This method is intended to check the "jsonrpc" field during
|
||||
* parsing of JSON-RPC messages.
|
||||
*
|
||||
* @param version The version parameter.
|
||||
* @param jsonString The original JSON string.
|
||||
*
|
||||
* @throws JSONRPC2Exception If the parameter is not a string matching
|
||||
* "2.0".
|
||||
*/
|
||||
private static void ensureVersion2(final Object version, final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
if (version == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0: Version string missing", jsonString);
|
||||
|
||||
else if (! (version instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0: Version not a JSON string", jsonString);
|
||||
|
||||
else if (! version.equals("2.0"))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0: Version must be \"2.0\"", jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides common parsing of JSON-RPC 2.0 requests, notifications
|
||||
* and responses. Use this method if you don't know which type of
|
||||
* JSON-RPC message the input string represents.
|
||||
*
|
||||
* <p>If you are certain about the message type use the dedicated
|
||||
* {@link #parseJSONRPC2Request}, {@link #parseJSONRPC2Notification}
|
||||
* and {@link #parseJSONRPC2Response} methods. They are more efficient
|
||||
* and would provide you with more detailed parse error reporting.
|
||||
*
|
||||
* @param jsonString A JSON string representing a JSON-RPC 2.0 request,
|
||||
* notification or response, UTF-8 encoded.
|
||||
*
|
||||
* @return An instance of {@link JSONRPC2Request},
|
||||
* {@link JSONRPC2Notification} or {@link JSONRPC2Response}.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Message parseJSONRPC2Message(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Try each of the parsers until one succeeds (or all fail)
|
||||
try {
|
||||
return parseJSONRPC2Request(jsonString);
|
||||
/**
|
||||
* Reusable JSON parser.
|
||||
*/
|
||||
private JSONParser parser;
|
||||
|
||||
} catch (JSONRPC2ParseException e) {
|
||||
|
||||
// throw on JSON error, ignore on protocol error
|
||||
if (e.getCauseType() == JSONRPC2ParseException.JSON)
|
||||
throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
return parseJSONRPC2Notification(jsonString);
|
||||
|
||||
} catch (JSONRPC2ParseException e) {
|
||||
|
||||
// throw on JSON error, ignore on protocol error
|
||||
if (e.getCauseType() == JSONRPC2ParseException.JSON)
|
||||
throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
return parseJSONRPC2Response(jsonString);
|
||||
|
||||
} catch (JSONRPC2ParseException e) {
|
||||
|
||||
// throw on JSON error, ignore on protocol error
|
||||
if (e.getCauseType() == JSONRPC2ParseException.JSON)
|
||||
throw e;
|
||||
}
|
||||
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 message", JSONRPC2ParseException.PROTOCOL, jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 request string.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 request string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 request object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Request parseJSONRPC2Request(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Initial JSON object parsing
|
||||
Map json = parseJSONObject(jsonString);
|
||||
|
||||
|
||||
// Check for JSON-RPC version "2.0"
|
||||
if (! noStrict) {
|
||||
Object version = json.get("jsonrpc");
|
||||
ensureVersion2(version, jsonString);
|
||||
}
|
||||
|
||||
|
||||
// Extract method name
|
||||
Object method = json.get("method");
|
||||
|
||||
if (method == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method name missing", jsonString);
|
||||
else if (! (method instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method name not a JSON string", jsonString);
|
||||
else if (((String)method).length() == 0)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method name is an empty string", jsonString);
|
||||
|
||||
|
||||
// Extract ID
|
||||
if (! json.containsKey("id"))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Missing identifier", jsonString);
|
||||
|
||||
Object id = json.get("id");
|
||||
|
||||
if ( id != null &&
|
||||
!(id instanceof Number ) &&
|
||||
!(id instanceof Boolean) &&
|
||||
!(id instanceof String ) )
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Identifier not a JSON scalar", jsonString);
|
||||
|
||||
|
||||
// Extract params
|
||||
Object params = json.get("params");
|
||||
|
||||
if (params == null)
|
||||
return new JSONRPC2Request((String)method, id);
|
||||
else if (params instanceof List)
|
||||
return new JSONRPC2Request((String)method, (List)params, id);
|
||||
else if (params instanceof Map)
|
||||
return new JSONRPC2Request((String)method, (Map)params, id);
|
||||
else
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method parameters have unexpected JSON type", jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 notification string.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 notification string, UTF-8
|
||||
* encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 notification object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Notification parseJSONRPC2Notification(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Initial JSON object parsing
|
||||
Map json = parseJSONObject(jsonString);
|
||||
|
||||
|
||||
// Check for JSON-RPC version "2.0"
|
||||
if (! noStrict) {
|
||||
Object version = json.get("jsonrpc");
|
||||
ensureVersion2(version, jsonString);
|
||||
}
|
||||
|
||||
|
||||
// Extract method name
|
||||
Object method = json.get("method");
|
||||
|
||||
if (method == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method name missing", jsonString);
|
||||
else if (! (method instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method name not a JSON string", jsonString);
|
||||
else if (((String)method).length() == 0)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method name is an empty string", jsonString);
|
||||
|
||||
|
||||
// Extract params
|
||||
Object params = json.get("params");
|
||||
|
||||
if (params == null)
|
||||
return new JSONRPC2Notification((String)method);
|
||||
else if (params instanceof List)
|
||||
return new JSONRPC2Notification((String)method, (List)params);
|
||||
else if (params instanceof Map)
|
||||
return new JSONRPC2Notification((String)method, (Map)params);
|
||||
else
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method parameters have unexpected JSON type", jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 response string.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 response string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 response object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Response parseJSONRPC2Response(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Initial JSON object parsing
|
||||
Map json = parseJSONObject(jsonString);
|
||||
|
||||
// Check for JSON-RPC version "2.0"
|
||||
if (! noStrict) {
|
||||
Object version = json.get("jsonrpc");
|
||||
ensureVersion2(version, jsonString);
|
||||
}
|
||||
|
||||
// Extract request ID
|
||||
Object id = json.get("id");
|
||||
|
||||
if ( id != null &&
|
||||
! (id instanceof Boolean) &&
|
||||
! (id instanceof Number ) &&
|
||||
! (id instanceof String ) )
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Identifier not a JSON scalar", jsonString);
|
||||
|
||||
|
||||
// Extract result/error and create response object
|
||||
// Note: result and error are mutually exclusive
|
||||
if (json.containsKey("result") && ! json.containsKey("error")) {
|
||||
|
||||
// Success
|
||||
Object res = json.get("result");
|
||||
|
||||
return new JSONRPC2Response(res, id);
|
||||
|
||||
}
|
||||
else if (! json.containsKey("result") && json.containsKey("error")) {
|
||||
|
||||
// Error
|
||||
Map errorJSON = (Map)json.get("error");
|
||||
|
||||
if (errorJSON == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Missing error object", jsonString);
|
||||
|
||||
int errorCode;
|
||||
try {
|
||||
errorCode = ((Long)errorJSON.get("code")).intValue();
|
||||
} catch (Exception e) {
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Error code missing or not an integer", jsonString);
|
||||
}
|
||||
|
||||
String errorMessage = null;
|
||||
try {
|
||||
errorMessage = (String)errorJSON.get("message");
|
||||
} catch (Exception e) {
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Error message missing or not a string", jsonString);
|
||||
}
|
||||
|
||||
Object errorData = errorJSON.get("data");
|
||||
|
||||
return new JSONRPC2Response(new JSONRPC2Error(errorCode, errorMessage, errorData), id);
|
||||
|
||||
}
|
||||
else if (json.containsKey("result") && json.containsKey("error")) {
|
||||
// Invalid response
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: You cannot have result and error at the same time", jsonString);
|
||||
}
|
||||
else if (! json.containsKey("result") && ! json.containsKey("error")){
|
||||
// Invalid response
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Neither result nor error specified", jsonString);
|
||||
}
|
||||
else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Controls the preservation of JSON object member order in parsed
|
||||
* JSON-RPC 2.0 messages.
|
||||
*
|
||||
* @param preserveOrder {@code true} to preserve JSON object member,
|
||||
* else {@code false}.
|
||||
*/
|
||||
public void preserveOrder(final boolean preserveOrder) {
|
||||
|
||||
this.preserveOrder = preserveOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the order of JSON object members in parsed
|
||||
* JSON-RPC 2.0 messages is preserved, else {@code false}.
|
||||
*
|
||||
* @return {@code true} if order is preserved, else {@code false}.
|
||||
*/
|
||||
public boolean preservesOrder() {
|
||||
|
||||
return preserveOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the strictness of JSON-RPC 2.0 message parsing.
|
||||
*
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"} version
|
||||
* field in parsed JSON-RPC 2.0 messages must be
|
||||
* ignored.
|
||||
*/
|
||||
public void noStrict(final boolean noStrict) {
|
||||
|
||||
this.noStrict = noStrict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the strictness of JSON-RPC 2.0 message parsing.
|
||||
*
|
||||
* @return {@code true} if the {@code "jsonrpc":"2.0"} version field in
|
||||
* parsed JSON-RPC 2.0 messages is ignored, else {@code false}.
|
||||
*/
|
||||
public boolean isNoStrict() {
|
||||
|
||||
return noStrict;
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@code true} the order of the parsed JSON object members must be
|
||||
* preserved.
|
||||
*/
|
||||
private boolean preserveOrder;
|
||||
|
||||
|
||||
/**
|
||||
* If {@code true} the {@code "jsonrpc":"2.0"} version field in the
|
||||
* JSON-RPC 2.0 message must not be checked.
|
||||
*/
|
||||
private boolean noStrict;
|
||||
|
||||
|
||||
/**
|
||||
* Special container factory for constructing JSON objects in a way
|
||||
* that preserves their original member order.
|
||||
*/
|
||||
private static final ContainerFactory linkedContainerFactory = new ContainerFactory() {
|
||||
|
||||
// Yes, there is a typo here!
|
||||
public List creatArrayContainer() {
|
||||
return new LinkedList();
|
||||
}
|
||||
|
||||
public Map createObjectContainer() {
|
||||
return new LinkedHashMap();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 message parser.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the {@link
|
||||
* #JSONRPC2Parser(boolean,boolean) alternative constructor}.
|
||||
*/
|
||||
public JSONRPC2Parser() {
|
||||
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 message parser.
|
||||
*
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters and results will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*/
|
||||
public JSONRPC2Parser(final boolean preserveOrder, final boolean noStrict) {
|
||||
|
||||
parser = new JSONParser();
|
||||
this.preserveOrder = preserveOrder;
|
||||
this.noStrict = noStrict;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON object string. Provides the initial parsing of JSON-RPC
|
||||
* 2.0 messages. The member order of JSON objects will be preserved if
|
||||
* {@link #preserveOrder} is set to {@code true}.
|
||||
*
|
||||
* @param jsonString The JSON string to parse.
|
||||
*
|
||||
* @return The parsed JSON object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if parsing
|
||||
* failed.
|
||||
*/
|
||||
private Map parseJSONObject(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
if (jsonString == null)
|
||||
throw new JSONRPC2ParseException("Null argument", JSONRPC2ParseException.JSON, null);
|
||||
|
||||
if (jsonString.trim().isEmpty())
|
||||
throw new JSONRPC2ParseException("Invalid JSON: Empty string", JSONRPC2ParseException.JSON, jsonString);
|
||||
|
||||
Object json;
|
||||
|
||||
// Parse the JSON string
|
||||
try {
|
||||
if (preserveOrder)
|
||||
json = parser.parse(jsonString, linkedContainerFactory);
|
||||
else
|
||||
json = parser.parse(jsonString);
|
||||
|
||||
} catch (ParseException e) {
|
||||
// JSON.simple provides no error message
|
||||
throw new JSONRPC2ParseException("Invalid JSON", JSONRPC2ParseException.JSON, jsonString);
|
||||
}
|
||||
|
||||
if (json instanceof List)
|
||||
throw new JSONRPC2ParseException("JSON-RPC 2.0 batch requests/notifications not supported", jsonString);
|
||||
|
||||
if (!(json instanceof Map))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 message: Message must be a JSON object", jsonString);
|
||||
|
||||
return (Map)json;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensures the specified parameter is a {@code String} object set to
|
||||
* "2.0". This method is intended to check the "jsonrpc" field during
|
||||
* parsing of JSON-RPC messages.
|
||||
*
|
||||
* @param version The version parameter.
|
||||
* @param jsonString The original JSON string.
|
||||
*
|
||||
* @throws JSONRPC2Exception If the parameter is not a string matching
|
||||
* "2.0".
|
||||
*/
|
||||
private static void ensureVersion2(final Object version, final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
if (version == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0: Version string missing", jsonString);
|
||||
|
||||
else if (!(version instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0: Version not a JSON string", jsonString);
|
||||
|
||||
else if (! version.equals("2.0"))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0: Version must be \"2.0\"", jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides common parsing of JSON-RPC 2.0 requests, notifications
|
||||
* and responses. Use this method if you don't know which type of
|
||||
* JSON-RPC message the input string represents.
|
||||
*
|
||||
* <p>If you are certain about the message type use the dedicated
|
||||
* {@link #parseJSONRPC2Request}, {@link #parseJSONRPC2Notification}
|
||||
* and {@link #parseJSONRPC2Response} methods. They are more efficient
|
||||
* and would provide you with more detailed parse error reporting.
|
||||
*
|
||||
* @param jsonString A JSON string representing a JSON-RPC 2.0 request,
|
||||
* notification or response, UTF-8 encoded.
|
||||
*
|
||||
* @return An instance of {@link JSONRPC2Request},
|
||||
* {@link JSONRPC2Notification} or {@link JSONRPC2Response}.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Message parseJSONRPC2Message(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Try each of the parsers until one succeeds (or all fail)
|
||||
try {
|
||||
return parseJSONRPC2Request(jsonString);
|
||||
|
||||
} catch (JSONRPC2ParseException e) {
|
||||
|
||||
// throw on JSON error, ignore on protocol error
|
||||
if (e.getCauseType() == JSONRPC2ParseException.JSON)
|
||||
throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
return parseJSONRPC2Notification(jsonString);
|
||||
|
||||
} catch (JSONRPC2ParseException e) {
|
||||
|
||||
// throw on JSON error, ignore on protocol error
|
||||
if (e.getCauseType() == JSONRPC2ParseException.JSON)
|
||||
throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
return parseJSONRPC2Response(jsonString);
|
||||
|
||||
} catch (JSONRPC2ParseException e) {
|
||||
|
||||
// throw on JSON error, ignore on protocol error
|
||||
if (e.getCauseType() == JSONRPC2ParseException.JSON)
|
||||
throw e;
|
||||
}
|
||||
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 message", JSONRPC2ParseException.PROTOCOL, jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 request string.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 request string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 request object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Request parseJSONRPC2Request(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Initial JSON object parsing
|
||||
Map json = parseJSONObject(jsonString);
|
||||
|
||||
|
||||
// Check for JSON-RPC version "2.0"
|
||||
if (! noStrict) {
|
||||
Object version = json.get("jsonrpc");
|
||||
ensureVersion2(version, jsonString);
|
||||
}
|
||||
|
||||
|
||||
// Extract method name
|
||||
Object method = json.get("method");
|
||||
|
||||
if (method == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method name missing", jsonString);
|
||||
else if (!(method instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method name not a JSON string", jsonString);
|
||||
else if (((String)method).length() == 0)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method name is an empty string", jsonString);
|
||||
|
||||
|
||||
// Extract ID
|
||||
if (! json.containsKey("id"))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Missing identifier", jsonString);
|
||||
|
||||
Object id = json.get("id");
|
||||
|
||||
if (id != null &&
|
||||
!(id instanceof Number) &&
|
||||
!(id instanceof Boolean) &&
|
||||
!(id instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Identifier not a JSON scalar", jsonString);
|
||||
|
||||
|
||||
// Extract params
|
||||
Object params = json.get("params");
|
||||
|
||||
if (params == null)
|
||||
return new JSONRPC2Request((String)method, id);
|
||||
else if (params instanceof List)
|
||||
return new JSONRPC2Request((String)method, (List)params, id);
|
||||
else if (params instanceof Map)
|
||||
return new JSONRPC2Request((String)method, (Map)params, id);
|
||||
else
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 request: Method parameters have unexpected JSON type", jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 notification string.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 notification string, UTF-8
|
||||
* encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 notification object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Notification parseJSONRPC2Notification(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Initial JSON object parsing
|
||||
Map json = parseJSONObject(jsonString);
|
||||
|
||||
|
||||
// Check for JSON-RPC version "2.0"
|
||||
if (! noStrict) {
|
||||
Object version = json.get("jsonrpc");
|
||||
ensureVersion2(version, jsonString);
|
||||
}
|
||||
|
||||
|
||||
// Extract method name
|
||||
Object method = json.get("method");
|
||||
|
||||
if (method == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method name missing", jsonString);
|
||||
else if (!(method instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method name not a JSON string", jsonString);
|
||||
else if (((String)method).length() == 0)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method name is an empty string", jsonString);
|
||||
|
||||
|
||||
// Extract params
|
||||
Object params = json.get("params");
|
||||
|
||||
if (params == null)
|
||||
return new JSONRPC2Notification((String)method);
|
||||
else if (params instanceof List)
|
||||
return new JSONRPC2Notification((String)method, (List)params);
|
||||
else if (params instanceof Map)
|
||||
return new JSONRPC2Notification((String)method, (Map)params);
|
||||
else
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 notification: Method parameters have unexpected JSON type", jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 response string.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 response string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 response object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public JSONRPC2Response parseJSONRPC2Response(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
// Initial JSON object parsing
|
||||
Map json = parseJSONObject(jsonString);
|
||||
|
||||
// Check for JSON-RPC version "2.0"
|
||||
if (! noStrict) {
|
||||
Object version = json.get("jsonrpc");
|
||||
ensureVersion2(version, jsonString);
|
||||
}
|
||||
|
||||
// Extract request ID
|
||||
Object id = json.get("id");
|
||||
|
||||
if (id != null &&
|
||||
!(id instanceof Boolean) &&
|
||||
!(id instanceof Number) &&
|
||||
!(id instanceof String))
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Identifier not a JSON scalar", jsonString);
|
||||
|
||||
|
||||
// Extract result/error and create response object
|
||||
// Note: result and error are mutually exclusive
|
||||
if (json.containsKey("result") && ! json.containsKey("error")) {
|
||||
|
||||
// Success
|
||||
Object res = json.get("result");
|
||||
|
||||
return new JSONRPC2Response(res, id);
|
||||
|
||||
}
|
||||
else if (! json.containsKey("result") && json.containsKey("error")) {
|
||||
|
||||
// Error
|
||||
Map errorJSON = (Map)json.get("error");
|
||||
|
||||
if (errorJSON == null)
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Missing error object", jsonString);
|
||||
|
||||
int errorCode;
|
||||
try {
|
||||
errorCode = ((Long)errorJSON.get("code")).intValue();
|
||||
} catch (Exception e) {
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Error code missing or not an integer", jsonString);
|
||||
}
|
||||
|
||||
String errorMessage = null;
|
||||
try {
|
||||
errorMessage = (String)errorJSON.get("message");
|
||||
} catch (Exception e) {
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Error message missing or not a string", jsonString);
|
||||
}
|
||||
|
||||
Object errorData = errorJSON.get("data");
|
||||
|
||||
return new JSONRPC2Response(new JSONRPC2Error(errorCode, errorMessage, errorData), id);
|
||||
|
||||
}
|
||||
else if (json.containsKey("result") && json.containsKey("error")) {
|
||||
// Invalid response
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: You cannot have result and error at the same time", jsonString);
|
||||
}
|
||||
else if (! json.containsKey("result") && ! json.containsKey("error")) {
|
||||
// Invalid response
|
||||
throw new JSONRPC2ParseException("Invalid JSON-RPC 2.0 response: Neither result nor error specified", jsonString);
|
||||
}
|
||||
else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Controls the preservation of JSON object member order in parsed
|
||||
* JSON-RPC 2.0 messages.
|
||||
*
|
||||
* @param preserveOrder {@code true} to preserve JSON object member,
|
||||
* else {@code false}.
|
||||
*/
|
||||
public void preserveOrder(final boolean preserveOrder) {
|
||||
|
||||
this.preserveOrder = preserveOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the order of JSON object members in parsed
|
||||
* JSON-RPC 2.0 messages is preserved, else {@code false}.
|
||||
*
|
||||
* @return {@code true} if order is preserved, else {@code false}.
|
||||
*/
|
||||
public boolean preservesOrder() {
|
||||
|
||||
return preserveOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the strictness of JSON-RPC 2.0 message parsing.
|
||||
*
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"} version
|
||||
* field in parsed JSON-RPC 2.0 messages must be
|
||||
* ignored.
|
||||
*/
|
||||
public void noStrict(final boolean noStrict) {
|
||||
|
||||
this.noStrict = noStrict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the strictness of JSON-RPC 2.0 message parsing.
|
||||
*
|
||||
* @return {@code true} if the {@code "jsonrpc":"2.0"} version field in
|
||||
* parsed JSON-RPC 2.0 messages is ignored, else {@code false}.
|
||||
*/
|
||||
public boolean isNoStrict() {
|
||||
|
||||
return noStrict;
|
||||
}
|
||||
}
|
||||
|
@ -6,24 +6,24 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 request.
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 request.
|
||||
*
|
||||
* <p>A request carries four pieces of data:
|
||||
* <ul>
|
||||
* <li>{@code method} The name of the remote method to call.
|
||||
* <li>{@code params} The required method parameters (if any), which can
|
||||
* <li>{@code params} The required method parameters (if any), which can
|
||||
* be packed into a JSON array or object.
|
||||
* <li>{@code id} An identifier which is echoed back to the client with
|
||||
* <li>{@code id} An identifier which is echoed back to the client with
|
||||
* the response.
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol version
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol version
|
||||
* set to "2.0".
|
||||
* </ul>
|
||||
*
|
||||
* <p>Here is a sample JSON-RPC 2.0 request string:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* {
|
||||
* "method" : "makePayment",
|
||||
* "params" : { "recipient" : "Penny Adams", "amount":175.05 },
|
||||
* "id" : "0001",
|
||||
@ -33,8 +33,8 @@ import java.util.Map;
|
||||
*
|
||||
* <p>This class provides two methods to obtain a request object:
|
||||
* <ul>
|
||||
* <li>Pass a JSON-RPC 2.0 request string to the static
|
||||
* {@link #parse} method, or
|
||||
* <li>Pass a JSON-RPC 2.0 request string to the static
|
||||
* {@link #parse} method, or
|
||||
* <li>Invoke one of the constructors with the appropriate arguments.
|
||||
* </ul>
|
||||
*
|
||||
@ -45,9 +45,9 @@ import java.util.Map;
|
||||
* "\"params\":{\"recipient\":\"Penny Adams\",\"amount\":175.05}," +
|
||||
* "\"id\":\"0001\","+
|
||||
* "\"jsonrpc\":\"2.0\"}";
|
||||
*
|
||||
*
|
||||
* JSONRPC2Request req = null;
|
||||
*
|
||||
*
|
||||
* try {
|
||||
* req = JSONRPC2Request.parse(jsonString);
|
||||
*
|
||||
@ -57,7 +57,7 @@ import java.util.Map;
|
||||
* </pre>
|
||||
*
|
||||
* <p>Example 2: Recreating the above request:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* String method = "makePayment";
|
||||
* Map params = new HashMap();
|
||||
@ -70,8 +70,8 @@ import java.util.Map;
|
||||
* System.out.println(req);
|
||||
* </pre>
|
||||
*
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <pre>
|
||||
* true|false <---> java.lang.Boolean
|
||||
* number <---> java.lang.Number
|
||||
@ -81,266 +81,266 @@ import java.util.Map;
|
||||
* null <---> null
|
||||
* </pre>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2011-05-19)
|
||||
*/
|
||||
public class JSONRPC2Request extends JSONRPC2Message {
|
||||
|
||||
|
||||
/**
|
||||
* The requested method name.
|
||||
*/
|
||||
private String method;
|
||||
|
||||
|
||||
/**
|
||||
* The request parameters.
|
||||
*/
|
||||
private Object params;
|
||||
|
||||
|
||||
/**
|
||||
* The parameters type constant.
|
||||
*/
|
||||
private JSONRPC2ParamsType paramsType;
|
||||
|
||||
|
||||
/**
|
||||
* The request identifier.
|
||||
*/
|
||||
private Object id;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 request string. This method is thread-safe.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 request string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 request object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Request parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 request string. This method is thread-safe.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 request string, UTF-8 encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 request object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Request parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Request(jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 request with no parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public JSONRPC2Request(final String method, final Object id) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(null);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 request with JSON array parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The request parameters packed as a JSON array
|
||||
* (<a href="#map">maps</a> to java.util.List).
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public JSONRPC2Request(final String method, final List params, final Object id) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 request with JSON object parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The request parameters packed as a JSON object
|
||||
* (<a href="#map">maps</a> to java.util.Map).
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public JSONRPC2Request(final String method, final Map params, final Object id) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the name of the requested method.
|
||||
*
|
||||
* @return The method name.
|
||||
*/
|
||||
public String getMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the requested method.
|
||||
*
|
||||
* @param method The method name.
|
||||
*/
|
||||
public void setMethod(final String method) {
|
||||
|
||||
// The method name is mandatory
|
||||
if (method == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parameters type ({@link JSONRPC2ParamsType#ARRAY},
|
||||
* {@link JSONRPC2ParamsType#OBJECT} or
|
||||
* {@link JSONRPC2ParamsType#NO_PARAMS}).
|
||||
*
|
||||
* @return The parameters type.
|
||||
*/
|
||||
public JSONRPC2ParamsType getParamsType() {
|
||||
|
||||
return paramsType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request parameters.
|
||||
*
|
||||
* @return The parameters as {@code List} if JSON array, {@code Map}
|
||||
* if JSON object, or {@code null} if none.
|
||||
*/
|
||||
public Object getParams() {
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the request parameters.
|
||||
*
|
||||
* @param params The parameters. For a JSON array type pass a
|
||||
* {@code List}. For a JSON object pass a {@code Map}.
|
||||
* If there are no parameters pass {@code null}.
|
||||
*/
|
||||
public void setParams(final Object params) {
|
||||
|
||||
if (params == null)
|
||||
paramsType = JSONRPC2ParamsType.NO_PARAMS;
|
||||
|
||||
else if (params instanceof List)
|
||||
paramsType = JSONRPC2ParamsType.ARRAY;
|
||||
|
||||
else if (params instanceof Map)
|
||||
paramsType = JSONRPC2ParamsType.OBJECT;
|
||||
|
||||
else
|
||||
throw new IllegalArgumentException("The request parameters must be of type List, Map or null");
|
||||
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request identifier.
|
||||
*
|
||||
* @return The request identifier ({@code Number}, {@code Boolean},
|
||||
* {@code String}) or {@code null}.
|
||||
*/
|
||||
public Object getID() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the request identifier (ID).
|
||||
*
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public void setID(final Object id) {
|
||||
|
||||
if ( id != null &&
|
||||
! (id instanceof Boolean) &&
|
||||
! (id instanceof Number ) &&
|
||||
! (id instanceof String ) )
|
||||
throw new IllegalArgumentException("The request identifier must map to a JSON scalar");
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of this JSON-RPC 2.0 request.
|
||||
*
|
||||
* @return A JSON object representing the request.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject req = new JSONObject();
|
||||
|
||||
req.put("method", method);
|
||||
|
||||
// the params can be omitted if empty
|
||||
if (params != null && paramsType != JSONRPC2ParamsType.NO_PARAMS)
|
||||
req.put("params", params);
|
||||
|
||||
req.put("id", id);
|
||||
|
||||
req.put("jsonrpc", "2.0");
|
||||
|
||||
return req;
|
||||
}
|
||||
/**
|
||||
* The requested method name.
|
||||
*/
|
||||
private String method;
|
||||
|
||||
|
||||
/**
|
||||
* The request parameters.
|
||||
*/
|
||||
private Object params;
|
||||
|
||||
|
||||
/**
|
||||
* The parameters type constant.
|
||||
*/
|
||||
private JSONRPC2ParamsType paramsType;
|
||||
|
||||
|
||||
/**
|
||||
* The request identifier.
|
||||
*/
|
||||
private Object id;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 request string. This method is thread-safe.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 request string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 request object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Request parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 request string. This method is thread-safe.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 request string, UTF-8 encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in parameters will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 request object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Request parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Request(jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 request with no parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public JSONRPC2Request(final String method, final Object id) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(null);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 request with JSON array parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The request parameters packed as a JSON array
|
||||
* (<a href="#map">maps</a> to java.util.List).
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public JSONRPC2Request(final String method, final List params, final Object id) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new JSON-RPC 2.0 request with JSON object parameters.
|
||||
*
|
||||
* @param method The name of the requested method.
|
||||
* @param params The request parameters packed as a JSON object
|
||||
* (<a href="#map">maps</a> to java.util.Map).
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public JSONRPC2Request(final String method, final Map params, final Object id) {
|
||||
|
||||
setMethod(method);
|
||||
setParams(params);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the name of the requested method.
|
||||
*
|
||||
* @return The method name.
|
||||
*/
|
||||
public String getMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the requested method.
|
||||
*
|
||||
* @param method The method name.
|
||||
*/
|
||||
public void setMethod(final String method) {
|
||||
|
||||
// The method name is mandatory
|
||||
if (method == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parameters type ({@link JSONRPC2ParamsType#ARRAY},
|
||||
* {@link JSONRPC2ParamsType#OBJECT} or
|
||||
* {@link JSONRPC2ParamsType#NO_PARAMS}).
|
||||
*
|
||||
* @return The parameters type.
|
||||
*/
|
||||
public JSONRPC2ParamsType getParamsType() {
|
||||
|
||||
return paramsType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request parameters.
|
||||
*
|
||||
* @return The parameters as {@code List} if JSON array, {@code Map}
|
||||
* if JSON object, or {@code null} if none.
|
||||
*/
|
||||
public Object getParams() {
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the request parameters.
|
||||
*
|
||||
* @param params The parameters. For a JSON array type pass a
|
||||
* {@code List}. For a JSON object pass a {@code Map}.
|
||||
* If there are no parameters pass {@code null}.
|
||||
*/
|
||||
public void setParams(final Object params) {
|
||||
|
||||
if (params == null)
|
||||
paramsType = JSONRPC2ParamsType.NO_PARAMS;
|
||||
|
||||
else if (params instanceof List)
|
||||
paramsType = JSONRPC2ParamsType.ARRAY;
|
||||
|
||||
else if (params instanceof Map)
|
||||
paramsType = JSONRPC2ParamsType.OBJECT;
|
||||
|
||||
else
|
||||
throw new IllegalArgumentException("The request parameters must be of type List, Map or null");
|
||||
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request identifier.
|
||||
*
|
||||
* @return The request identifier ({@code Number}, {@code Boolean},
|
||||
* {@code String}) or {@code null}.
|
||||
*/
|
||||
public Object getID() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the request identifier (ID).
|
||||
*
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* The value must <a href="#map">map</a> to a JSON
|
||||
* scalar ({@code null} and fractions, however, should
|
||||
* be avoided).
|
||||
*/
|
||||
public void setID(final Object id) {
|
||||
|
||||
if (id != null &&
|
||||
!(id instanceof Boolean) &&
|
||||
!(id instanceof Number) &&
|
||||
!(id instanceof String))
|
||||
throw new IllegalArgumentException("The request identifier must map to a JSON scalar");
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of this JSON-RPC 2.0 request.
|
||||
*
|
||||
* @return A JSON object representing the request.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject req = new JSONObject();
|
||||
|
||||
req.put("method", method);
|
||||
|
||||
// the params can be omitted if empty
|
||||
if (params != null && paramsType != JSONRPC2ParamsType.NO_PARAMS)
|
||||
req.put("params", params);
|
||||
|
||||
req.put("id", id);
|
||||
|
||||
req.put("jsonrpc", "2.0");
|
||||
|
||||
return req;
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 response.
|
||||
*
|
||||
* <p>A response is returned to the caller after a JSON-RPC 2.0 request has
|
||||
* <p>A response is returned to the caller after a JSON-RPC 2.0 request has
|
||||
* been processed (notifications, however, don't produce a response). The
|
||||
* response can take two different forms depending on the outcome:
|
||||
*
|
||||
@ -18,11 +18,11 @@ import java.util.Map;
|
||||
* a JSON object with the following information:
|
||||
* <ul>
|
||||
* <li>{@code result} The result, which can be of any JSON type
|
||||
* - a number, a boolean value, a string, an array, an object
|
||||
* - a number, a boolean value, a string, an array, an object
|
||||
* or null.
|
||||
* <li>{@code id} The request identifier which is echoed back back
|
||||
* <li>{@code id} The request identifier which is echoed back back
|
||||
* to the caller.
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol
|
||||
* version set to "2.0".
|
||||
* </ul>
|
||||
* <li>The request failed. The returned JSON object contains:
|
||||
@ -33,10 +33,10 @@ import java.util.Map;
|
||||
* <li>{@code message} A brief error messsage.
|
||||
* <li>{@code data} Optional error data.
|
||||
* </ul>
|
||||
* <li>{@code id} The request identifier. If it couldn't be
|
||||
* <li>{@code id} The request identifier. If it couldn't be
|
||||
* determined, e.g. due to a request parse error, the ID is
|
||||
* set to {@code null}.
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol
|
||||
* <li>{@code jsonrpc} A string indicating the JSON-RPC protocol
|
||||
* version set to "2.0".
|
||||
* </ul>
|
||||
* </ul>
|
||||
@ -45,10 +45,10 @@ import java.util.Map;
|
||||
* has succeeded:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* {
|
||||
* "result" : true,
|
||||
* "id" : "req-002",
|
||||
* "jsonrpc" : "2.0"
|
||||
* "jsonrpc" : "2.0"
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
@ -56,7 +56,7 @@ import java.util.Map;
|
||||
* <p>And here is an example JSON-RPC 2.0 response string indicating a failure:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* {
|
||||
* "error" : { "code" : -32601, "message" : "Method not found" },
|
||||
* "id" : "req-003",
|
||||
* "jsonrpc" : "2.0"
|
||||
@ -68,12 +68,12 @@ import java.util.Map;
|
||||
* appropriate constructor.
|
||||
*
|
||||
* <p>Here is how parsing is done:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* String jsonString = "{\"result\":true,\"id\":\"req-002\",\"jsonrpc\":\"2.0\"}";
|
||||
*
|
||||
*
|
||||
* JSONRPC2Response response = null;
|
||||
*
|
||||
*
|
||||
* try {
|
||||
* response = JSONRPC2Response.parse(jsonString);
|
||||
*
|
||||
@ -88,16 +88,16 @@ import java.util.Map;
|
||||
* // success example
|
||||
* JSONRPC2Response resp = new JSONRPC2Response(true, "req-002");
|
||||
* System.out.println(resp);
|
||||
*
|
||||
*
|
||||
* // failure example
|
||||
* JSONRPC2Error err = new JSONRPC2Error(-32601, "Method not found");
|
||||
* resp = new JSONRPC2Response(err, "req-003");
|
||||
* System.out.println(resp);
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <pre>
|
||||
* true|false <---> java.lang.Boolean
|
||||
* number <---> java.lang.Number
|
||||
@ -107,252 +107,252 @@ import java.util.Map;
|
||||
* null <---> null
|
||||
* </pre>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
* @version 1.16 (2010-05-19)
|
||||
*/
|
||||
public class JSONRPC2Response extends JSONRPC2Message {
|
||||
|
||||
|
||||
/**
|
||||
* The result.
|
||||
*/
|
||||
private Object result = null;
|
||||
|
||||
|
||||
/**
|
||||
* The error object.
|
||||
*/
|
||||
private JSONRPC2Error error = null;
|
||||
|
||||
|
||||
/**
|
||||
* The request identifier.
|
||||
*/
|
||||
private Object id = null;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 response string. This method is thread-safe.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 response string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 response object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Response parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 response string. This method is thread-safe.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 response string, UTF-8 encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in results will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 response object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Response parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Response(jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 response to a successful request.
|
||||
*
|
||||
* @param result The result. The value can <a href="#map">map</a>
|
||||
* to any JSON type.
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
*/
|
||||
public JSONRPC2Response(final Object result, final Object id) {
|
||||
|
||||
setResult(result);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 response to a failed request.
|
||||
*
|
||||
* @param error A JSON-RPC 2.0 error instance indicating the
|
||||
* cause of the failure.
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* Pass a {@code null} if the request identifier couldn't
|
||||
* be determined (e.g. due to a parse error).
|
||||
*/
|
||||
public JSONRPC2Response(final JSONRPC2Error error, final Object id) {
|
||||
|
||||
setError(error);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a successful JSON-RPC 2.0 request and sets the result.
|
||||
* Note that if the response was previously indicating failure this
|
||||
* will turn it into a response indicating success. Any previously set
|
||||
* error data will be invalidated.
|
||||
*
|
||||
* @param result The result. The value can <a href="#map">map</a> to
|
||||
* any JSON type.
|
||||
*/
|
||||
public void setResult(final Object result) {
|
||||
|
||||
if ( result != null &&
|
||||
! (result instanceof Boolean) &&
|
||||
! (result instanceof Number ) &&
|
||||
! (result instanceof String ) &&
|
||||
! (result instanceof List ) &&
|
||||
! (result instanceof Map ) )
|
||||
throw new IllegalArgumentException("The result must map to a JSON type");
|
||||
|
||||
// result and error are mutually exclusive
|
||||
this.result = result;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the result of the request. The returned value has meaning
|
||||
* only if the request was successful. Use the {@link #getError getError}
|
||||
* method to check this.
|
||||
*
|
||||
* @return The result
|
||||
*/
|
||||
public Object getResult() {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a failed JSON-RPC 2.0 request and sets the error details.
|
||||
* Note that if the response was previously indicating success this
|
||||
* will turn it into a response indicating failure. Any previously set
|
||||
* result data will be invalidated.
|
||||
*
|
||||
* @param error A JSON-RPC 2.0 error instance indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void setError(final JSONRPC2Error error) {
|
||||
|
||||
if (error == null)
|
||||
throw new NullPointerException("The error object cannot be null");
|
||||
|
||||
// result and error are mutually exclusive
|
||||
this.error = error;
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the error object indicating the cause of the request failure.
|
||||
* If a {@code null} is returned, the request succeeded and there was
|
||||
* no error.
|
||||
*
|
||||
* @return A JSON-RPC 2.0 error object, {@code null} if the
|
||||
* response indicates success.
|
||||
*/
|
||||
public JSONRPC2Error getError() {
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A convinience method to check if the response indicates success or
|
||||
* failure of the request. Alternatively, you can use the
|
||||
* {@code #getError} method for this purpose.
|
||||
*
|
||||
* @return {@code true} if the request succeeded, {@code false} if
|
||||
* there was an error.
|
||||
*/
|
||||
public boolean indicatesSuccess() {
|
||||
|
||||
if (error == null)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the request identifier echoed back to the caller.
|
||||
*
|
||||
* @param id The value must <a href="#map">map</a> to a JSON scalar.
|
||||
* Pass a {@code null} if the request identifier couldn't
|
||||
* be determined (e.g. due to a parse error).
|
||||
*/
|
||||
public void setID(final Object id) {
|
||||
|
||||
if ( id != null &&
|
||||
! (id instanceof Boolean) &&
|
||||
! (id instanceof Number ) &&
|
||||
! (id instanceof String ) )
|
||||
throw new IllegalArgumentException("The request identifier must map to a JSON scalar");
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request identifier that is echoed back to the caller.
|
||||
*
|
||||
* @return The request identifier. If there was an error during the
|
||||
* the request retrieval (e.g. parse error) and the identifier
|
||||
* couldn't be determined, the value will be {@code null}.
|
||||
*/
|
||||
public Object getID() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of this JSON-RPC 2.0 response.
|
||||
*
|
||||
* @return A JSON object representing the response.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject out = new JSONObject();
|
||||
|
||||
// Result and error are mutually exclusive
|
||||
if (error != null) {
|
||||
out.put("error", error.toJSON());
|
||||
}
|
||||
else {
|
||||
out.put("result", result);
|
||||
}
|
||||
|
||||
out.put("id", id);
|
||||
|
||||
out.put("jsonrpc", "2.0");
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The result.
|
||||
*/
|
||||
private Object result = null;
|
||||
|
||||
|
||||
/**
|
||||
* The error object.
|
||||
*/
|
||||
private JSONRPC2Error error = null;
|
||||
|
||||
|
||||
/**
|
||||
* The request identifier.
|
||||
*/
|
||||
private Object id = null;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 response string. This method is thread-safe.
|
||||
*
|
||||
* <p>The member order of parsed JSON objects will not be preserved
|
||||
* (for efficiency reasons) and the JSON-RPC 2.0 version field must be
|
||||
* set to "2.0". To change this behaviour check the optional {@link
|
||||
* #parse(String,boolean,boolean)} method.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 response string, UTF-8 encoded.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 response object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Response parse(final String jsonString)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
return parse(jsonString, false, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a JSON-RPC 2.0 response string. This method is thread-safe.
|
||||
*
|
||||
* @param jsonString The JSON-RPC 2.0 response string, UTF-8 encoded.
|
||||
* @param preserveOrder If {@code true} the member order of JSON objects
|
||||
* in results will be preserved.
|
||||
* @param noStrict If {@code true} the {@code "jsonrpc":"2.0"}
|
||||
* version field in the JSON-RPC 2.0 message will
|
||||
* not be checked.
|
||||
*
|
||||
* @return The corresponding JSON-RPC 2.0 response object.
|
||||
*
|
||||
* @throws JSONRPC2ParseException With detailed message if the parsing
|
||||
* failed.
|
||||
*/
|
||||
public static JSONRPC2Response parse(final String jsonString, final boolean preserveOrder, final boolean noStrict)
|
||||
throws JSONRPC2ParseException {
|
||||
|
||||
JSONRPC2Parser parser = new JSONRPC2Parser(preserveOrder, noStrict);
|
||||
|
||||
return parser.parseJSONRPC2Response(jsonString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 response to a successful request.
|
||||
*
|
||||
* @param result The result. The value can <a href="#map">map</a>
|
||||
* to any JSON type.
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
*/
|
||||
public JSONRPC2Response(final Object result, final Object id) {
|
||||
|
||||
setResult(result);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 response to a failed request.
|
||||
*
|
||||
* @param error A JSON-RPC 2.0 error instance indicating the
|
||||
* cause of the failure.
|
||||
* @param id The request identifier echoed back to the caller.
|
||||
* Pass a {@code null} if the request identifier couldn't
|
||||
* be determined (e.g. due to a parse error).
|
||||
*/
|
||||
public JSONRPC2Response(final JSONRPC2Error error, final Object id) {
|
||||
|
||||
setError(error);
|
||||
setID(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a successful JSON-RPC 2.0 request and sets the result.
|
||||
* Note that if the response was previously indicating failure this
|
||||
* will turn it into a response indicating success. Any previously set
|
||||
* error data will be invalidated.
|
||||
*
|
||||
* @param result The result. The value can <a href="#map">map</a> to
|
||||
* any JSON type.
|
||||
*/
|
||||
public void setResult(final Object result) {
|
||||
|
||||
if (result != null &&
|
||||
!(result instanceof Boolean) &&
|
||||
!(result instanceof Number) &&
|
||||
!(result instanceof String) &&
|
||||
!(result instanceof List) &&
|
||||
!(result instanceof Map))
|
||||
throw new IllegalArgumentException("The result must map to a JSON type");
|
||||
|
||||
// result and error are mutually exclusive
|
||||
this.result = result;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the result of the request. The returned value has meaning
|
||||
* only if the request was successful. Use the {@link #getError getError}
|
||||
* method to check this.
|
||||
*
|
||||
* @return The result
|
||||
*/
|
||||
public Object getResult() {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a failed JSON-RPC 2.0 request and sets the error details.
|
||||
* Note that if the response was previously indicating success this
|
||||
* will turn it into a response indicating failure. Any previously set
|
||||
* result data will be invalidated.
|
||||
*
|
||||
* @param error A JSON-RPC 2.0 error instance indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void setError(final JSONRPC2Error error) {
|
||||
|
||||
if (error == null)
|
||||
throw new NullPointerException("The error object cannot be null");
|
||||
|
||||
// result and error are mutually exclusive
|
||||
this.error = error;
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the error object indicating the cause of the request failure.
|
||||
* If a {@code null} is returned, the request succeeded and there was
|
||||
* no error.
|
||||
*
|
||||
* @return A JSON-RPC 2.0 error object, {@code null} if the
|
||||
* response indicates success.
|
||||
*/
|
||||
public JSONRPC2Error getError() {
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A convinience method to check if the response indicates success or
|
||||
* failure of the request. Alternatively, you can use the
|
||||
* {@code #getError} method for this purpose.
|
||||
*
|
||||
* @return {@code true} if the request succeeded, {@code false} if
|
||||
* there was an error.
|
||||
*/
|
||||
public boolean indicatesSuccess() {
|
||||
|
||||
if (error == null)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the request identifier echoed back to the caller.
|
||||
*
|
||||
* @param id The value must <a href="#map">map</a> to a JSON scalar.
|
||||
* Pass a {@code null} if the request identifier couldn't
|
||||
* be determined (e.g. due to a parse error).
|
||||
*/
|
||||
public void setID(final Object id) {
|
||||
|
||||
if (id != null &&
|
||||
!(id instanceof Boolean) &&
|
||||
!(id instanceof Number) &&
|
||||
!(id instanceof String))
|
||||
throw new IllegalArgumentException("The request identifier must map to a JSON scalar");
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request identifier that is echoed back to the caller.
|
||||
*
|
||||
* @return The request identifier. If there was an error during the
|
||||
* the request retrieval (e.g. parse error) and the identifier
|
||||
* couldn't be determined, the value will be {@code null}.
|
||||
*/
|
||||
public Object getID() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a JSON representation of this JSON-RPC 2.0 response.
|
||||
*
|
||||
* @return A JSON object representing the response.
|
||||
*/
|
||||
public JSONObject toJSON() {
|
||||
|
||||
JSONObject out = new JSONObject();
|
||||
|
||||
// Result and error are mutually exclusive
|
||||
if (error != null) {
|
||||
out.put("error", error.toJSON());
|
||||
}
|
||||
else {
|
||||
out.put("result", result);
|
||||
}
|
||||
|
||||
out.put("id", id);
|
||||
|
||||
out.put("jsonrpc", "2.0");
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,25 +1,25 @@
|
||||
/**
|
||||
* Classes to represent, parse and serialise JSON-RPC 2.0 requests,
|
||||
/**
|
||||
* Classes to represent, parse and serialise JSON-RPC 2.0 requests,
|
||||
* notifications and responses.
|
||||
*
|
||||
* <p>JSON-RPC is a protocol for
|
||||
* <a href="http://en.wikipedia.org/wiki/Remote_procedure_call">remote
|
||||
* <p>JSON-RPC is a protocol for
|
||||
* <a href="http://en.wikipedia.org/wiki/Remote_procedure_call">remote
|
||||
* procedure calls</a> (RPC) using <a href="http://www.json.org" >JSON</a>
|
||||
* - encoded requests and responses. It can be easily relayed over HTTP
|
||||
* and is of JavaScript origin, making it ideal for use in interactive web
|
||||
* - encoded requests and responses. It can be easily relayed over HTTP
|
||||
* and is of JavaScript origin, making it ideal for use in interactive web
|
||||
* applications (popularly known as AJAX or Web 2.0).
|
||||
*
|
||||
* <p>This package implements <b>version 2.0</b> of the protocol, with the
|
||||
* <p>This package implements <b>version 2.0</b> of the protocol, with the
|
||||
* exception of <i>batching/multicall</i>. This feature was deliberately left
|
||||
* out, as it tends to confuse users (judging by posts in the JSON-RPC forum).
|
||||
*
|
||||
* The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
* <p><b>Package dependencies:</b> The classes in this package rely on the
|
||||
* {@code org.json.simple} and {@code org.json.simple.parser} packages
|
||||
* <p><b>Package dependencies:</b> The classes in this package rely on the
|
||||
* {@code org.json.simple} and {@code org.json.simple.parser} packages
|
||||
* (version 1.1 and compabile) for JSON encoding and decoding. You can obtain
|
||||
* them as a single JAR file from the
|
||||
* them as a single JAR file from the
|
||||
* <a href="http://code.google.com/p/json-simple/">JSON-simple</a> website.
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
@ -28,4 +28,4 @@
|
||||
package com.thetransactioncompany.jsonrpc2;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -19,180 +19,180 @@ import java.util.Hashtable;
|
||||
* @version 1.3 (2011-03-05)
|
||||
*/
|
||||
public class Dispatcher {
|
||||
|
||||
|
||||
/**
|
||||
* Hashtable of request name / handler pairs.
|
||||
*/
|
||||
private Hashtable<String,RequestHandler> requestHandlers;
|
||||
|
||||
|
||||
/**
|
||||
* Hashtable of notification name / handler pairs.
|
||||
*/
|
||||
private Hashtable<String,NotificationHandler> notificationHandlers;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new dispatcher with no registered handlers.
|
||||
*/
|
||||
public Dispatcher() {
|
||||
|
||||
requestHandlers = new Hashtable<String,RequestHandler>();
|
||||
notificationHandlers = new Hashtable<String,NotificationHandler>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a new JSON-RPC 2.0 request handler.
|
||||
*
|
||||
* @param handler The request handler to register.
|
||||
*
|
||||
* @throws IllegalArgumentException On attempting to register a handler
|
||||
* that duplicates an existing request
|
||||
* name.
|
||||
*/
|
||||
public void register(final RequestHandler handler) {
|
||||
|
||||
for (String name: handler.handledRequests()) {
|
||||
|
||||
if (requestHandlers.containsKey(name))
|
||||
throw new IllegalArgumentException("Cannot register a duplicate handler for request " + name);
|
||||
|
||||
requestHandlers.put(name, handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a new JSON-RPC 2.0 notification handler.
|
||||
*
|
||||
* @param handler The notification handler to register.
|
||||
*
|
||||
* @throws IllegalArgumentException On attempting to register a handler
|
||||
* that duplicates an existing
|
||||
* notification name.
|
||||
*/
|
||||
public void register(final NotificationHandler handler) {
|
||||
|
||||
for (String name: handler.handledNotifications()) {
|
||||
|
||||
if (notificationHandlers.containsKey(name))
|
||||
throw new IllegalArgumentException("Cannot register a duplicate handler for notification " + name);
|
||||
|
||||
notificationHandlers.put(name, handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the registered request names.
|
||||
*
|
||||
* @return The request names.
|
||||
*/
|
||||
public String[] handledRequests() {
|
||||
|
||||
return requestHandlers.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the registered notification names.
|
||||
*
|
||||
* @return The notification names.
|
||||
*/
|
||||
public String[] handledNotifications() {
|
||||
|
||||
return notificationHandlers.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the handler for the specified JSON-RPC 2.0 request name.
|
||||
*
|
||||
* @param requestName The request name to lookup.
|
||||
*
|
||||
* @return The corresponding request handler or {@code null} if none
|
||||
* was found.
|
||||
*/
|
||||
public RequestHandler getRequestHandler(final String requestName) {
|
||||
|
||||
return requestHandlers.get(requestName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the handler for the specified JSON-RPC 2.0 notification name.
|
||||
*
|
||||
* @param notificationName The notification name to lookup.
|
||||
*
|
||||
* @return The corresponding notification handler or {@code null} if
|
||||
* none was found.
|
||||
*/
|
||||
public NotificationHandler getNotificationHandler(final String notificationName) {
|
||||
|
||||
return notificationHandlers.get(notificationName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches the specified JSON-RPC 2.0 request to the appropriate
|
||||
* handler for processing and returns the response.
|
||||
*
|
||||
* @param request The JSON-RPC 2.0 request to dispatch for
|
||||
* processing.
|
||||
* @param requestCtx Context information about the request, may be
|
||||
* {@code null} if undefined.
|
||||
*
|
||||
* @return The response, which may indicate a processing error, such
|
||||
* as METHOD_NOT_FOUND.
|
||||
*/
|
||||
public JSONRPC2Response dispatch(final JSONRPC2Request request, final MessageContext requestCtx) {
|
||||
|
||||
final String method = request.getMethod();
|
||||
|
||||
RequestHandler handler = getRequestHandler(method);
|
||||
|
||||
if (handler == null) {
|
||||
|
||||
// We didn't find a handler for the requested RPC
|
||||
|
||||
Object id = request.getID();
|
||||
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, id);
|
||||
}
|
||||
|
||||
// Process the request
|
||||
|
||||
return handler.process(request, requestCtx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches the specified JSON-RPC 2.0 notification to the appropriate
|
||||
* handler for processing.
|
||||
*
|
||||
* <p>Note that JSON-RPC 2.0 notifications don't produce a response!
|
||||
*
|
||||
* @param notification The JSON-RPC 2.0 notification to dispatch for
|
||||
* processing.
|
||||
* @param notificationCtx Context information about the notification,
|
||||
* may be {@code null} if undefined.
|
||||
*/
|
||||
public void dispatch(final JSONRPC2Notification notification, final MessageContext notificationCtx) {
|
||||
|
||||
final String method = notification.getMethod();
|
||||
|
||||
NotificationHandler handler = getNotificationHandler(method);
|
||||
|
||||
if (handler == null) {
|
||||
|
||||
// We didn't find a handler for the requested RPC
|
||||
return;
|
||||
}
|
||||
|
||||
// Process the notification
|
||||
|
||||
handler.process(notification, notificationCtx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hashtable of request name / handler pairs.
|
||||
*/
|
||||
private Hashtable<String, RequestHandler> requestHandlers;
|
||||
|
||||
|
||||
/**
|
||||
* Hashtable of notification name / handler pairs.
|
||||
*/
|
||||
private Hashtable<String, NotificationHandler> notificationHandlers;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new dispatcher with no registered handlers.
|
||||
*/
|
||||
public Dispatcher() {
|
||||
|
||||
requestHandlers = new Hashtable<String, RequestHandler>();
|
||||
notificationHandlers = new Hashtable<String, NotificationHandler>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a new JSON-RPC 2.0 request handler.
|
||||
*
|
||||
* @param handler The request handler to register.
|
||||
*
|
||||
* @throws IllegalArgumentException On attempting to register a handler
|
||||
* that duplicates an existing request
|
||||
* name.
|
||||
*/
|
||||
public void register(final RequestHandler handler) {
|
||||
|
||||
for (String name : handler.handledRequests()) {
|
||||
|
||||
if (requestHandlers.containsKey(name))
|
||||
throw new IllegalArgumentException("Cannot register a duplicate handler for request " + name);
|
||||
|
||||
requestHandlers.put(name, handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a new JSON-RPC 2.0 notification handler.
|
||||
*
|
||||
* @param handler The notification handler to register.
|
||||
*
|
||||
* @throws IllegalArgumentException On attempting to register a handler
|
||||
* that duplicates an existing
|
||||
* notification name.
|
||||
*/
|
||||
public void register(final NotificationHandler handler) {
|
||||
|
||||
for (String name : handler.handledNotifications()) {
|
||||
|
||||
if (notificationHandlers.containsKey(name))
|
||||
throw new IllegalArgumentException("Cannot register a duplicate handler for notification " + name);
|
||||
|
||||
notificationHandlers.put(name, handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the registered request names.
|
||||
*
|
||||
* @return The request names.
|
||||
*/
|
||||
public String[] handledRequests() {
|
||||
|
||||
return requestHandlers.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the registered notification names.
|
||||
*
|
||||
* @return The notification names.
|
||||
*/
|
||||
public String[] handledNotifications() {
|
||||
|
||||
return notificationHandlers.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the handler for the specified JSON-RPC 2.0 request name.
|
||||
*
|
||||
* @param requestName The request name to lookup.
|
||||
*
|
||||
* @return The corresponding request handler or {@code null} if none
|
||||
* was found.
|
||||
*/
|
||||
public RequestHandler getRequestHandler(final String requestName) {
|
||||
|
||||
return requestHandlers.get(requestName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the handler for the specified JSON-RPC 2.0 notification name.
|
||||
*
|
||||
* @param notificationName The notification name to lookup.
|
||||
*
|
||||
* @return The corresponding notification handler or {@code null} if
|
||||
* none was found.
|
||||
*/
|
||||
public NotificationHandler getNotificationHandler(final String notificationName) {
|
||||
|
||||
return notificationHandlers.get(notificationName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches the specified JSON-RPC 2.0 request to the appropriate
|
||||
* handler for processing and returns the response.
|
||||
*
|
||||
* @param request The JSON-RPC 2.0 request to dispatch for
|
||||
* processing.
|
||||
* @param requestCtx Context information about the request, may be
|
||||
* {@code null} if undefined.
|
||||
*
|
||||
* @return The response, which may indicate a processing error, such
|
||||
* as METHOD_NOT_FOUND.
|
||||
*/
|
||||
public JSONRPC2Response dispatch(final JSONRPC2Request request, final MessageContext requestCtx) {
|
||||
|
||||
final String method = request.getMethod();
|
||||
|
||||
RequestHandler handler = getRequestHandler(method);
|
||||
|
||||
if (handler == null) {
|
||||
|
||||
// We didn't find a handler for the requested RPC
|
||||
|
||||
Object id = request.getID();
|
||||
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, id);
|
||||
}
|
||||
|
||||
// Process the request
|
||||
|
||||
return handler.process(request, requestCtx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches the specified JSON-RPC 2.0 notification to the appropriate
|
||||
* handler for processing.
|
||||
*
|
||||
* <p>Note that JSON-RPC 2.0 notifications don't produce a response!
|
||||
*
|
||||
* @param notification The JSON-RPC 2.0 notification to dispatch for
|
||||
* processing.
|
||||
* @param notificationCtx Context information about the notification,
|
||||
* may be {@code null} if undefined.
|
||||
*/
|
||||
public void dispatch(final JSONRPC2Notification notification, final MessageContext notificationCtx) {
|
||||
|
||||
final String method = notification.getMethod();
|
||||
|
||||
NotificationHandler handler = getNotificationHandler(method);
|
||||
|
||||
if (handler == null) {
|
||||
|
||||
// We didn't find a handler for the requested RPC
|
||||
return;
|
||||
}
|
||||
|
||||
// Process the notification
|
||||
|
||||
handler.process(notification, notificationCtx);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import java.security.cert.X509Certificate;
|
||||
* <ul>
|
||||
* <li>The client's host name.
|
||||
* <li>The client's IP address.
|
||||
* <li>Whether the request / notification was transmitted securely (e.g.
|
||||
* <li>Whether the request / notification was transmitted securely (e.g.
|
||||
* via HTTPS).
|
||||
* <li>The client principal (user), if authenticated.
|
||||
* </ul>
|
||||
@ -23,224 +23,224 @@ import java.security.cert.X509Certificate;
|
||||
public class MessageContext {
|
||||
|
||||
|
||||
/**
|
||||
* The client hostname.
|
||||
*/
|
||||
private String clientHostName = null;
|
||||
/**
|
||||
* The client hostname.
|
||||
*/
|
||||
private String clientHostName = null;
|
||||
|
||||
|
||||
/**
|
||||
* The client IP address.
|
||||
*/
|
||||
private String clientInetAddress = null;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether the request was received over HTTPS.
|
||||
*/
|
||||
private boolean secure = false;
|
||||
|
||||
|
||||
/**
|
||||
* The authenticated client principal.
|
||||
*/
|
||||
private Principal principal = null;
|
||||
|
||||
|
||||
/**
|
||||
* Minimal implementation of the {@link java.security.Principal}
|
||||
* interface.
|
||||
*/
|
||||
protected class BasicPrincipal implements Principal {
|
||||
|
||||
/**
|
||||
* The principal name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new principal.
|
||||
*
|
||||
* @param name The principal name.
|
||||
*/
|
||||
public BasicPrincipal(final String name) {
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for equality.
|
||||
*
|
||||
* @param another The object to compare to.
|
||||
*/
|
||||
public boolean equals(final Object another) {
|
||||
|
||||
if (another instanceof Principal && ((Principal)another).getName().equals(this.getName()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a hash code for this principal.
|
||||
*
|
||||
* @return The hash code.
|
||||
*/
|
||||
public int hashCode() {
|
||||
|
||||
if (name == null)
|
||||
return 0;
|
||||
else
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the principal name.
|
||||
*
|
||||
* @return The principal name.
|
||||
*/
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context.
|
||||
*
|
||||
* @param clientHostName The client host name, {@code null} if
|
||||
* unknown.
|
||||
* @param clientInetAddress The client IP address, {@code null} if
|
||||
* unknown.
|
||||
* @param secure Specifies a request received over HTTPS.
|
||||
* @param principalName Specifies the authenticated client principle
|
||||
* name, {@code null} if none.
|
||||
*/
|
||||
public MessageContext(final String clientHostName,
|
||||
final String clientInetAddress,
|
||||
final boolean secure,
|
||||
final String principalName) {
|
||||
|
||||
this.clientHostName = clientHostName;
|
||||
this.clientInetAddress = clientInetAddress;
|
||||
this.secure = secure;
|
||||
|
||||
this.principal = new BasicPrincipal(principalName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context. No
|
||||
* authenticated client principal is specified.
|
||||
*
|
||||
* @param clientHostName The client host name, {@code null} if
|
||||
* unknown.
|
||||
* @param clientInetAddress The client IP address, {@code null} if
|
||||
* unknown.
|
||||
* @param secure Specifies a request received over HTTPS.
|
||||
*/
|
||||
public MessageContext(final String clientHostName,
|
||||
final String clientInetAddress,
|
||||
final boolean secure) {
|
||||
|
||||
this(clientHostName, clientInetAddress, secure, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context. Indicates
|
||||
* an insecure transport (plain HTTP) and no authenticated client
|
||||
* principal.
|
||||
*
|
||||
* @param clientHostName The client host name, {@code null} if
|
||||
* unknown.
|
||||
* @param clientInetAddress The client IP address, {@code null} if
|
||||
* unknown.
|
||||
*/
|
||||
public MessageContext(final String clientHostName,
|
||||
final String clientInetAddress) {
|
||||
|
||||
this(clientHostName, clientInetAddress, false, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context from the
|
||||
* specified HTTP request.
|
||||
*
|
||||
* @param httpRequest The HTTP request.
|
||||
*/
|
||||
public MessageContext(final HttpServletRequest httpRequest) {
|
||||
|
||||
clientInetAddress = httpRequest.getRemoteAddr();
|
||||
|
||||
clientHostName = httpRequest.getRemoteHost();
|
||||
|
||||
if (clientHostName != null && clientHostName.equals(clientInetAddress))
|
||||
clientHostName = null; // not resolved actually
|
||||
|
||||
secure = httpRequest.isSecure();
|
||||
/**
|
||||
* The client IP address.
|
||||
*/
|
||||
private String clientInetAddress = null;
|
||||
|
||||
X509Certificate[] certs = (X509Certificate[])httpRequest.getAttribute("javax.servlet.request.X509Certificate");
|
||||
|
||||
String principalName = null;
|
||||
/**
|
||||
* Indicates whether the request was received over HTTPS.
|
||||
*/
|
||||
private boolean secure = false;
|
||||
|
||||
if (certs != null)
|
||||
principalName = certs[0].getSubjectDN().getName();
|
||||
|
||||
principal = new BasicPrincipal(principalName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the host name of the client that sent the request /
|
||||
* notification.
|
||||
*
|
||||
* @return The client host name, {@code null} if unknown.
|
||||
*/
|
||||
public String getClientHostName() {
|
||||
|
||||
return clientHostName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the IP address of the client that sent the request /
|
||||
* notification.
|
||||
*
|
||||
* @return The client IP address, {@code null} if unknown.
|
||||
*/
|
||||
public String getClientInetAddress() {
|
||||
|
||||
return clientInetAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether the request / notification was received over a
|
||||
* secure HTTPS connection.
|
||||
*
|
||||
* @return {@code true} If the request was received over HTTPS,
|
||||
* {@code false} if it was received over plain HTTP.
|
||||
*/
|
||||
public boolean isSecure() {
|
||||
|
||||
return secure;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the authenticated client principal, {@code null} if none.
|
||||
*
|
||||
* @return The client principal, {@code null} if none.
|
||||
*/
|
||||
public Principal getPrincipal() {
|
||||
|
||||
return principal;
|
||||
}
|
||||
/**
|
||||
* The authenticated client principal.
|
||||
*/
|
||||
private Principal principal = null;
|
||||
|
||||
|
||||
/**
|
||||
* Minimal implementation of the {@link java.security.Principal}
|
||||
* interface.
|
||||
*/
|
||||
protected class BasicPrincipal implements Principal {
|
||||
|
||||
/**
|
||||
* The principal name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new principal.
|
||||
*
|
||||
* @param name The principal name.
|
||||
*/
|
||||
public BasicPrincipal(final String name) {
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for equality.
|
||||
*
|
||||
* @param another The object to compare to.
|
||||
*/
|
||||
public boolean equals(final Object another) {
|
||||
|
||||
if (another instanceof Principal && ((Principal)another).getName().equals(this.getName()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a hash code for this principal.
|
||||
*
|
||||
* @return The hash code.
|
||||
*/
|
||||
public int hashCode() {
|
||||
|
||||
if (name == null)
|
||||
return 0;
|
||||
else
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the principal name.
|
||||
*
|
||||
* @return The principal name.
|
||||
*/
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context.
|
||||
*
|
||||
* @param clientHostName The client host name, {@code null} if
|
||||
* unknown.
|
||||
* @param clientInetAddress The client IP address, {@code null} if
|
||||
* unknown.
|
||||
* @param secure Specifies a request received over HTTPS.
|
||||
* @param principalName Specifies the authenticated client principle
|
||||
* name, {@code null} if none.
|
||||
*/
|
||||
public MessageContext(final String clientHostName,
|
||||
final String clientInetAddress,
|
||||
final boolean secure,
|
||||
final String principalName) {
|
||||
|
||||
this.clientHostName = clientHostName;
|
||||
this.clientInetAddress = clientInetAddress;
|
||||
this.secure = secure;
|
||||
|
||||
this.principal = new BasicPrincipal(principalName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context. No
|
||||
* authenticated client principal is specified.
|
||||
*
|
||||
* @param clientHostName The client host name, {@code null} if
|
||||
* unknown.
|
||||
* @param clientInetAddress The client IP address, {@code null} if
|
||||
* unknown.
|
||||
* @param secure Specifies a request received over HTTPS.
|
||||
*/
|
||||
public MessageContext(final String clientHostName,
|
||||
final String clientInetAddress,
|
||||
final boolean secure) {
|
||||
|
||||
this(clientHostName, clientInetAddress, secure, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context. Indicates
|
||||
* an insecure transport (plain HTTP) and no authenticated client
|
||||
* principal.
|
||||
*
|
||||
* @param clientHostName The client host name, {@code null} if
|
||||
* unknown.
|
||||
* @param clientInetAddress The client IP address, {@code null} if
|
||||
* unknown.
|
||||
*/
|
||||
public MessageContext(final String clientHostName,
|
||||
final String clientInetAddress) {
|
||||
|
||||
this(clientHostName, clientInetAddress, false, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 request / notification context from the
|
||||
* specified HTTP request.
|
||||
*
|
||||
* @param httpRequest The HTTP request.
|
||||
*/
|
||||
public MessageContext(final HttpServletRequest httpRequest) {
|
||||
|
||||
clientInetAddress = httpRequest.getRemoteAddr();
|
||||
|
||||
clientHostName = httpRequest.getRemoteHost();
|
||||
|
||||
if (clientHostName != null && clientHostName.equals(clientInetAddress))
|
||||
clientHostName = null; // not resolved actually
|
||||
|
||||
secure = httpRequest.isSecure();
|
||||
|
||||
X509Certificate[] certs = (X509Certificate[])httpRequest.getAttribute("javax.servlet.request.X509Certificate");
|
||||
|
||||
String principalName = null;
|
||||
|
||||
if (certs != null)
|
||||
principalName = certs[0].getSubjectDN().getName();
|
||||
|
||||
principal = new BasicPrincipal(principalName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the host name of the client that sent the request /
|
||||
* notification.
|
||||
*
|
||||
* @return The client host name, {@code null} if unknown.
|
||||
*/
|
||||
public String getClientHostName() {
|
||||
|
||||
return clientHostName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the IP address of the client that sent the request /
|
||||
* notification.
|
||||
*
|
||||
* @return The client IP address, {@code null} if unknown.
|
||||
*/
|
||||
public String getClientInetAddress() {
|
||||
|
||||
return clientInetAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether the request / notification was received over a
|
||||
* secure HTTPS connection.
|
||||
*
|
||||
* @return {@code true} If the request was received over HTTPS,
|
||||
* {@code false} if it was received over plain HTTP.
|
||||
*/
|
||||
public boolean isSecure() {
|
||||
|
||||
return secure;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the authenticated client principal, {@code null} if none.
|
||||
*
|
||||
* @return The client principal, {@code null} if none.
|
||||
*/
|
||||
public Principal getPrincipal() {
|
||||
|
||||
return principal;
|
||||
}
|
||||
}
|
||||
|
@ -12,23 +12,23 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Notification;
|
||||
*/
|
||||
public interface NotificationHandler {
|
||||
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 notification method names that this handler
|
||||
* processes.
|
||||
*
|
||||
* @return The method names of the served JSON-RPC 2.0 notifications.
|
||||
*/
|
||||
public String[] handledNotifications();
|
||||
|
||||
|
||||
/**
|
||||
* Processes a JSON-RPC 2.0 notification.
|
||||
*
|
||||
* @param notification A valid JSON-RPC 2.0 notification instance.
|
||||
* @param notificationCtx Context information about the notification,
|
||||
* may be {@code null} if undefined.
|
||||
*/
|
||||
public void process(final JSONRPC2Notification notification, final MessageContext notificationCtx);
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 notification method names that this handler
|
||||
* processes.
|
||||
*
|
||||
* @return The method names of the served JSON-RPC 2.0 notifications.
|
||||
*/
|
||||
public String[] handledNotifications();
|
||||
|
||||
|
||||
/**
|
||||
* Processes a JSON-RPC 2.0 notification.
|
||||
*
|
||||
* @param notification A valid JSON-RPC 2.0 notification instance.
|
||||
* @param notificationCtx Context information about the notification,
|
||||
* may be {@code null} if undefined.
|
||||
*/
|
||||
public void process(final JSONRPC2Notification notification, final MessageContext notificationCtx);
|
||||
|
||||
}
|
||||
|
@ -13,25 +13,25 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
|
||||
*/
|
||||
public interface RequestHandler {
|
||||
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 request method names that this handler
|
||||
* processes.
|
||||
*
|
||||
* @return The method names of the served JSON-RPC 2.0 requests.
|
||||
*/
|
||||
public String[] handledRequests();
|
||||
|
||||
|
||||
/**
|
||||
* Processes a JSON-RPC 2.0 request.
|
||||
*
|
||||
* @param request A valid JSON-RPC 2.0 request instance.
|
||||
* @param requestCtx Context information about the request, may be
|
||||
* {@code null} if undefined.
|
||||
*
|
||||
* @return The resulting JSON-RPC 2.0 response.
|
||||
*/
|
||||
public JSONRPC2Response process(final JSONRPC2Request request, final MessageContext requestCtx);
|
||||
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 request method names that this handler
|
||||
* processes.
|
||||
*
|
||||
* @return The method names of the served JSON-RPC 2.0 requests.
|
||||
*/
|
||||
public String[] handledRequests();
|
||||
|
||||
|
||||
/**
|
||||
* Processes a JSON-RPC 2.0 request.
|
||||
*
|
||||
* @param request A valid JSON-RPC 2.0 request instance.
|
||||
* @param requestCtx Context information about the request, may be
|
||||
* {@code null} if undefined.
|
||||
*
|
||||
* @return The resulting JSON-RPC 2.0 response.
|
||||
*/
|
||||
public JSONRPC2Response process(final JSONRPC2Request request, final MessageContext requestCtx);
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* Simple server framework for processing JSON-RPC 2.0 requests and
|
||||
* notifications.
|
||||
*
|
||||
@ -8,12 +8,12 @@
|
||||
* <li>Implement {@link com.thetransactioncompany.jsonrpc2.server.RequestHandler request}
|
||||
* and / or {@link com.thetransactioncompany.jsonrpc2.server.NotificationHandler notification}
|
||||
* handlers for the various expected JSON-RPC 2.0 messages. A handler
|
||||
* may process one or more request/notification methods (identified by
|
||||
* may process one or more request/notification methods (identified by
|
||||
* method name).
|
||||
* <li>Create a new {@link com.thetransactioncompany.jsonrpc2.server.Dispatcher}
|
||||
* and register the handlers with it.
|
||||
* <li>Pass the received JSON-RPC 2.0 requests and notifications to the
|
||||
* appropriate {@code Dispatcher.dispatch(...)} method, then, if the
|
||||
* <li>Pass the received JSON-RPC 2.0 requests and notifications to the
|
||||
* appropriate {@code Dispatcher.dispatch(...)} method, then, if the
|
||||
* message is a request, pass the resulting JSON-RPC 2.0 response back
|
||||
* to the client.
|
||||
* </ol>
|
||||
@ -21,10 +21,10 @@
|
||||
* <p>Direct package dependencies:
|
||||
*
|
||||
* <ul>
|
||||
* <li><b><a href="http://software.dzhuvinov.com/json-rpc-2.0-base.html">JSON-RPC 2.0 Base</a></b>
|
||||
* [<i>com.thetransactioncompany.jsonrpc2</i>] to construct and represent
|
||||
* <li><b><a href="http://software.dzhuvinov.com/json-rpc-2.0-base.html">JSON-RPC 2.0 Base</a></b>
|
||||
* [<i>com.thetransactioncompany.jsonrpc2</i>] to construct and represent
|
||||
* JSON-RPC 2.0 messages.
|
||||
* <li><b>Java Servlet API</b> [<i>javax.servlet.http</i>] for constructing
|
||||
* <li><b>Java Servlet API</b> [<i>javax.servlet.http</i>] for constructing
|
||||
* {@link com.thetransactioncompany.jsonrpc2.server.MessageContext}
|
||||
* objects from HTTP servlet requests.
|
||||
* </ul>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,86 +12,86 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Error;
|
||||
*/
|
||||
public abstract class ParamsRetriever {
|
||||
|
||||
/**
|
||||
* Returns the parameter count.
|
||||
*
|
||||
* @return The number of parameters.
|
||||
*/
|
||||
public abstract int size();
|
||||
/**
|
||||
* Returns the parameter count.
|
||||
*
|
||||
* @return The number of parameters.
|
||||
*/
|
||||
public abstract int size();
|
||||
|
||||
|
||||
/**
|
||||
* Throws a {@code JSONRPC2Error.INVALID_PARAMS} exception if the input
|
||||
* string doesn't match a value in the specified string array.
|
||||
*
|
||||
* <p>This method is intended to check a string against a set of
|
||||
* acceptable values.
|
||||
*
|
||||
* @param input The string to check.
|
||||
* @param enumStrings The acceptable string values.
|
||||
* @param ignoreCase {@code true} for a case insensitive match.
|
||||
*
|
||||
* @return The matching string value.
|
||||
*
|
||||
* @throws JSONRPC2Error With proper code and message if the input
|
||||
* string didn't match.
|
||||
*/
|
||||
protected static String ensureEnumString(final String input, final String[] enumStrings, final boolean ignoreCase)
|
||||
throws JSONRPC2Error {
|
||||
|
||||
for (String en: enumStrings) {
|
||||
|
||||
if (ignoreCase) {
|
||||
if (en.toLowerCase().equals(input.toLowerCase()))
|
||||
return en;
|
||||
}
|
||||
else {
|
||||
if (en.equals(input))
|
||||
return en;
|
||||
}
|
||||
}
|
||||
|
||||
// No match -> raise error
|
||||
throw JSONRPC2Error.INVALID_PARAMS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws a {@code JSONRPC2Error.INVALID_PARAMS} exception if the input
|
||||
* string doesn't match a constant name in the specified enumeration
|
||||
* class.
|
||||
*
|
||||
* <p>This method is intended to check a string against a set of
|
||||
* acceptable values.
|
||||
*
|
||||
* @param input The string to check.
|
||||
* @param enumClass The enumeration class specifying the acceptable
|
||||
* constant names.
|
||||
* @param ignoreCase {@code true} for a case insensitive match.
|
||||
*
|
||||
* @return The matching enumeration constant.
|
||||
*
|
||||
* @throws JSONRPC2Error With proper code and message if the input
|
||||
* string didn't match.
|
||||
*/
|
||||
protected static <T extends Enum<T>> T ensureEnumString(final String input, final Class<T> enumClass, final boolean ignoreCase)
|
||||
throws JSONRPC2Error {
|
||||
|
||||
for (T en: enumClass.getEnumConstants()) {
|
||||
|
||||
if (ignoreCase) {
|
||||
if (en.toString().toLowerCase().equals(input.toLowerCase()))
|
||||
return en;
|
||||
}
|
||||
else {
|
||||
if (en.toString().equals(input))
|
||||
return en;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// No match -> raise error
|
||||
throw JSONRPC2Error.INVALID_PARAMS;
|
||||
}
|
||||
/**
|
||||
* Throws a {@code JSONRPC2Error.INVALID_PARAMS} exception if the input
|
||||
* string doesn't match a value in the specified string array.
|
||||
*
|
||||
* <p>This method is intended to check a string against a set of
|
||||
* acceptable values.
|
||||
*
|
||||
* @param input The string to check.
|
||||
* @param enumStrings The acceptable string values.
|
||||
* @param ignoreCase {@code true} for a case insensitive match.
|
||||
*
|
||||
* @return The matching string value.
|
||||
*
|
||||
* @throws JSONRPC2Error With proper code and message if the input
|
||||
* string didn't match.
|
||||
*/
|
||||
protected static String ensureEnumString(final String input, final String[] enumStrings, final boolean ignoreCase)
|
||||
throws JSONRPC2Error {
|
||||
|
||||
for (String en : enumStrings) {
|
||||
|
||||
if (ignoreCase) {
|
||||
if (en.toLowerCase().equals(input.toLowerCase()))
|
||||
return en;
|
||||
}
|
||||
else {
|
||||
if (en.equals(input))
|
||||
return en;
|
||||
}
|
||||
}
|
||||
|
||||
// No match -> raise error
|
||||
throw JSONRPC2Error.INVALID_PARAMS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws a {@code JSONRPC2Error.INVALID_PARAMS} exception if the input
|
||||
* string doesn't match a constant name in the specified enumeration
|
||||
* class.
|
||||
*
|
||||
* <p>This method is intended to check a string against a set of
|
||||
* acceptable values.
|
||||
*
|
||||
* @param input The string to check.
|
||||
* @param enumClass The enumeration class specifying the acceptable
|
||||
* constant names.
|
||||
* @param ignoreCase {@code true} for a case insensitive match.
|
||||
*
|
||||
* @return The matching enumeration constant.
|
||||
*
|
||||
* @throws JSONRPC2Error With proper code and message if the input
|
||||
* string didn't match.
|
||||
*/
|
||||
protected static <T extends Enum<T>> T ensureEnumString(final String input, final Class<T> enumClass, final boolean ignoreCase)
|
||||
throws JSONRPC2Error {
|
||||
|
||||
for (T en : enumClass.getEnumConstants()) {
|
||||
|
||||
if (ignoreCase) {
|
||||
if (en.toString().toLowerCase().equals(input.toLowerCase()))
|
||||
return en;
|
||||
}
|
||||
else {
|
||||
if (en.toString().equals(input))
|
||||
return en;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// No match -> raise error
|
||||
throw JSONRPC2Error.INVALID_PARAMS;
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,18 @@
|
||||
/**
|
||||
/**
|
||||
* Utility classes for typed retrieval of JSON-RPC 2.0 request parameters on the
|
||||
* server side.
|
||||
*
|
||||
*
|
||||
* <p>The following parameter type conversion choices are available:
|
||||
*
|
||||
* <ul>
|
||||
* <li>JSON true/false to Java {@code boolean}</li>
|
||||
* <li>JSON number to Java {@code int}, {@code long}, {@code float} or
|
||||
* <li>JSON number to Java {@code int}, {@code long}, {@code float} or
|
||||
* {@code double}</li>
|
||||
* <li>JSON string to {@code java.lang.String}</li>
|
||||
* <li>Predefined (enumerated) JSON string to a Java {@code enum} constant
|
||||
* or {@code java.lang.String}</li>
|
||||
* <li>JSON array to Java {@code boolean[]}, {@code int[]}, {@code long[]},
|
||||
* {@code float[]}, {@code double[]} or {@code string[]} array, or
|
||||
* {@code float[]}, {@code double[]} or {@code string[]} array, or
|
||||
* to mixed type {@code java.util.List}</li>
|
||||
* <li>JSON object to {@code java.util.Map}</li>
|
||||
* </ul>
|
||||
@ -24,16 +24,16 @@
|
||||
* <p>There are two concrete classes:
|
||||
*
|
||||
* <ul>
|
||||
* <li>The {@link com.thetransactioncompany.jsonrpc2.util.PositionalParamsRetriever}
|
||||
* <li>The {@link com.thetransactioncompany.jsonrpc2.util.PositionalParamsRetriever}
|
||||
* class is for extracting <em>positional parameters</em> (packed in a
|
||||
* JSON array).
|
||||
* <li>The {@link com.thetransactioncompany.jsonrpc2.util.NamedParamsRetriever}
|
||||
* JSON array).
|
||||
* <li>The {@link com.thetransactioncompany.jsonrpc2.util.NamedParamsRetriever}
|
||||
* class is for extracting <em>named parameters</em> (packed in a JSON
|
||||
* object).
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <p><b>Package dependencies:</b> The classes in this package depend on the
|
||||
* <p><b>Package dependencies:</b> The classes in this package depend on the
|
||||
* sister {@link com.thetransactioncompany.jsonrpc2} package.
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
@ -41,4 +41,4 @@
|
||||
*/
|
||||
package com.thetransactioncompany.jsonrpc2.util;
|
||||
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ import java.security.KeyStore;
|
||||
*
|
||||
* @author hottuna
|
||||
*/
|
||||
public class I2PControlController{
|
||||
public class I2PControlController {
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlController.class);
|
||||
private static String _pluginDir = "";
|
||||
private static ConfigurationManager _conf;
|
||||
@ -57,7 +57,7 @@ public class I2PControlController{
|
||||
if (args.length != 3 || (!"-d".equals(args[0])))
|
||||
throw new IllegalArgumentException("Usage: PluginController -d $PLUGINDIR [start|stop]");
|
||||
|
||||
if ("start".equals(args[2])){
|
||||
if ("start".equals(args[2])) {
|
||||
File pluginDir = new File(args[1]);
|
||||
if (!pluginDir.exists())
|
||||
throw new IllegalArgumentException("Plugin directory " + pluginDir.getAbsolutePath() + " does not exist");
|
||||
@ -79,10 +79,10 @@ public class I2PControlController{
|
||||
I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class).setMinimumPriority(Log.DEBUG);
|
||||
|
||||
try {
|
||||
Connector ssl = buildDefaultListenter();
|
||||
Connector ssl = buildDefaultListenter();
|
||||
_server = buildServer(ssl);
|
||||
} catch (IOException e) {
|
||||
_log.error("Unable to add listener " + _conf.getConf("i2pcontrol.listen.address", "127.0.0.1")+":"+_conf.getConf("i2pcontrol.listen.port", 7560) + " - " + e.getMessage());
|
||||
_log.error("Unable to add listener " + _conf.getConf("i2pcontrol.listen.address", "127.0.0.1") + ":" + _conf.getConf("i2pcontrol.listen.port", 7560) + " - " + e.getMessage());
|
||||
} catch (ClassNotFoundException e) {
|
||||
_log.error("Unable to find class net.i2p.i2pcontrol.JSONRPCServlet: " + e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
@ -93,7 +93,7 @@ public class I2PControlController{
|
||||
_log.error("Unable to start jetty server: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -102,8 +102,8 @@ public class I2PControlController{
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static Connector buildDefaultListenter() throws UnknownHostException {
|
||||
SslSocketConnector ssl = buildSslListener(_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
|
||||
_conf.getConf("i2pcontrol.listen.port", 7650));
|
||||
SslSocketConnector ssl = buildSslListener(_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
|
||||
_conf.getConf("i2pcontrol.listen.port", 7650));
|
||||
return ssl;
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ public class I2PControlController{
|
||||
* @throws InstantiationException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public static Server buildServer(Connector ssl) throws UnknownHostException, Exception, InstantiationException, IllegalAccessException{
|
||||
public static Server buildServer(Connector ssl) throws UnknownHostException, Exception, InstantiationException, IllegalAccessException {
|
||||
Server server = new Server();
|
||||
server.addConnector(ssl);
|
||||
|
||||
@ -136,9 +136,9 @@ public class I2PControlController{
|
||||
* @return - Newly created listener
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static SslSocketConnector buildSslListener(String address, int port) throws UnknownHostException{
|
||||
public static SslSocketConnector buildSslListener(String address, int port) throws UnknownHostException {
|
||||
int listeners = 0;
|
||||
if (_server != null){
|
||||
if (_server != null) {
|
||||
listeners = _server.getConnectors().length;
|
||||
}
|
||||
|
||||
@ -160,15 +160,15 @@ public class I2PControlController{
|
||||
|
||||
/**
|
||||
* Add a listener to the server
|
||||
* If a listener listening to the same port as the provided listener
|
||||
* If a listener listening to the same port as the provided listener
|
||||
* uses already exists within the server, replace the one already used by
|
||||
* the server with the provided listener.
|
||||
* @param listener
|
||||
* @throws Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void replaceListener(Connector listener) throws Exception{
|
||||
public static void replaceListener(Connector listener) throws Exception {
|
||||
if (_server != null) {
|
||||
stopServer();
|
||||
stopServer();
|
||||
}
|
||||
_server = buildServer(listener);
|
||||
}
|
||||
@ -177,8 +177,8 @@ public class I2PControlController{
|
||||
* Get all listeners of the server.
|
||||
* @return
|
||||
*/
|
||||
public static Connector[] getListeners(){
|
||||
if (_server != null){
|
||||
public static Connector[] getListeners() {
|
||||
if (_server != null) {
|
||||
return _server.getConnectors();
|
||||
}
|
||||
return new Connector[0];
|
||||
@ -187,20 +187,20 @@ public class I2PControlController{
|
||||
/**
|
||||
* Removes all listeners
|
||||
*/
|
||||
public static void clearListeners(){
|
||||
if (_server != null){
|
||||
for (Connector listen : getListeners()){
|
||||
public static void clearListeners() {
|
||||
if (_server != null) {
|
||||
for (Connector listen : getListeners()) {
|
||||
_server.removeConnector(listen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void stopServer()
|
||||
{
|
||||
try {
|
||||
if (_server != null){
|
||||
if (_server != null) {
|
||||
_server.stop();
|
||||
for (Connector listener : _server.getConnectors()){
|
||||
for (Connector listener : _server.getConnectors()) {
|
||||
listener.stop();
|
||||
}
|
||||
_server.destroy();
|
||||
@ -218,19 +218,19 @@ public class I2PControlController{
|
||||
}
|
||||
|
||||
stopServer();
|
||||
|
||||
|
||||
// Get and stop all running threads
|
||||
ThreadGroup threadgroup = Thread.currentThread().getThreadGroup();
|
||||
Thread[] threads = new Thread[threadgroup.activeCount()+3];
|
||||
Thread[] threads = new Thread[threadgroup.activeCount() + 3];
|
||||
threadgroup.enumerate(threads, true);
|
||||
for (Thread thread : threads){
|
||||
if (thread != null ){//&& thread.isAlive()){
|
||||
for (Thread thread : threads) {
|
||||
if (thread != null) {//&& thread.isAlive()){
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
for (Thread thread : threads){
|
||||
if (thread != null){
|
||||
for (Thread thread : threads) {
|
||||
if (thread != null) {
|
||||
System.out.println("Active thread: " + thread.getName());
|
||||
}
|
||||
}
|
||||
@ -239,7 +239,7 @@ public class I2PControlController{
|
||||
//Thread.currentThread().getThreadGroup().destroy();
|
||||
}
|
||||
|
||||
public static String getPluginDir(){
|
||||
public static String getPluginDir() {
|
||||
return _pluginDir;
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ public class RouterManager {
|
||||
|
||||
public static RouterContext getRouterContext() throws Exception {
|
||||
// If not running as a plugin from within I2P.
|
||||
if(context.isRouterContext()) {
|
||||
if (context.isRouterContext()) {
|
||||
return (RouterContext) context;
|
||||
}else {
|
||||
} else {
|
||||
throw new Exception("No RouterContext available!");
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public class AuthToken {
|
||||
private String id;
|
||||
private Date expiry;
|
||||
|
||||
public AuthToken(String password){
|
||||
public AuthToken(String password) {
|
||||
_secMan = SecurityManager.getInstance();
|
||||
String hash = _secMan.getPasswdHash(password);
|
||||
this.id = _secMan.getHash(hash + Calendar.getInstance().getTimeInMillis());
|
||||
@ -20,7 +20,7 @@ public class AuthToken {
|
||||
this.expiry = expiry.getTime();
|
||||
}
|
||||
|
||||
public String getId(){
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -28,23 +28,23 @@ public class AuthToken {
|
||||
* Checks whether the AuthToken has expired.
|
||||
* @return True if AuthToken hasn't expired. False in any other case.
|
||||
*/
|
||||
public boolean isValid(){
|
||||
public boolean isValid() {
|
||||
return Calendar.getInstance().getTime().before(expiry);
|
||||
}
|
||||
|
||||
public String getExpiryTime(){
|
||||
public String getExpiryTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat();
|
||||
sdf.applyPattern("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(expiry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
package net.i2p.i2pcontrol.security;
|
||||
|
||||
public class ExpiredAuthTokenException extends Exception{
|
||||
public class ExpiredAuthTokenException extends Exception {
|
||||
private static final long serialVersionUID = 2279019346592900289L;
|
||||
|
||||
private String expiryTime;
|
||||
|
||||
public ExpiredAuthTokenException(String str, String expiryTime){
|
||||
public ExpiredAuthTokenException(String str, String expiryTime) {
|
||||
super(str);
|
||||
this.expiryTime = expiryTime;
|
||||
}
|
||||
|
||||
public String getExpirytime(){
|
||||
public String getExpirytime() {
|
||||
return expiryTime;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package net.i2p.i2pcontrol.security;
|
||||
|
||||
public class InvalidAuthTokenException extends Exception{
|
||||
public class InvalidAuthTokenException extends Exception {
|
||||
private static final long serialVersionUID = 7605321329341235577L;
|
||||
|
||||
public InvalidAuthTokenException(String str){
|
||||
public InvalidAuthTokenException(String str) {
|
||||
super(str);
|
||||
}
|
||||
}
|
||||
|
@ -10,14 +10,14 @@ import java.security.cert.X509Certificate;
|
||||
public class KeyStoreProvider {
|
||||
public static final String DEFAULT_CERTIFICATE_ALGORITHM_STRING = "RSA";
|
||||
public static final int DEFAULT_CERTIFICATE_KEY_LENGTH = 4096;
|
||||
public static final int DEFAULT_CERTIFICATE_VALIDITY = 365*10;
|
||||
public static final int DEFAULT_CERTIFICATE_VALIDITY = 365 * 10;
|
||||
public final static String DEFAULT_CERTIFICATE_DOMAIN = "net.i2p.i2pcontrol";
|
||||
public final static String DEFAULT_CERTIFICATE_ALIAS = "I2PControl CA";
|
||||
public static final String DEFAULT_KEYSTORE_NAME = "key.store";
|
||||
public static final String DEFAULT_KEYSTORE_PASSWORD = "nut'nfancy";
|
||||
private static KeyStore _keystore = null;
|
||||
|
||||
|
||||
|
||||
public static void initialize() {
|
||||
KeyStoreUtil.createKeys(new File(getKeyStoreLocation()),
|
||||
DEFAULT_KEYSTORE_PASSWORD,
|
||||
@ -30,8 +30,8 @@ public class KeyStoreProvider {
|
||||
DEFAULT_KEYSTORE_PASSWORD);
|
||||
}
|
||||
|
||||
public static X509Certificate readCert(KeyStore ks, String certAlias, String password){
|
||||
try{
|
||||
public static X509Certificate readCert(KeyStore ks, String certAlias, String password) {
|
||||
try {
|
||||
X509Certificate cert = (X509Certificate) ks.getCertificate(certAlias);
|
||||
|
||||
if (cert == null) {
|
||||
@ -45,13 +45,13 @@ public class KeyStoreProvider {
|
||||
System.err.println("Failed to verify caCert certificate against caCert");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (KeyStoreException e){
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static X509Certificate readCert(File keyStoreFile, String certAlias, String password){
|
||||
public static X509Certificate readCert(File keyStoreFile, String certAlias, String password) {
|
||||
try {
|
||||
KeyStore ks = getDefaultKeyStore();
|
||||
ks.load(new FileInputStream(keyStoreFile), password.toCharArray());
|
||||
@ -68,7 +68,7 @@ public class KeyStoreProvider {
|
||||
System.err.println("Failed to verify caCert certificate against caCert");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IOException e){
|
||||
} catch (IOException e) {
|
||||
System.err.println("Couldn't read keystore from: " + keyStoreFile.toString());
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
@ -82,7 +82,7 @@ public class KeyStoreProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PrivateKey readPrivateKey(KeyStore ks, String alias, String password){
|
||||
public static PrivateKey readPrivateKey(KeyStore ks, String alias, String password) {
|
||||
try {
|
||||
// load the key entry from the keystore
|
||||
Key key = ks.getKey(alias, password.toCharArray());
|
||||
@ -93,17 +93,17 @@ public class KeyStoreProvider {
|
||||
|
||||
PrivateKey privKey = (PrivateKey) key;
|
||||
return privKey;
|
||||
} catch (UnrecoverableKeyException e){
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e){
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyStoreException e){
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PrivateKey readPrivateKey(String alias, File keyStoreFile, String keyStorePassword, String keyPassword){
|
||||
public static PrivateKey readPrivateKey(String alias, File keyStoreFile, String keyStorePassword, String keyPassword) {
|
||||
try {
|
||||
KeyStore ks = getDefaultKeyStore();
|
||||
ks.load(new FileInputStream(keyStoreFile), keyStorePassword.toCharArray());
|
||||
@ -121,13 +121,13 @@ public class KeyStoreProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static KeyStore writeCACertToKeyStore(KeyStore keyStore, String keyPassword, String alias, PrivateKey caPrivKey, X509Certificate caCert){
|
||||
public static KeyStore writeCACertToKeyStore(KeyStore keyStore, String keyPassword, String alias, PrivateKey caPrivKey, X509Certificate caCert) {
|
||||
try {
|
||||
X509Certificate[] chain = new X509Certificate[1];
|
||||
chain[0] = caCert;
|
||||
|
||||
keyStore.setKeyEntry(alias, caPrivKey, keyPassword.toCharArray(), chain);
|
||||
File keyStoreFile = new File(I2PControlController.getPluginDir()+File.separator+DEFAULT_KEYSTORE_NAME);
|
||||
File keyStoreFile = new File(I2PControlController.getPluginDir() + File.separator + DEFAULT_KEYSTORE_NAME);
|
||||
keyStore.store(new FileOutputStream(keyStoreFile), DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
return keyStore;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
@ -144,27 +144,27 @@ public class KeyStoreProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static synchronized KeyStore getDefaultKeyStore(){
|
||||
if (_keystore == null){
|
||||
public static synchronized KeyStore getDefaultKeyStore() {
|
||||
if (_keystore == null) {
|
||||
File keyStoreFile = new File(getKeyStoreLocation());
|
||||
|
||||
try {
|
||||
_keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
if (keyStoreFile.exists()){
|
||||
if (keyStoreFile.exists()) {
|
||||
InputStream is = new FileInputStream(keyStoreFile);
|
||||
_keystore.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
return _keystore;
|
||||
}
|
||||
|
||||
|
||||
initialize();
|
||||
_keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
if (keyStoreFile.exists()){
|
||||
if (keyStoreFile.exists()) {
|
||||
InputStream is = new FileInputStream(keyStoreFile);
|
||||
_keystore.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
return _keystore;
|
||||
} else {
|
||||
throw new IOException("KeyStore file " + keyStoreFile.getAbsolutePath() + " wasn't readable");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore. Not an issue. Let's just create a new keystore instead.
|
||||
}
|
||||
@ -174,8 +174,8 @@ public class KeyStoreProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getKeyStoreLocation(){
|
||||
File keyStoreFile = new File(I2PControlController.getPluginDir()+File.separator+DEFAULT_KEYSTORE_NAME);
|
||||
public static String getKeyStoreLocation() {
|
||||
File keyStoreFile = new File(I2PControlController.getPluginDir() + File.separator + DEFAULT_KEYSTORE_NAME);
|
||||
return keyStoreFile.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
@ -38,48 +38,48 @@ public class SecurityManager {
|
||||
private final static String SSL_PROVIDER = "SunJSSE";
|
||||
private final static String DEFAULT_AUTH_BCRYPT_SALT = "$2a$11$5aOLx2x/8i4fNaitoCSSWu";
|
||||
private final static String DEFAULT_AUTH_PASSWORD = "$2a$11$5aOLx2x/8i4fNaitoCSSWuut2wEl3Hupuca8DCT.NXzvH9fq1pBU.";
|
||||
private HashMap<String,AuthToken> authTokens;
|
||||
private HashMap<String, AuthToken> authTokens;
|
||||
private Timer timer;
|
||||
private String[] SSL_CIPHER_SUITES;
|
||||
private KeyStore _ks;
|
||||
private Log _log;
|
||||
private static SecurityManager _securityManager;
|
||||
|
||||
public static SecurityManager getInstance(){
|
||||
if (_securityManager == null){
|
||||
public static SecurityManager getInstance() {
|
||||
if (_securityManager == null) {
|
||||
_securityManager = new SecurityManager();
|
||||
}
|
||||
return _securityManager;
|
||||
}
|
||||
|
||||
private SecurityManager(){
|
||||
private SecurityManager() {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(SecurityManager.class);
|
||||
authTokens = new HashMap<String,AuthToken>();
|
||||
authTokens = new HashMap<String, AuthToken>();
|
||||
|
||||
timer = new Timer("SecurityManager Timer Sweeper ");
|
||||
// Start running periodic task after 20 minutes, run periodically every 10th minute.
|
||||
timer.scheduleAtFixedRate(new Sweeper(), 1000*60*20, 1000*60*10);
|
||||
timer.scheduleAtFixedRate(new Sweeper(), 1000 * 60 * 20, 1000 * 60 * 10);
|
||||
|
||||
// Get supported SSL cipher suites.
|
||||
SocketFactory SSLF = SSLSocketFactory.getDefault();
|
||||
try{
|
||||
SSL_CIPHER_SUITES = ((SSLSocket)SSLF.createSocket()).getSupportedCipherSuites();
|
||||
} catch (Exception e){
|
||||
try {
|
||||
SSL_CIPHER_SUITES = ((SSLSocket)SSLF.createSocket()).getSupportedCipherSuites();
|
||||
} catch (Exception e) {
|
||||
_log.log(Log.CRIT, "Unable to create SSLSocket used for fetching supported ssl cipher suites.", e);
|
||||
}
|
||||
|
||||
_ks = KeyStoreProvider.getDefaultKeyStore();
|
||||
}
|
||||
|
||||
public String[] getSupprtedSSLCipherSuites(){
|
||||
public String[] getSupprtedSSLCipherSuites() {
|
||||
return SSL_CIPHER_SUITES;
|
||||
}
|
||||
|
||||
public String getSecurityProvider(){
|
||||
public String getSecurityProvider() {
|
||||
return SSL_PROVIDER;
|
||||
}
|
||||
|
||||
public void stopTimedEvents(){
|
||||
public void stopTimedEvents() {
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
@ -87,10 +87,10 @@ public class SecurityManager {
|
||||
* Return the X509Certificate of the server as a Base64 encoded string.
|
||||
* @return base64 encode of X509Certificate
|
||||
*/
|
||||
public String getBase64Cert(){
|
||||
public String getBase64Cert() {
|
||||
X509Certificate caCert = KeyStoreProvider.readCert(_ks,
|
||||
KeyStoreProvider.DEFAULT_CERTIFICATE_ALIAS,
|
||||
KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
|
||||
KeyStoreProvider.DEFAULT_CERTIFICATE_ALIAS,
|
||||
KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
|
||||
return getBase64FromCert(caCert);
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ public class SecurityManager {
|
||||
* @param cert
|
||||
* @return base64 encode of X509Certificate
|
||||
*/
|
||||
private static String getBase64FromCert(X509Certificate cert){
|
||||
private static String getBase64FromCert(X509Certificate cert) {
|
||||
try {
|
||||
return Base64.encode(cert.getEncoded());
|
||||
} catch (CertificateEncodingException e) {
|
||||
@ -115,7 +115,7 @@ public class SecurityManager {
|
||||
* @param pwd
|
||||
* @return BCrypt hash of salt and input string
|
||||
*/
|
||||
public String getPasswdHash(String pwd){
|
||||
public String getPasswdHash(String pwd) {
|
||||
return BCrypt.hashpw(pwd, ConfigurationManager.getInstance().getConf("auth.salt", DEFAULT_AUTH_BCRYPT_SALT));
|
||||
}
|
||||
|
||||
@ -135,11 +135,11 @@ public class SecurityManager {
|
||||
/**
|
||||
* Add a Authentication Token if the provided password is valid.
|
||||
* The token will be valid for one day.
|
||||
* @return Returns AuthToken if password is valid. If password is invalid null will be returned.
|
||||
* @return Returns AuthToken if password is valid. If password is invalid null will be returned.
|
||||
*/
|
||||
public AuthToken validatePasswd(String pwd){
|
||||
public AuthToken validatePasswd(String pwd) {
|
||||
String storedPass = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
|
||||
if (getPasswdHash(pwd).equals(storedPass)){
|
||||
if (getPasswdHash(pwd).equals(storedPass)) {
|
||||
AuthToken token = new AuthToken(pwd);
|
||||
synchronized (authTokens) {
|
||||
authTokens.put(token.getId(), token);
|
||||
@ -155,11 +155,11 @@ public class SecurityManager {
|
||||
* @param newPasswd
|
||||
* @return Returns true if a new password was set.
|
||||
*/
|
||||
public boolean setPasswd(String newPasswd){
|
||||
public boolean setPasswd(String newPasswd) {
|
||||
String newHash = getPasswdHash(newPasswd);
|
||||
String oldHash = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
|
||||
|
||||
if (!newHash.equals(oldHash)){
|
||||
if (!newHash.equals(oldHash)) {
|
||||
ConfigurationManager.getInstance().setConf("auth.password", newHash);
|
||||
synchronized (authTokens) {
|
||||
authTokens.clear();
|
||||
@ -177,9 +177,9 @@ public class SecurityManager {
|
||||
*/
|
||||
public void verifyToken(String tokenID) throws InvalidAuthTokenException, ExpiredAuthTokenException {
|
||||
AuthToken token = authTokens.get(tokenID);
|
||||
if (token == null){
|
||||
if (token == null) {
|
||||
throw new InvalidAuthTokenException("AuthToken with ID: " + tokenID + " couldn't be found.");
|
||||
} else if (!token.isValid()){
|
||||
} else if (!token.isValid()) {
|
||||
synchronized (authTokens) {
|
||||
authTokens.remove(token.getId());
|
||||
}
|
||||
@ -194,19 +194,19 @@ public class SecurityManager {
|
||||
* @author hottuna
|
||||
*
|
||||
*/
|
||||
private class Sweeper extends TimerTask{
|
||||
private class Sweeper extends TimerTask {
|
||||
@Override
|
||||
public void run(){
|
||||
public void run() {
|
||||
_log.debug("Starting cleanup job..");
|
||||
ArrayList<String> arr = new ArrayList<String>();
|
||||
for (Map.Entry<String,AuthToken> e : authTokens.entrySet()){
|
||||
for (Map.Entry<String, AuthToken> e : authTokens.entrySet()) {
|
||||
AuthToken token = e.getValue();
|
||||
if (!token.isValid()){
|
||||
if (!token.isValid()) {
|
||||
arr.add(e.getKey());
|
||||
}
|
||||
}
|
||||
synchronized (authTokens) {
|
||||
for (String s : arr){
|
||||
for (String s : arr) {
|
||||
authTokens.remove(s);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,176 +23,176 @@
|
||||
// * @version 0.2
|
||||
// */
|
||||
//public class TestBCrypt extends TestCase {
|
||||
// String test_vectors[][] = {
|
||||
// { "",
|
||||
// "$2a$06$DCq7YPn5Rq63x1Lad4cll.",
|
||||
// "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." },
|
||||
// { "",
|
||||
// "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.",
|
||||
// "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye" },
|
||||
// { "",
|
||||
// "$2a$10$k1wbIrmNyFAPwPVPSVa/ze",
|
||||
// "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW" },
|
||||
// { "",
|
||||
// "$2a$12$k42ZFHFWqBp3vWli.nIn8u",
|
||||
// "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO" },
|
||||
// { "a",
|
||||
// "$2a$06$m0CrhHm10qJ3lXRY.5zDGO",
|
||||
// "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe" },
|
||||
// { "a",
|
||||
// "$2a$08$cfcvVd2aQ8CMvoMpP2EBfe",
|
||||
// "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V." },
|
||||
// { "a",
|
||||
// "$2a$10$k87L/MF28Q673VKh8/cPi.",
|
||||
// "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u" },
|
||||
// { "a",
|
||||
// "$2a$12$8NJH3LsPrANStV6XtBakCe",
|
||||
// "$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS" },
|
||||
// { "abc",
|
||||
// "$2a$06$If6bvum7DFjUnE9p2uDeDu",
|
||||
// "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i" },
|
||||
// { "abc",
|
||||
// "$2a$08$Ro0CUfOqk6cXEKf3dyaM7O",
|
||||
// "$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm" },
|
||||
// { "abc",
|
||||
// "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.",
|
||||
// "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi" },
|
||||
// { "abc",
|
||||
// "$2a$12$EXRkfkdmXn2gzds2SSitu.",
|
||||
// "$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q" },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$06$.rCVZVOThsIa97pEDOxvGu",
|
||||
// "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC" },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$08$aTsUwsyowQuzRrDqFflhge",
|
||||
// "$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz." },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$10$fVH8e28OQRj9tqiDXs1e1u",
|
||||
// "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq" },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$12$D4G5f18o7aMMfwasBL7Gpu",
|
||||
// "$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$06$fPIsBO8qRqkjj273rfaOI.",
|
||||
// "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$08$Eq2r4G/76Wv39MzSX262hu",
|
||||
// "$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$10$LgfYWkbzEvQ4JakH7rOvHe",
|
||||
// "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$12$WApznUOJfkEGSmYRfnkrPO",
|
||||
// "$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC" },
|
||||
// };
|
||||
// String test_vectors[][] = {
|
||||
// { "",
|
||||
// "$2a$06$DCq7YPn5Rq63x1Lad4cll.",
|
||||
// "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." },
|
||||
// { "",
|
||||
// "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.",
|
||||
// "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye" },
|
||||
// { "",
|
||||
// "$2a$10$k1wbIrmNyFAPwPVPSVa/ze",
|
||||
// "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW" },
|
||||
// { "",
|
||||
// "$2a$12$k42ZFHFWqBp3vWli.nIn8u",
|
||||
// "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO" },
|
||||
// { "a",
|
||||
// "$2a$06$m0CrhHm10qJ3lXRY.5zDGO",
|
||||
// "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe" },
|
||||
// { "a",
|
||||
// "$2a$08$cfcvVd2aQ8CMvoMpP2EBfe",
|
||||
// "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V." },
|
||||
// { "a",
|
||||
// "$2a$10$k87L/MF28Q673VKh8/cPi.",
|
||||
// "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u" },
|
||||
// { "a",
|
||||
// "$2a$12$8NJH3LsPrANStV6XtBakCe",
|
||||
// "$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS" },
|
||||
// { "abc",
|
||||
// "$2a$06$If6bvum7DFjUnE9p2uDeDu",
|
||||
// "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i" },
|
||||
// { "abc",
|
||||
// "$2a$08$Ro0CUfOqk6cXEKf3dyaM7O",
|
||||
// "$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm" },
|
||||
// { "abc",
|
||||
// "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.",
|
||||
// "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi" },
|
||||
// { "abc",
|
||||
// "$2a$12$EXRkfkdmXn2gzds2SSitu.",
|
||||
// "$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q" },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$06$.rCVZVOThsIa97pEDOxvGu",
|
||||
// "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC" },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$08$aTsUwsyowQuzRrDqFflhge",
|
||||
// "$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz." },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$10$fVH8e28OQRj9tqiDXs1e1u",
|
||||
// "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq" },
|
||||
// { "abcdefghijklmnopqrstuvwxyz",
|
||||
// "$2a$12$D4G5f18o7aMMfwasBL7Gpu",
|
||||
// "$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$06$fPIsBO8qRqkjj273rfaOI.",
|
||||
// "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$08$Eq2r4G/76Wv39MzSX262hu",
|
||||
// "$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$10$LgfYWkbzEvQ4JakH7rOvHe",
|
||||
// "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS" },
|
||||
// { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
|
||||
// "$2a$12$WApznUOJfkEGSmYRfnkrPO",
|
||||
// "$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC" },
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * Entry point for unit tests
|
||||
// * @param args unused
|
||||
// */
|
||||
// public static void main(String[] args) {
|
||||
// junit.textui.TestRunner.run(TestBCrypt.class);
|
||||
// }
|
||||
// /**
|
||||
// * Entry point for unit tests
|
||||
// * @param args unused
|
||||
// */
|
||||
// public static void main(String[] args) {
|
||||
// junit.textui.TestRunner.run(TestBCrypt.class);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test method for 'BCrypt.hashpw(String, String)'
|
||||
// */
|
||||
// public void testHashpw() {
|
||||
// System.out.print("BCrypt.hashpw(): ");
|
||||
// for (int i = 0; i < test_vectors.length; i++) {
|
||||
// String plain = test_vectors[i][0];
|
||||
// String salt = test_vectors[i][1];
|
||||
// String expected = test_vectors[i][2];
|
||||
// String hashed = BCrypt.hashpw(plain, salt);
|
||||
// assertEquals(hashed, expected);
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// /**
|
||||
// * Test method for 'BCrypt.hashpw(String, String)'
|
||||
// */
|
||||
// public void testHashpw() {
|
||||
// System.out.print("BCrypt.hashpw(): ");
|
||||
// for (int i = 0; i < test_vectors.length; i++) {
|
||||
// String plain = test_vectors[i][0];
|
||||
// String salt = test_vectors[i][1];
|
||||
// String expected = test_vectors[i][2];
|
||||
// String hashed = BCrypt.hashpw(plain, salt);
|
||||
// assertEquals(hashed, expected);
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test method for 'BCrypt.gensalt(int)'
|
||||
// */
|
||||
// public void testGensaltInt() {
|
||||
// System.out.print("BCrypt.gensalt(log_rounds):");
|
||||
// for (int i = 4; i <= 12; i++) {
|
||||
// System.out.print(" " + Integer.toString(i) + ":");
|
||||
// for (int j = 0; j < test_vectors.length; j += 4) {
|
||||
// String plain = test_vectors[j][0];
|
||||
// String salt = BCrypt.gensalt(i);
|
||||
// String hashed1 = BCrypt.hashpw(plain, salt);
|
||||
// String hashed2 = BCrypt.hashpw(plain, hashed1);
|
||||
// assertEquals(hashed1, hashed2);
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// /**
|
||||
// * Test method for 'BCrypt.gensalt(int)'
|
||||
// */
|
||||
// public void testGensaltInt() {
|
||||
// System.out.print("BCrypt.gensalt(log_rounds):");
|
||||
// for (int i = 4; i <= 12; i++) {
|
||||
// System.out.print(" " + Integer.toString(i) + ":");
|
||||
// for (int j = 0; j < test_vectors.length; j += 4) {
|
||||
// String plain = test_vectors[j][0];
|
||||
// String salt = BCrypt.gensalt(i);
|
||||
// String hashed1 = BCrypt.hashpw(plain, salt);
|
||||
// String hashed2 = BCrypt.hashpw(plain, hashed1);
|
||||
// assertEquals(hashed1, hashed2);
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test method for 'BCrypt.gensalt()'
|
||||
// */
|
||||
// public void testGensalt() {
|
||||
// System.out.print("BCrypt.gensalt(): ");
|
||||
// for (int i = 0; i < test_vectors.length; i += 4) {
|
||||
// String plain = test_vectors[i][0];
|
||||
// String salt = BCrypt.gensalt();
|
||||
// String hashed1 = BCrypt.hashpw(plain, salt);
|
||||
// String hashed2 = BCrypt.hashpw(plain, hashed1);
|
||||
// assertEquals(hashed1, hashed2);
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// /**
|
||||
// * Test method for 'BCrypt.gensalt()'
|
||||
// */
|
||||
// public void testGensalt() {
|
||||
// System.out.print("BCrypt.gensalt(): ");
|
||||
// for (int i = 0; i < test_vectors.length; i += 4) {
|
||||
// String plain = test_vectors[i][0];
|
||||
// String salt = BCrypt.gensalt();
|
||||
// String hashed1 = BCrypt.hashpw(plain, salt);
|
||||
// String hashed2 = BCrypt.hashpw(plain, hashed1);
|
||||
// assertEquals(hashed1, hashed2);
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test method for 'BCrypt.checkpw(String, String)'
|
||||
// * expecting success
|
||||
// */
|
||||
// public void testCheckpw_success() {
|
||||
// System.out.print("BCrypt.checkpw w/ good passwords: ");
|
||||
// for (int i = 0; i < test_vectors.length; i++) {
|
||||
// String plain = test_vectors[i][0];
|
||||
// String expected = test_vectors[i][2];
|
||||
// assertTrue(BCrypt.checkpw(plain, expected));
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// /**
|
||||
// * Test method for 'BCrypt.checkpw(String, String)'
|
||||
// * expecting success
|
||||
// */
|
||||
// public void testCheckpw_success() {
|
||||
// System.out.print("BCrypt.checkpw w/ good passwords: ");
|
||||
// for (int i = 0; i < test_vectors.length; i++) {
|
||||
// String plain = test_vectors[i][0];
|
||||
// String expected = test_vectors[i][2];
|
||||
// assertTrue(BCrypt.checkpw(plain, expected));
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test method for 'BCrypt.checkpw(String, String)'
|
||||
// * expecting failure
|
||||
// */
|
||||
// public void testCheckpw_failure() {
|
||||
// System.out.print("BCrypt.checkpw w/ bad passwords: ");
|
||||
// for (int i = 0; i < test_vectors.length; i++) {
|
||||
// int broken_index = (i + 4) % test_vectors.length;
|
||||
// String plain = test_vectors[i][0];
|
||||
// String expected = test_vectors[broken_index][2];
|
||||
// assertFalse(BCrypt.checkpw(plain, expected));
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
// /**
|
||||
// * Test method for 'BCrypt.checkpw(String, String)'
|
||||
// * expecting failure
|
||||
// */
|
||||
// public void testCheckpw_failure() {
|
||||
// System.out.print("BCrypt.checkpw w/ bad passwords: ");
|
||||
// for (int i = 0; i < test_vectors.length; i++) {
|
||||
// int broken_index = (i + 4) % test_vectors.length;
|
||||
// String plain = test_vectors[i][0];
|
||||
// String expected = test_vectors[broken_index][2];
|
||||
// assertFalse(BCrypt.checkpw(plain, expected));
|
||||
// System.out.print(".");
|
||||
// }
|
||||
// System.out.println("");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test for correct hashing of non-US-ASCII passwords
|
||||
// */
|
||||
// public void testInternationalChars() {
|
||||
// System.out.print("BCrypt.hashpw w/ international chars: ");
|
||||
// String pw1 = "ππππππππ";
|
||||
// String pw2 = "????????";
|
||||
// /**
|
||||
// * Test for correct hashing of non-US-ASCII passwords
|
||||
// */
|
||||
// public void testInternationalChars() {
|
||||
// System.out.print("BCrypt.hashpw w/ international chars: ");
|
||||
// String pw1 = "ππππππππ";
|
||||
// String pw2 = "????????";
|
||||
//
|
||||
// String h1 = BCrypt.hashpw(pw1, BCrypt.gensalt());
|
||||
// assertFalse(BCrypt.checkpw(pw2, h1));
|
||||
// System.out.print(".");
|
||||
// String h1 = BCrypt.hashpw(pw1, BCrypt.gensalt());
|
||||
// assertFalse(BCrypt.checkpw(pw2, h1));
|
||||
// System.out.print(".");
|
||||
//
|
||||
// String h2 = BCrypt.hashpw(pw2, BCrypt.gensalt());
|
||||
// assertFalse(BCrypt.checkpw(pw1, h2));
|
||||
// System.out.print(".");
|
||||
// System.out.println("");
|
||||
// }
|
||||
// String h2 = BCrypt.hashpw(pw2, BCrypt.gensalt());
|
||||
// assertFalse(BCrypt.checkpw(pw1, h2));
|
||||
// System.out.print(".");
|
||||
// System.out.println("");
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
|
@ -34,7 +34,7 @@ import java.io.*;
|
||||
/**
|
||||
* Provide an JSON-RPC 2.0 API for remote controlling of I2P
|
||||
*/
|
||||
public class JSONRPC2Servlet extends HttpServlet{
|
||||
public class JSONRPC2Servlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = -45075606818515212L;
|
||||
private static final int BUFFER_LENGTH = 2048;
|
||||
@ -44,7 +44,7 @@ public class JSONRPC2Servlet extends HttpServlet{
|
||||
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
public void init() {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class);
|
||||
readBuffer = new char[BUFFER_LENGTH];
|
||||
|
||||
@ -60,7 +60,7 @@ public class JSONRPC2Servlet extends HttpServlet{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException{
|
||||
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
|
||||
httpServletResponse.setContentType("text/html");
|
||||
PrintWriter out = httpServletResponse.getWriter();
|
||||
out.println("Nothing to see here");
|
||||
@ -68,7 +68,7 @@ public class JSONRPC2Servlet extends HttpServlet{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException{
|
||||
protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
|
||||
String req = getRequest(httpServletRequest.getInputStream());
|
||||
httpServletResponse.setContentType("application/json");
|
||||
PrintWriter out = httpServletResponse.getWriter();
|
||||
@ -95,10 +95,10 @@ public class JSONRPC2Servlet extends HttpServlet{
|
||||
}
|
||||
}
|
||||
|
||||
private String getRequest(ServletInputStream sis) throws IOException{
|
||||
private String getRequest(ServletInputStream sis) throws IOException {
|
||||
Writer writer = new StringWriter();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(sis,"UTF-8"));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(sis, "UTF-8"));
|
||||
int n;
|
||||
while ((n = reader.read(readBuffer)) != -1) {
|
||||
writer.write(readBuffer, 0, n);
|
||||
|
@ -33,9 +33,9 @@ public class ConfigurationManager {
|
||||
* Should only be set before getInstance is first called.
|
||||
* @param dir
|
||||
*/
|
||||
public static void setConfDir(String dir){
|
||||
if (!configLocationModified){
|
||||
if (dir.endsWith("/")){
|
||||
public static void setConfDir(String dir) {
|
||||
if (!configLocationModified) {
|
||||
if (dir.endsWith("/")) {
|
||||
configLocation = dir + configLocation;
|
||||
} else {
|
||||
configLocation = dir + "/" + configLocation;
|
||||
@ -48,7 +48,7 @@ public class ConfigurationManager {
|
||||
}
|
||||
|
||||
public synchronized static ConfigurationManager getInstance() {
|
||||
if(instance == null) {
|
||||
if (instance == null) {
|
||||
instance = new ConfigurationManager();
|
||||
}
|
||||
return instance;
|
||||
@ -60,9 +60,9 @@ public class ConfigurationManager {
|
||||
* @param settingNames Command line settingNameuments to the application
|
||||
*/
|
||||
public void loadsettingNameuments(String[] settingNames) {
|
||||
for(int i=0; i<settingNames.length; i++) {
|
||||
for (int i = 0; i < settingNames.length; i++) {
|
||||
String settingName = settingNames[i];
|
||||
if(settingName.startsWith("--")) {
|
||||
if (settingName.startsWith("--")) {
|
||||
parseConfigStr(settingName.substring(2));
|
||||
}
|
||||
}
|
||||
@ -71,11 +71,11 @@ public class ConfigurationManager {
|
||||
/**
|
||||
* Reads configuration from file itoopie.conf, every line is parsed as key=value.
|
||||
*/
|
||||
public static void readConfFile(){
|
||||
public static void readConfFile() {
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new FileReader(configLocation));
|
||||
String input;
|
||||
while ((input = br.readLine()) != null){
|
||||
while ((input = br.readLine()) != null) {
|
||||
parseConfigStr(input);
|
||||
}
|
||||
br.close();
|
||||
@ -89,20 +89,20 @@ public class ConfigurationManager {
|
||||
/**
|
||||
* Write configuration into default config file.
|
||||
*/
|
||||
public static void writeConfFile(){
|
||||
TreeMap<String,String> tree = new TreeMap<String,String>();
|
||||
for (Entry<String,String> e : stringConfigurations.entrySet()){
|
||||
public static void writeConfFile() {
|
||||
TreeMap<String, String> tree = new TreeMap<String, String>();
|
||||
for (Entry<String, String> e : stringConfigurations.entrySet()) {
|
||||
tree.put(e.getKey(), e.getValue());
|
||||
}
|
||||
for (Entry<String,Integer> e : integerConfigurations.entrySet()){
|
||||
for (Entry<String, Integer> e : integerConfigurations.entrySet()) {
|
||||
tree.put(e.getKey(), e.getValue().toString());
|
||||
}
|
||||
for (Entry<String,Boolean> e : booleanConfigurations.entrySet()){
|
||||
for (Entry<String, Boolean> e : booleanConfigurations.entrySet()) {
|
||||
tree.put(e.getKey(), e.getValue().toString());
|
||||
}
|
||||
try {
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(configLocation));
|
||||
for (Entry<String,String> e : tree.entrySet()){
|
||||
for (Entry<String, String> e : tree.entrySet()) {
|
||||
bw.write(e.getKey() + "=" + e.getValue() + "\r\n");
|
||||
}
|
||||
bw.close();
|
||||
@ -112,26 +112,26 @@ public class ConfigurationManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to parse the given line as 'key=value',
|
||||
* where value will (in order) be parsed as integer/boolean/string.
|
||||
* Try to parse the given line as 'key=value',
|
||||
* where value will (in order) be parsed as integer/boolean/string.
|
||||
* @param str
|
||||
*/
|
||||
public static void parseConfigStr(String str){
|
||||
public static void parseConfigStr(String str) {
|
||||
int eqIndex = str.indexOf('=');
|
||||
if (eqIndex != -1){
|
||||
if (eqIndex != -1) {
|
||||
String key = str.substring(0, eqIndex).trim().toLowerCase();
|
||||
String value = str.substring(eqIndex+1, str.length()).trim();
|
||||
String value = str.substring(eqIndex + 1, str.length()).trim();
|
||||
//Try parse as integer.
|
||||
try {
|
||||
int i = Integer.parseInt(value);
|
||||
integerConfigurations.put(key, i);
|
||||
return;
|
||||
} catch (NumberFormatException e){}
|
||||
} catch (NumberFormatException e) {}
|
||||
//Check if value is a bool
|
||||
if (value.toLowerCase().equals("true")){
|
||||
if (value.toLowerCase().equals("true")) {
|
||||
booleanConfigurations.put(key, Boolean.TRUE);
|
||||
return;
|
||||
} else if (value.toLowerCase().equals("false")){
|
||||
} else if (value.toLowerCase().equals("false")) {
|
||||
booleanConfigurations.put(key, Boolean.FALSE);
|
||||
return;
|
||||
}
|
||||
@ -148,7 +148,7 @@ public class ConfigurationManager {
|
||||
*/
|
||||
public boolean getConf(String settingName, boolean defaultValue) {
|
||||
Boolean value = booleanConfigurations.get(settingName);
|
||||
if(value != null) {
|
||||
if (value != null) {
|
||||
return value;
|
||||
} else {
|
||||
booleanConfigurations.put(settingName, defaultValue);
|
||||
@ -165,7 +165,7 @@ public class ConfigurationManager {
|
||||
*/
|
||||
public int getConf(String settingName, int defaultValue) {
|
||||
Integer value = integerConfigurations.get(settingName);
|
||||
if(value != null) {
|
||||
if (value != null) {
|
||||
return value;
|
||||
} else {
|
||||
integerConfigurations.put(settingName, defaultValue);
|
||||
@ -181,7 +181,7 @@ public class ConfigurationManager {
|
||||
*/
|
||||
public String getConf(String settingName, String defaultValue) {
|
||||
String value = stringConfigurations.get(settingName);
|
||||
if(value != null) {
|
||||
if (value != null) {
|
||||
return value;
|
||||
} else {
|
||||
stringConfigurations.put(settingName, defaultValue);
|
||||
@ -194,7 +194,7 @@ public class ConfigurationManager {
|
||||
* @param settingName
|
||||
* @param nbr
|
||||
*/
|
||||
public void setConf(String settingName, int nbr){
|
||||
public void setConf(String settingName, int nbr) {
|
||||
integerConfigurations.put(settingName, nbr);
|
||||
}
|
||||
|
||||
@ -203,7 +203,7 @@ public class ConfigurationManager {
|
||||
* @param settingName
|
||||
* @param string
|
||||
*/
|
||||
public void setConf(String settingName, String str){
|
||||
public void setConf(String settingName, String str) {
|
||||
stringConfigurations.put(settingName, str);
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ public class ConfigurationManager {
|
||||
* @param settingName
|
||||
* @param boolean
|
||||
*/
|
||||
public void setConf(String settingName, boolean bool){
|
||||
public void setConf(String settingName, boolean bool) {
|
||||
booleanConfigurations.put(settingName, bool);
|
||||
}
|
||||
}
|
||||
|
@ -13,17 +13,15 @@ import net.i2p.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
public class AdvancedSettingsHandler implements RequestHandler {
|
||||
|
||||
|
||||
private static RouterContext _context;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(AdvancedSettingsHandler.class);
|
||||
|
||||
static{
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
@ -34,122 +32,122 @@ public class AdvancedSettingsHandler implements RequestHandler {
|
||||
private String[] requiredArgs = {};
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[]{"AdvancedSettings"};
|
||||
return new String[] {"AdvancedSettings"};
|
||||
}
|
||||
|
||||
// Processes the requests
|
||||
@SuppressWarnings("unchecked")
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("AdvancedSettings")) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
|
||||
if (err != null) {
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
Map outParams = new HashMap();
|
||||
|
||||
if (inParams.containsKey("setAll")) {
|
||||
Object obj = inParams.get("setAll");
|
||||
if (!(obj instanceof Map)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Value of \"setAll\" is not a Map");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map objMap = (Map) inParams.get("setAll");
|
||||
if (objMap.size() > 0)
|
||||
{
|
||||
if (!(objMap.keySet().toArray()[0] instanceof String) &&
|
||||
!(objMap.values().toArray()[0] instanceof String)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Map of settings does not contain String keys and values");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
if (!checkTypes(objMap)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Some of the supplied values are not strings");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
Map<String, String> allSettings = (Map<String, String>) objMap;
|
||||
boolean success = setAdvancedSettings(allSettings, true);
|
||||
if (!success) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Failed to save new config");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
} else {
|
||||
// Empty list of settings submitted
|
||||
boolean success = setAdvancedSettings(null, true);
|
||||
if (!success) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Failed to save new config");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("getAll")) {
|
||||
outParams.put("getAll", getAdvancedSettings());
|
||||
}
|
||||
|
||||
if (inParams.containsKey("set")) {
|
||||
Object obj = inParams.get("set");
|
||||
if (!(obj instanceof Map)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Value of \"set\" is not a Map");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
Map objMap = (Map) inParams.get("set");
|
||||
if (objMap.size() > 0)
|
||||
{
|
||||
if (!(objMap.keySet().toArray()[0] instanceof String) &&
|
||||
!(objMap.values().toArray()[0] instanceof String)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Map of settings does not contain String keys and values");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
if (!checkTypes(objMap)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Some of the supplied values are not strings");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
Object obj = inParams.get("setAll");
|
||||
if (!(obj instanceof Map)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Value of \"setAll\" is not a Map");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
Map<String, String> allSettings = (Map<String, String>) objMap;
|
||||
boolean success = setAdvancedSettings(allSettings, false);
|
||||
if (!success) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Failed to save new config");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
} else {
|
||||
// Empty list of settings submitted
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Map of settings does not contain any entries");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map objMap = (Map) inParams.get("setAll");
|
||||
if (objMap.size() > 0)
|
||||
{
|
||||
if (!(objMap.keySet().toArray()[0] instanceof String) &&
|
||||
!(objMap.values().toArray()[0] instanceof String)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Map of settings does not contain String keys and values");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
if (!checkTypes(objMap)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Some of the supplied values are not strings");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
Map<String, String> allSettings = (Map<String, String>) objMap;
|
||||
boolean success = setAdvancedSettings(allSettings, true);
|
||||
if (!success) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Failed to save new config");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
} else {
|
||||
// Empty list of settings submitted
|
||||
boolean success = setAdvancedSettings(null, true);
|
||||
if (!success) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Failed to save new config");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (inParams.containsKey("getAll")) {
|
||||
outParams.put("getAll", getAdvancedSettings());
|
||||
}
|
||||
|
||||
if (inParams.containsKey("set")) {
|
||||
Object obj = inParams.get("set");
|
||||
if (!(obj instanceof Map)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Value of \"set\" is not a Map");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
Map objMap = (Map) inParams.get("set");
|
||||
if (objMap.size() > 0)
|
||||
{
|
||||
if (!(objMap.keySet().toArray()[0] instanceof String) &&
|
||||
!(objMap.values().toArray()[0] instanceof String)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Map of settings does not contain String keys and values");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
if (!checkTypes(objMap)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Some of the supplied values are not strings");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
Map<String, String> allSettings = (Map<String, String>) objMap;
|
||||
boolean success = setAdvancedSettings(allSettings, false);
|
||||
if (!success) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"Failed to save new config");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
|
||||
} else {
|
||||
// Empty list of settings submitted
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Map of settings does not contain any entries");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("get")) {
|
||||
Object obj = inParams.get("get");
|
||||
if(!(obj instanceof String)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Value of \"get\" is not a string");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
String getStr = (String) obj;
|
||||
String getVal = getAdvancedSetting(getStr);
|
||||
Map<String, String> outMap = new HashMap<String, String>();
|
||||
outMap.put(getStr, getVal);
|
||||
outParams.put("get", outMap);
|
||||
Object obj = inParams.get("get");
|
||||
if (!(obj instanceof String)) {
|
||||
JSONRPC2Error rpcErr = new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"Value of \"get\" is not a string");
|
||||
return new JSONRPC2Response(rpcErr, req.getID());
|
||||
}
|
||||
String getStr = (String) obj;
|
||||
String getVal = getAdvancedSetting(getStr);
|
||||
Map<String, String> outMap = new HashMap<String, String>();
|
||||
outMap.put(getStr, getVal);
|
||||
outParams.put("get", outMap);
|
||||
}
|
||||
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
@ -158,36 +156,36 @@ public class AdvancedSettingsHandler implements RequestHandler {
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getAdvancedSetting(String key) {
|
||||
return _context.router().getConfigSetting(key);
|
||||
return _context.router().getConfigSetting(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private Map<String, String> getAdvancedSettings() {
|
||||
return _context.router().getConfigMap();
|
||||
}
|
||||
|
||||
|
||||
private boolean checkTypes(Map<String, Object> newSettings) {
|
||||
for (String key : newSettings.keySet()) {
|
||||
if (!(newSettings.get(key) instanceof String)) {
|
||||
return false;
|
||||
}
|
||||
if (!(newSettings.get(key) instanceof String)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private boolean setAdvancedSettings(Map<String, String> newSettings, boolean clearConfig) {
|
||||
Set<String> unsetKeys = null;
|
||||
|
||||
if(clearConfig) {
|
||||
unsetKeys = new HashSet<String>(_context.router().getConfigSettings());
|
||||
|
||||
for (String key : newSettings.keySet()) {
|
||||
unsetKeys.remove(key);
|
||||
}
|
||||
}
|
||||
Set<String> unsetKeys = null;
|
||||
|
||||
if (clearConfig) {
|
||||
unsetKeys = new HashSet<String>(_context.router().getConfigSettings());
|
||||
|
||||
for (String key : newSettings.keySet()) {
|
||||
unsetKeys.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
return _context.router().saveConfig(newSettings, unsetKeys);
|
||||
}
|
||||
|
@ -31,10 +31,10 @@ import java.util.Map;
|
||||
|
||||
public class AuthenticateHandler implements RequestHandler {
|
||||
|
||||
private String[] requiredArgs = {"Password","API"};
|
||||
private String[] requiredArgs = {"Password", "API"};
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[]{"Authenticate"};
|
||||
return new String[] {"Authenticate"};
|
||||
}
|
||||
|
||||
// Processes the requests
|
||||
@ -51,7 +51,7 @@ public class AuthenticateHandler implements RequestHandler {
|
||||
// Try get an AuthToken
|
||||
|
||||
AuthToken token = SecurityManager.getInstance().validatePasswd(pwd);
|
||||
if (token == null){
|
||||
if (token == null) {
|
||||
return new JSONRPC2Response(JSONRPC2ExtendedError.INVALID_PASSWORD, req.getID());
|
||||
}
|
||||
|
||||
@ -74,23 +74,23 @@ public class AuthenticateHandler implements RequestHandler {
|
||||
/**
|
||||
* Validate the provided I2PControl API version against the ones supported by I2PControl.
|
||||
*/
|
||||
private static JSONRPC2Error validateAPIVersion(Object api){
|
||||
private static JSONRPC2Error validateAPIVersion(Object api) {
|
||||
|
||||
Integer apiVersion;
|
||||
try {
|
||||
apiVersion = ((Long) api).intValue();
|
||||
} catch (ClassCastException e){
|
||||
} catch (ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
return JSONRPC2ExtendedError.UNSPECIFIED_API_VERSION;
|
||||
}
|
||||
|
||||
if (!I2PControlVersion.SUPPORTED_API_VERSIONS.contains(apiVersion)){
|
||||
if (!I2PControlVersion.SUPPORTED_API_VERSIONS.contains(apiVersion)) {
|
||||
String supportedAPIVersions = "";
|
||||
for (Integer i : I2PControlVersion.SUPPORTED_API_VERSIONS){
|
||||
supportedAPIVersions += ", "+ i;
|
||||
for (Integer i : I2PControlVersion.SUPPORTED_API_VERSIONS) {
|
||||
supportedAPIVersions += ", " + i;
|
||||
}
|
||||
return new JSONRPC2Error(JSONRPC2ExtendedError.UNSUPPORTED_API_VERSION.getCode(),
|
||||
"The provided API version \'" + apiVersion + "\' is not supported. The supported versions are" + supportedAPIVersions+".");
|
||||
"The provided API version \'" + apiVersion + "\' is not supported. The supported versions are" + supportedAPIVersions + ".");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ public class EchoHandler implements RequestHandler {
|
||||
private String[] requiredArgs = {"Echo"};
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[]{"Echo"};
|
||||
return new String[] {"Echo"};
|
||||
}
|
||||
|
||||
// Processes the requests
|
||||
|
@ -34,7 +34,7 @@ public class GetRateHandler implements RequestHandler {
|
||||
private String[] requiredArgs = {"Stat", "Period"};
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[]{"GetRate"};
|
||||
return new String[] {"GetRate"};
|
||||
}
|
||||
|
||||
// Processes the requests
|
||||
@ -47,20 +47,20 @@ public class GetRateHandler implements RequestHandler {
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
|
||||
String input = (String) inParams.get("Stat");
|
||||
if (input == null){
|
||||
if (input == null) {
|
||||
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
|
||||
}
|
||||
long period;
|
||||
try{
|
||||
try {
|
||||
period = (Long) inParams.get("Period");
|
||||
} catch (NumberFormatException e){
|
||||
} catch (NumberFormatException e) {
|
||||
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
|
||||
}
|
||||
|
||||
RateStat rateStat = I2PAppContext.getGlobalContext().statManager().getRate(input);
|
||||
|
||||
// If RateStat or the requested period doesn't already exist, create them.
|
||||
if (rateStat == null || rateStat.getRate(period) == null){
|
||||
if (rateStat == null || rateStat.getRate(period) == null) {
|
||||
long[] tempArr = new long[1];
|
||||
tempArr[0] = period;
|
||||
I2PAppContext.getGlobalContext().statManager().createRequiredRateStat(input, "I2PControl", "I2PControl", tempArr);
|
||||
|
@ -43,7 +43,7 @@ public class I2PControlHandler implements RequestHandler {
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlHandler.class);
|
||||
private static final ConfigurationManager _conf = ConfigurationManager.getInstance();
|
||||
|
||||
static{
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
@ -53,30 +53,30 @@ public class I2PControlHandler implements RequestHandler {
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[]{"I2PControl"};
|
||||
return new String[] {"I2PControl"};
|
||||
}
|
||||
|
||||
// Processes the requests
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("I2PControl")) {
|
||||
return process(req);
|
||||
}else {
|
||||
} else {
|
||||
// Method name not supported
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private JSONRPC2Response process(JSONRPC2Request req){
|
||||
private JSONRPC2Response process(JSONRPC2Request req) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
if (_context == null){
|
||||
if (_context == null) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
}
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
Map outParams = new HashMap();
|
||||
@ -85,21 +85,21 @@ public class I2PControlHandler implements RequestHandler {
|
||||
boolean settingsSaved = false;
|
||||
String inParam;
|
||||
|
||||
if (inParams.containsKey("i2pcontrol.port")){
|
||||
if (inParams.containsKey("i2pcontrol.port")) {
|
||||
Integer oldPort = _conf.getConf("i2pcontrol.listen.port", 7650);
|
||||
if ((inParam = (String) inParams.get("i2pcontrol.port")) != null){
|
||||
if (oldPort == null || !inParam.equals(oldPort.toString())){
|
||||
if ((inParam = (String) inParams.get("i2pcontrol.port")) != null) {
|
||||
if (oldPort == null || !inParam.equals(oldPort.toString())) {
|
||||
Integer newPort;
|
||||
try {
|
||||
newPort = Integer.valueOf(inParam);
|
||||
if (newPort < 1 || newPort > 65535){
|
||||
if (newPort < 1 || newPort > 65535) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
} catch (NumberFormatException e){
|
||||
} catch (NumberFormatException e) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.port\" must be a string representing a number in the range 1-65535. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.port\" must be a string representing a number in the range 1-65535. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
}
|
||||
try {
|
||||
SslSocketConnector ssl = I2PControlController.buildSslListener(_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"), newPort);
|
||||
@ -118,24 +118,24 @@ public class I2PControlHandler implements RequestHandler {
|
||||
SslSocketConnector ssl = I2PControlController.buildSslListener(_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"), oldPort);
|
||||
I2PControlController.clearListeners();
|
||||
I2PControlController.replaceListener(ssl);
|
||||
} catch (Exception e2){
|
||||
_log.log(Log.CRIT, "Unable to resume server on previous listening port." );
|
||||
} catch (Exception e2) {
|
||||
_log.log(Log.CRIT, "Unable to resume server on previous listening port.");
|
||||
}
|
||||
_log.error("Client tried to set listen port to, " + newPort + " which isn't valid.", e);
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.port\" has been set to a port that is already in use, reverting. " +
|
||||
inParam + " is an already used port.\n"
|
||||
+ "Exception: " + e.toString()),
|
||||
req.getID());
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.port\" has been set to a port that is already in use, reverting. " +
|
||||
inParam + " is an already used port.\n"
|
||||
+ "Exception: " + e.toString()),
|
||||
req.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(inParams.containsKey("i2pcontrol.password")){
|
||||
if ((inParam = (String) inParams.get("i2pcontrol.password")) != null){
|
||||
if (SecurityManager.getInstance().setPasswd(inParam)){
|
||||
if (inParams.containsKey("i2pcontrol.password")) {
|
||||
if ((inParam = (String) inParams.get("i2pcontrol.password")) != null) {
|
||||
if (SecurityManager.getInstance().setPasswd(inParam)) {
|
||||
outParams.put("i2pcontrol.password", null);
|
||||
settingsSaved = true;
|
||||
}
|
||||
@ -143,20 +143,20 @@ public class I2PControlHandler implements RequestHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if(inParams.containsKey("i2pcontrol.address")){
|
||||
if (inParams.containsKey("i2pcontrol.address")) {
|
||||
String oldAddress = _conf.getConf("i2pcontrol.listen.address", "127.0.0.1");
|
||||
if ((inParam = (String) inParams.get("i2pcontrol.address")) != null){
|
||||
if ((oldAddress == null || !inParam.equals(oldAddress.toString()) &&
|
||||
(inParam.equals("0.0.0.0") || inParam.equals("127.0.0.1")))){
|
||||
if ((inParam = (String) inParams.get("i2pcontrol.address")) != null) {
|
||||
if ((oldAddress == null || !inParam.equals(oldAddress.toString()) &&
|
||||
(inParam.equals("0.0.0.0") || inParam.equals("127.0.0.1")))) {
|
||||
InetAddress[] newAddress;
|
||||
|
||||
try {
|
||||
newAddress = InetAddress.getAllByName(inParam);
|
||||
} catch (UnknownHostException e){
|
||||
} catch (UnknownHostException e) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.address\" must be a string representing a hostname or ipaddress. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.address\" must be a string representing a hostname or ipaddress. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
}
|
||||
try {
|
||||
SslSocketConnector ssl = I2PControlController.buildSslListener(inParam, _conf.getConf("i2pcontrol.listen.port", 7650));
|
||||
@ -173,13 +173,13 @@ public class I2PControlHandler implements RequestHandler {
|
||||
SslSocketConnector ssl = I2PControlController.buildSslListener(inParam, _conf.getConf("i2pcontrol.listen.port", 7650));
|
||||
I2PControlController.clearListeners();
|
||||
I2PControlController.replaceListener(ssl);
|
||||
} catch (Exception e2){
|
||||
_log.log(Log.CRIT, "Unable to resume server on previous listening ip." );
|
||||
} catch (Exception e2) {
|
||||
_log.log(Log.CRIT, "Unable to resume server on previous listening ip.");
|
||||
}
|
||||
_log.error("Client tried to set listen address to, " + newAddress.toString() + " which isn't valid.", e);
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.address\" has been set to an invalid address, reverting. "), req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2pcontrol.address\" has been set to an invalid address, reverting. "), req.getID());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -20,27 +20,27 @@ import org.json.simple.JSONObject;
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 error that occured during the processing of a
|
||||
/**
|
||||
* Represents a JSON-RPC 2.0 error that occured during the processing of a
|
||||
* request.
|
||||
*
|
||||
* <p>The protocol expects error objects to be structured like this:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code code} An integer that indicates the error type.
|
||||
* <li>{@code message} A string providing a short description of the
|
||||
* <li>{@code message} A string providing a short description of the
|
||||
* error. The message should be limited to a concise single sentence.
|
||||
* <li>{@code data} Additional information, which may be omitted. Its
|
||||
* <li>{@code data} Additional information, which may be omitted. Its
|
||||
* contents is entirely defined by the application.
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <p>Note that the "Error" word in the class name was put there solely to
|
||||
* comply with the parlance of the JSON-RPC spec. This class doesn't inherit
|
||||
* from {@code java.lang.Error}. It's a regular subclass of
|
||||
* {@code java.lang.Exception} and, if thrown, it's to indicate a condition
|
||||
* comply with the parlance of the JSON-RPC spec. This class doesn't inherit
|
||||
* from {@code java.lang.Error}. It's a regular subclass of
|
||||
* {@code java.lang.Exception} and, if thrown, it's to indicate a condition
|
||||
* that a reasonable application might want to catch.
|
||||
*
|
||||
* <p>This class also includes convenient final static instances for all
|
||||
* <p>This class also includes convenient final static instances for all
|
||||
* standard JSON-RPC 2.0 errors:
|
||||
*
|
||||
* <ul>
|
||||
@ -51,11 +51,11 @@ import org.json.simple.JSONObject;
|
||||
* <li>{@link #INTERNAL_ERROR} Internal error (-32603)
|
||||
* </ul>
|
||||
*
|
||||
* <p>Note that the range -32099..-32000 is reserved for additional server
|
||||
* <p>Note that the range -32099..-32000 is reserved for additional server
|
||||
* errors.
|
||||
*
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <p id="map">The mapping between JSON and Java entities (as defined by the
|
||||
* underlying JSON.simple library):
|
||||
* <pre>
|
||||
* true|false <---> java.lang.Boolean
|
||||
* number <---> java.lang.Number
|
||||
@ -65,7 +65,7 @@ import org.json.simple.JSONObject;
|
||||
* null <---> null
|
||||
* </pre>
|
||||
*
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <p>The JSON-RPC 2.0 specification and user group forum can be found
|
||||
* <a href="http://groups.google.com/group/json-rpc">here</a>.
|
||||
*
|
||||
* @author <a href="http://dzhuvinov.com">Vladimir Dzhuvinov</a>
|
||||
@ -95,23 +95,23 @@ public class JSONRPC2ExtendedError extends JSONRPC2Error {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code and
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code and
|
||||
* message. The optional data is omitted.
|
||||
*
|
||||
*
|
||||
* @param code The error code (standard pre-defined or
|
||||
* application-specific).
|
||||
* @param message The error message.
|
||||
*/
|
||||
public JSONRPC2ExtendedError(int code, String message) {
|
||||
public JSONRPC2ExtendedError(int code, String message) {
|
||||
super(code, message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code,
|
||||
* message and data.
|
||||
*
|
||||
*
|
||||
* @param code The error code (standard pre-defined or
|
||||
* application-specific).
|
||||
* @param message The error message.
|
||||
@ -123,7 +123,7 @@ public class JSONRPC2ExtendedError extends JSONRPC2Error {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gets the JSON-RPC 2.0 error code.
|
||||
*
|
||||
* @return The error code.
|
||||
@ -143,7 +143,7 @@ public class JSONRPC2ExtendedError extends JSONRPC2Error {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gets a JSON representation of the JSON-RPC 2.0 error.
|
||||
*
|
||||
* @return A JSON object representing this error object.
|
||||
@ -159,7 +159,7 @@ public class JSONRPC2ExtendedError extends JSONRPC2Error {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Serialises the error object to a JSON string.
|
||||
*
|
||||
* @return A JSON-encoded string representing this error object.
|
||||
|
@ -37,32 +37,32 @@ public class JSONRPC2Helper {
|
||||
* @param useAuth - If true, will validate authentication token.
|
||||
* @return - null if no errors were found. Corresponding JSONRPC2Error if error is found.
|
||||
*/
|
||||
public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req, Boolean useAuth){
|
||||
public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req, Boolean useAuth) {
|
||||
|
||||
// Error on unnamed parameters
|
||||
if (req.getParamsType() != JSONRPC2ParamsType.OBJECT){
|
||||
if (req.getParamsType() != JSONRPC2ParamsType.OBJECT) {
|
||||
return JSONRPC2Error.INVALID_PARAMS;
|
||||
}
|
||||
HashMap params = (HashMap) req.getParams();
|
||||
|
||||
// Validate authentication token.
|
||||
if (useAuth){
|
||||
if (useAuth) {
|
||||
JSONRPC2Error err = validateToken(params);
|
||||
if (err != null){
|
||||
if (err != null) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// If there exist any required arguments.
|
||||
if (requiredArgs != null && requiredArgs.length > 0){
|
||||
if (requiredArgs != null && requiredArgs.length > 0) {
|
||||
String missingArgs = "";
|
||||
for (int i = 0; i < requiredArgs.length; i++){
|
||||
if (!params.containsKey(requiredArgs[i])){
|
||||
for (int i = 0; i < requiredArgs.length; i++) {
|
||||
if (!params.containsKey(requiredArgs[i])) {
|
||||
missingArgs = missingArgs.concat(requiredArgs[i] + ",");
|
||||
}
|
||||
}
|
||||
if (missingArgs.length() > 0){
|
||||
missingArgs = missingArgs.substring(0, missingArgs.length()-1);
|
||||
if (missingArgs.length() > 0) {
|
||||
missingArgs = missingArgs.substring(0, missingArgs.length() - 1);
|
||||
return new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(), "Missing parameter(s): " + missingArgs);
|
||||
}
|
||||
}
|
||||
@ -75,7 +75,7 @@ public class JSONRPC2Helper {
|
||||
* @param req - Incoming JSONRPC2 request
|
||||
* @return - null if no errors were found. Corresponding JSONRPC2Error if error is found.
|
||||
*/
|
||||
public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req){
|
||||
public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req) {
|
||||
return validateParams(requiredArgs, req, JSONRPC2Helper.USE_AUTH);
|
||||
}
|
||||
|
||||
@ -86,18 +86,18 @@ public class JSONRPC2Helper {
|
||||
* @param req - Parameters of incoming request
|
||||
* @return null if everything is fine, JSONRPC2Error for any corresponding error.
|
||||
*/
|
||||
private static JSONRPC2Error validateToken(HashMap params){
|
||||
private static JSONRPC2Error validateToken(HashMap params) {
|
||||
String tokenID = (String) params.get("Token");
|
||||
if (tokenID == null){
|
||||
if (tokenID == null) {
|
||||
return JSONRPC2ExtendedError.NO_TOKEN;
|
||||
}
|
||||
try {
|
||||
SecurityManager.getInstance().verifyToken(tokenID);
|
||||
} catch (InvalidAuthTokenException e){
|
||||
} catch (InvalidAuthTokenException e) {
|
||||
return JSONRPC2ExtendedError.INVALID_TOKEN;
|
||||
} catch (ExpiredAuthTokenException e){
|
||||
} catch (ExpiredAuthTokenException e) {
|
||||
JSONRPC2Error err = new JSONRPC2ExtendedError(JSONRPC2ExtendedError.TOKEN_EXPIRED.getCode(),
|
||||
"Provided authentication token expired "+e.getExpirytime()+", will be removed.");
|
||||
"Provided authentication token expired " + e.getExpirytime() + ", will be removed.");
|
||||
return err;
|
||||
}
|
||||
return null;
|
||||
|
@ -44,7 +44,7 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
private static RouterContext _context;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(NetworkSettingHandler.class);
|
||||
|
||||
static{
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
@ -54,30 +54,30 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[]{"NetworkSetting"};
|
||||
return new String[] {"NetworkSetting"};
|
||||
}
|
||||
|
||||
// Processes the requests
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("NetworkSetting")) {
|
||||
return process(req);
|
||||
}else {
|
||||
} else {
|
||||
// Method name not supported
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private JSONRPC2Response process(JSONRPC2Request req){
|
||||
private JSONRPC2Response process(JSONRPC2Request req) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
if (_context == null){
|
||||
if (_context == null) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
}
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
Map outParams = new HashMap();
|
||||
@ -86,21 +86,21 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
boolean settingsSaved = false;
|
||||
String inParam;
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ntcp.port")){
|
||||
if (inParams.containsKey("i2p.router.net.ntcp.port")) {
|
||||
String oldNTCPPort = _context.getProperty(NTCPTransport.PROP_I2NP_NTCP_PORT);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ntcp.port")) != null){
|
||||
if (oldNTCPPort == null || !oldNTCPPort.equals(inParam.trim())){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ntcp.port")) != null) {
|
||||
if (oldNTCPPort == null || !oldNTCPPort.equals(inParam.trim())) {
|
||||
Integer newPort;
|
||||
try {
|
||||
newPort = Integer.valueOf(inParam);
|
||||
if (newPort < 1 || newPort > 65535){
|
||||
if (newPort < 1 || newPort > 65535) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
} catch (NumberFormatException e){
|
||||
} catch (NumberFormatException e) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ntcp.port\" must be a string representing a number in the range 1-65535. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ntcp.port\" must be a string representing a number in the range 1-65535. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
}
|
||||
HashMap<String, String> config = new HashMap<String, String>();
|
||||
config.put(NTCPTransport.PROP_I2NP_NTCP_PORT, String.valueOf(newPort));
|
||||
@ -109,10 +109,10 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
restartNeeded = true;
|
||||
}
|
||||
settingsSaved = true;
|
||||
} else{
|
||||
} else {
|
||||
String sAutoPort = _context.getProperty(NTCPTransport.PROP_I2NP_NTCP_AUTO_PORT, "true");
|
||||
boolean oldAutoPort = "true".equalsIgnoreCase(sAutoPort);
|
||||
if (oldAutoPort){
|
||||
if (oldAutoPort) {
|
||||
String oldSSUPort = "" + _context.getProperty(UDPTransport.PROP_INTERNAL_PORT, 8887);
|
||||
outParams.put("i2p.router.net.ntcp.port", oldSSUPort);
|
||||
} else {
|
||||
@ -120,33 +120,33 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(inParams.containsKey("i2p.router.net.ntcp.hostname")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ntcp.hostname")) {
|
||||
String oldNTCPHostname = _context.getProperty(NTCPTransport.PROP_I2NP_NTCP_HOSTNAME);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ntcp.hostname")) != null){
|
||||
if (oldNTCPHostname == null || !oldNTCPHostname.equals(inParam.trim())){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ntcp.hostname")) != null) {
|
||||
if (oldNTCPHostname == null || !oldNTCPHostname.equals(inParam.trim())) {
|
||||
_context.router().saveConfig(NTCPTransport.PROP_I2NP_NTCP_HOSTNAME, inParam);
|
||||
restartNeeded = true;
|
||||
}
|
||||
settingsSaved = true;
|
||||
} else {
|
||||
outParams.put("i2p.router.net.ntcp.hostname", oldNTCPHostname);
|
||||
} else {
|
||||
outParams.put("i2p.router.net.ntcp.hostname", oldNTCPHostname);
|
||||
}
|
||||
}
|
||||
|
||||
if(inParams.containsKey("i2p.router.net.ntcp.autoip")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ntcp.autoip")) {
|
||||
String oldNTCPAutoIP = _context.getProperty(NTCPTransport.PROP_I2NP_NTCP_AUTO_IP);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ntcp.autoip")) != null){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ntcp.autoip")) != null) {
|
||||
inParam = inParam.trim().toLowerCase();
|
||||
if (oldNTCPAutoIP == null || !oldNTCPAutoIP.equals(inParam)){
|
||||
if ("always".equals(inParam) || "true".equals(inParam) || "false".equals(inParam)){
|
||||
if (oldNTCPAutoIP == null || !oldNTCPAutoIP.equals(inParam)) {
|
||||
if ("always".equals(inParam) || "true".equals(inParam) || "false".equals(inParam)) {
|
||||
_context.router().saveConfig(NTCPTransport.PROP_I2NP_NTCP_AUTO_IP, inParam);
|
||||
restartNeeded = true;
|
||||
} else {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ntcp.autoip\" can only be always, true or false. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ntcp.autoip\" can only be always, true or false. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
}
|
||||
}
|
||||
settingsSaved = true;
|
||||
@ -154,22 +154,22 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.ntcp.autoip", oldNTCPAutoIP);
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ssu.port")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ssu.port")) {
|
||||
String oldSSUPort = "" + _context.getProperty(UDPTransport.PROP_INTERNAL_PORT, 8887);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.port")) != null){
|
||||
if (oldSSUPort== null || !oldSSUPort.equals(inParam.trim())){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.port")) != null) {
|
||||
if (oldSSUPort == null || !oldSSUPort.equals(inParam.trim())) {
|
||||
Integer newPort;
|
||||
try {
|
||||
newPort = Integer.valueOf(inParam);
|
||||
if (newPort < 1 || newPort > 65535){
|
||||
if (newPort < 1 || newPort > 65535) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
} catch (NumberFormatException e){
|
||||
} catch (NumberFormatException e) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ssu.port\" must be a string representing a number in the range 1-65535. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ssu.port\" must be a string representing a number in the range 1-65535. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
}
|
||||
HashMap<String, String> config = new HashMap<String, String>();
|
||||
config.put(UDPTransport.PROP_EXTERNAL_PORT, String.valueOf(newPort));
|
||||
@ -182,11 +182,11 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.ssu.port", oldSSUPort);
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ssu.hostname")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ssu.hostname")) {
|
||||
String oldSSUHostname = _context.getProperty(UDPTransport.PROP_EXTERNAL_HOST);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.hostname")) != null){
|
||||
if (oldSSUHostname == null || !oldSSUHostname.equals(inParam.trim())){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.hostname")) != null) {
|
||||
if (oldSSUHostname == null || !oldSSUHostname.equals(inParam.trim())) {
|
||||
_context.router().saveConfig(UDPTransport.PROP_EXTERNAL_HOST, inParam);
|
||||
restartNeeded = true;
|
||||
}
|
||||
@ -195,20 +195,20 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.ssu.hostname", oldSSUHostname);
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ssu.autoip")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.ssu.autoip")) {
|
||||
String oldSSUAutoIP = _context.getProperty(UDPTransport.PROP_SOURCES);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.autoip")) != null){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.autoip")) != null) {
|
||||
inParam = inParam.trim().toLowerCase();
|
||||
if (oldSSUAutoIP == null || !oldSSUAutoIP.equals(inParam)){
|
||||
if (inParam.equals("ssu") || inParam.equals("local,ssu") || inParam.equals("upnp,ssu") || inParam.equals("local,upnp,ssu")){
|
||||
_context.router().saveConfig(UDPTransport.PROP_SOURCES, inParam);
|
||||
restartNeeded = true;
|
||||
if (oldSSUAutoIP == null || !oldSSUAutoIP.equals(inParam)) {
|
||||
if (inParam.equals("ssu") || inParam.equals("local,ssu") || inParam.equals("upnp,ssu") || inParam.equals("local,upnp,ssu")) {
|
||||
_context.router().saveConfig(UDPTransport.PROP_SOURCES, inParam);
|
||||
restartNeeded = true;
|
||||
} else {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ssu.autoip\" can only be ssu/local,upnp,ssu/local/ssu/upnp,ssu. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.ssu.autoip\" can only be ssu/local,upnp,ssu/local/ssu/upnp,ssu. " + inParam + " isn't valid."),
|
||||
req.getID());
|
||||
}
|
||||
}
|
||||
settingsSaved = true;
|
||||
@ -216,10 +216,10 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.ssu.autoip", oldSSUAutoIP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Non-setable key.
|
||||
if (inParams.containsKey("i2p.router.net.ssu.detectedip")){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.autoip")) == null){
|
||||
if (inParams.containsKey("i2p.router.net.ssu.detectedip")) {
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.ssu.autoip")) == null) {
|
||||
byte[] ipBytes = _context.router().getRouterInfo().getTargetAddress("SSU").getIP();
|
||||
try {
|
||||
InetAddress i = InetAddress.getByAddress(ipBytes);
|
||||
@ -229,11 +229,11 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.upnp")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.upnp")) {
|
||||
String oldUPNP = _context.getProperty(TransportManager.PROP_ENABLE_UPNP);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.upnp")) != null){
|
||||
if (oldUPNP == null || !oldUPNP.equals(inParam.trim())){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.upnp")) != null) {
|
||||
if (oldUPNP == null || !oldUPNP.equals(inParam.trim())) {
|
||||
_context.router().saveConfig(TransportManager.PROP_ENABLE_UPNP, inParam);
|
||||
restartNeeded = true;
|
||||
}
|
||||
@ -242,23 +242,23 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.upnp", oldUPNP);
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.bw.share")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.bw.share")) {
|
||||
String oldShare = _context.router().getConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.bw.share")) != null){
|
||||
if (oldShare == null || !oldShare.equals(inParam.trim())){
|
||||
Integer percent;
|
||||
try{
|
||||
percent = Integer.parseInt(inParam);
|
||||
if (percent < 0 || percent > 100 || inParam.length() == 0) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
} catch (NumberFormatException e){
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.bw.share\" A positive integer must supplied, \"" + inParam + "\" isn't valid"),
|
||||
req.getID());
|
||||
}
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.bw.share")) != null) {
|
||||
if (oldShare == null || !oldShare.equals(inParam.trim())) {
|
||||
Integer percent;
|
||||
try {
|
||||
percent = Integer.parseInt(inParam);
|
||||
if (percent < 0 || percent > 100 || inParam.length() == 0) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.bw.share\" A positive integer must supplied, \"" + inParam + "\" isn't valid"),
|
||||
req.getID());
|
||||
}
|
||||
_context.router().saveConfig(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE, inParam);
|
||||
}
|
||||
settingsSaved = true;
|
||||
@ -266,25 +266,25 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.bw.share", oldShare);
|
||||
}
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.bw.in")){
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.bw.in")) {
|
||||
String oldBWIn = _context.getProperty(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.bw.in")) != null){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.bw.in")) != null) {
|
||||
Integer rate;
|
||||
try{
|
||||
try {
|
||||
rate = Integer.parseInt(inParam);
|
||||
if (rate < 0 || inParam.length() == 0) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
} catch (NumberFormatException e){
|
||||
} catch (NumberFormatException e) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.bw.in\" A positive integer must supplied, " + inParam + " isn't valid"),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.bw.in\" A positive integer must supplied, " + inParam + " isn't valid"),
|
||||
req.getID());
|
||||
}
|
||||
Integer burstRate = (rate * BW_BURST_PCT)/100;
|
||||
Integer burstRate = (rate * BW_BURST_PCT) / 100;
|
||||
Integer burstSize = (burstRate * BW_BURST_TIME);
|
||||
if (oldBWIn == null || !oldBWIn.equals(rate.toString())){
|
||||
if (oldBWIn == null || !oldBWIn.equals(rate.toString())) {
|
||||
HashMap<String, String> config = new HashMap<String, String>();
|
||||
config.put(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH, rate.toString());
|
||||
config.put(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH, burstRate.toString());
|
||||
@ -297,23 +297,23 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.bw.in", oldBWIn);
|
||||
}
|
||||
}
|
||||
if (inParams.containsKey("i2p.router.net.bw.out")){
|
||||
if (inParams.containsKey("i2p.router.net.bw.out")) {
|
||||
String oldBWOut = _context.getProperty(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.bw.out")) != null){
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.bw.out")) != null) {
|
||||
Integer rate;
|
||||
try{
|
||||
try {
|
||||
rate = Integer.parseInt(inParam);
|
||||
if (rate < 0 || inParam.length() == 0)
|
||||
throw new NumberFormatException();
|
||||
} catch (NumberFormatException e){
|
||||
} catch (NumberFormatException e) {
|
||||
return new JSONRPC2Response(
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.bw.out\" A positive integer must supplied, " + inParam + " isn't valid"),
|
||||
req.getID());
|
||||
new JSONRPC2Error(JSONRPC2Error.INVALID_PARAMS.getCode(),
|
||||
"\"i2p.router.net.bw.out\" A positive integer must supplied, " + inParam + " isn't valid"),
|
||||
req.getID());
|
||||
}
|
||||
Integer burstRate = (rate * BW_BURST_PCT)/100;
|
||||
Integer burstRate = (rate * BW_BURST_PCT) / 100;
|
||||
Integer burstSize = (burstRate * BW_BURST_TIME);
|
||||
if (oldBWOut == null || !oldBWOut.equals(rate.toString())){
|
||||
if (oldBWOut == null || !oldBWOut.equals(rate.toString())) {
|
||||
HashMap<String, String> config = new HashMap<String, String>();
|
||||
config.put(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH, rate.toString());
|
||||
config.put(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, burstRate.toString());
|
||||
@ -326,12 +326,12 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
outParams.put("i2p.router.net.bw.out", oldBWOut);
|
||||
}
|
||||
}
|
||||
if (inParams.containsKey("i2p.router.net.laptopmode")){
|
||||
if (inParams.containsKey("i2p.router.net.laptopmode")) {
|
||||
String oldLaptopMode = _context.getProperty(UDPTransport.PROP_LAPTOP_MODE);
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.laptopmode")) != null){
|
||||
if (oldLaptopMode == null || !oldLaptopMode.equals(inParam.trim())){
|
||||
_context.router().saveConfig(UDPTransport.PROP_LAPTOP_MODE, String.valueOf(inParam));
|
||||
}
|
||||
if ((inParam = (String) inParams.get("i2p.router.net.laptopmode")) != null) {
|
||||
if (oldLaptopMode == null || !oldLaptopMode.equals(inParam.trim())) {
|
||||
_context.router().saveConfig(UDPTransport.PROP_LAPTOP_MODE, String.valueOf(inParam));
|
||||
}
|
||||
settingsSaved = true;
|
||||
} else {
|
||||
outParams.put("i2p.router.net.laptopmode", oldLaptopMode);
|
||||
|
@ -61,7 +61,7 @@ public class RouterInfoHandler implements RequestHandler {
|
||||
} else {
|
||||
// Method name not supported
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND,
|
||||
req.getID());
|
||||
req.getID());
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,20 +73,20 @@ public class RouterInfoHandler implements RequestHandler {
|
||||
|
||||
if (_context == null) {
|
||||
return new JSONRPC2Response(new JSONRPC2Error(
|
||||
JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
}
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
Map outParams = new HashMap();
|
||||
|
||||
if (inParams.containsKey("i2p.router.version")) {
|
||||
try {
|
||||
Class rvClass = Class.forName("net.i2p.router.RouterVersion");
|
||||
java.lang.reflect.Field field = rvClass.getDeclaredField("FULL_VERSION");
|
||||
String fullVersion = (String) field.get(new RouterVersion());
|
||||
outParams.put("i2p.router.version", fullVersion);
|
||||
} catch (Exception e){} // Ignore
|
||||
Class rvClass = Class.forName("net.i2p.router.RouterVersion");
|
||||
java.lang.reflect.Field field = rvClass.getDeclaredField("FULL_VERSION");
|
||||
String fullVersion = (String) field.get(new RouterVersion());
|
||||
outParams.put("i2p.router.version", fullVersion);
|
||||
} catch (Exception e) {} // Ignore
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.uptime")) {
|
||||
@ -128,7 +128,7 @@ public class RouterInfoHandler implements RequestHandler {
|
||||
|
||||
if (inParams.containsKey("i2p.router.netdb.knownpeers")) {
|
||||
// Why max(-1, 0) is used I don't know, it is the implementation used in the router console.
|
||||
outParams.put("i2p.router.netdb.knownpeers", Math.max(_context.netDb().getKnownRouters()-1,0));
|
||||
outParams.put("i2p.router.netdb.knownpeers", Math.max(_context.netDb().getKnownRouters() - 1, 0));
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.netdb.activepeers")) {
|
||||
@ -149,7 +149,7 @@ public class RouterInfoHandler implements RequestHandler {
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
|
||||
private static enum NETWORK_STATUS{
|
||||
private static enum NETWORK_STATUS {
|
||||
OK,
|
||||
TESTING,
|
||||
FIREWALLED,
|
||||
|
@ -62,7 +62,7 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
} else {
|
||||
// Method name not supported
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND,
|
||||
req.getID());
|
||||
req.getID());
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,32 +73,33 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
|
||||
if (_context == null) {
|
||||
return new JSONRPC2Response(new JSONRPC2Error(
|
||||
JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
}
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
final Map outParams = new HashMap();
|
||||
|
||||
if (inParams.containsKey("Shutdown")) {
|
||||
outParams.put("Shutdown", null);
|
||||
(new Thread(){
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(SHUTDOWN_WAIT);
|
||||
} catch (InterruptedException e) {}
|
||||
_context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_HARD));
|
||||
_context.router().shutdown(Router.EXIT_HARD); }
|
||||
_context.router().shutdown(Router.EXIT_HARD);
|
||||
}
|
||||
}).start();
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
|
||||
if (inParams.containsKey("Restart")) {
|
||||
outParams.put("Restart", null);
|
||||
(new Thread(){
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(SHUTDOWN_WAIT);
|
||||
} catch (InterruptedException e) {}
|
||||
@ -111,9 +112,9 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
|
||||
if (inParams.containsKey("ShutdownGraceful")) {
|
||||
outParams.put("ShutdownGraceful", null);
|
||||
(new Thread(){
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(SHUTDOWN_WAIT);
|
||||
} catch (InterruptedException e) {}
|
||||
@ -126,23 +127,24 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
|
||||
if (inParams.containsKey("RestartGraceful")) {
|
||||
outParams.put("RestartGraceful", null);
|
||||
(new Thread(){
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(SHUTDOWN_WAIT);
|
||||
} catch (InterruptedException e) {}
|
||||
_context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART));
|
||||
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART); }
|
||||
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
|
||||
}
|
||||
}).start();
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
|
||||
if (inParams.containsKey("Reseed")){
|
||||
if (inParams.containsKey("Reseed")) {
|
||||
outParams.put("Reseed", null);
|
||||
(new Thread(){
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
public void run() {
|
||||
ReseedChecker reseeder = new ReseedChecker(_context);
|
||||
reseeder.requestReseed();
|
||||
}
|
||||
@ -150,11 +152,11 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
|
||||
if (inParams.containsKey("FindUpdates")){
|
||||
Thread t = new Thread(){
|
||||
if (inParams.containsKey("FindUpdates")) {
|
||||
Thread t = new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
ClientAppManager clmgr = I2PAppContext.getCurrentContext().clientAppManager();
|
||||
public void run() {
|
||||
ClientAppManager clmgr = I2PAppContext.getCurrentContext().clientAppManager();
|
||||
if (clmgr == null) {
|
||||
outParams.put("FindUpdates", "ClientAppManager is null");
|
||||
return;
|
||||
@ -174,12 +176,12 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
} catch (InterruptedException e) {}
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
|
||||
if (inParams.containsKey("Update")){
|
||||
Thread t = new Thread(){
|
||||
|
||||
if (inParams.containsKey("Update")) {
|
||||
Thread t = new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
ClientAppManager clmgr = I2PAppContext.getCurrentContext().clientAppManager();
|
||||
public void run() {
|
||||
ClientAppManager clmgr = I2PAppContext.getCurrentContext().clientAppManager();
|
||||
if (clmgr == null) {
|
||||
outParams.put("Update", "ClientAppManager is null");
|
||||
return;
|
||||
@ -196,7 +198,9 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
}
|
||||
boolean isUpdating = upmgr.isUpdateInProgress(UpdateType.ROUTER_SIGNED);
|
||||
while (isUpdating) {
|
||||
try { Thread.sleep(100);} catch (Exception e){}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (Exception e) {}
|
||||
isUpdating = upmgr.isUpdateInProgress(UpdateType.ROUTER_SIGNED);
|
||||
}
|
||||
outParams.put("Update", upmgr.getStatus());
|
||||
@ -208,7 +212,7 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
} catch (InterruptedException e) {}
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
|
||||
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
|
||||
|
@ -15,133 +15,133 @@ import java.util.StringTokenizer;
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public class ItemList {
|
||||
private String sp=",";
|
||||
List items=new ArrayList();
|
||||
|
||||
|
||||
public ItemList(){}
|
||||
|
||||
|
||||
public ItemList(String s){
|
||||
this.split(s,sp,items);
|
||||
}
|
||||
|
||||
public ItemList(String s,String sp){
|
||||
this.sp=s;
|
||||
this.split(s,sp,items);
|
||||
}
|
||||
|
||||
public ItemList(String s,String sp,boolean isMultiToken){
|
||||
split(s,sp,items,isMultiToken);
|
||||
}
|
||||
|
||||
public List getItems(){
|
||||
return this.items;
|
||||
}
|
||||
|
||||
public String[] getArray(){
|
||||
return (String[])this.items.toArray();
|
||||
}
|
||||
|
||||
public void split(String s,String sp,List append,boolean isMultiToken){
|
||||
if(s==null || sp==null)
|
||||
return;
|
||||
if(isMultiToken){
|
||||
StringTokenizer tokens=new StringTokenizer(s,sp);
|
||||
while(tokens.hasMoreTokens()){
|
||||
append.add(tokens.nextToken().trim());
|
||||
}
|
||||
}
|
||||
else{
|
||||
this.split(s,sp,append);
|
||||
}
|
||||
}
|
||||
|
||||
public void split(String s,String sp,List append){
|
||||
if(s==null || sp==null)
|
||||
return;
|
||||
int pos=0;
|
||||
int prevPos=0;
|
||||
do{
|
||||
prevPos=pos;
|
||||
pos=s.indexOf(sp,pos);
|
||||
if(pos==-1)
|
||||
break;
|
||||
append.add(s.substring(prevPos,pos).trim());
|
||||
pos+=sp.length();
|
||||
}while(pos!=-1);
|
||||
append.add(s.substring(prevPos).trim());
|
||||
}
|
||||
|
||||
public void setSP(String sp){
|
||||
this.sp=sp;
|
||||
}
|
||||
|
||||
public void add(int i,String item){
|
||||
if(item==null)
|
||||
return;
|
||||
items.add(i,item.trim());
|
||||
}
|
||||
private String sp = ",";
|
||||
List items = new ArrayList();
|
||||
|
||||
public void add(String item){
|
||||
if(item==null)
|
||||
return;
|
||||
items.add(item.trim());
|
||||
}
|
||||
|
||||
public void addAll(ItemList list){
|
||||
items.addAll(list.items);
|
||||
}
|
||||
|
||||
public void addAll(String s){
|
||||
this.split(s,sp,items);
|
||||
}
|
||||
|
||||
public void addAll(String s,String sp){
|
||||
this.split(s,sp,items);
|
||||
}
|
||||
|
||||
public void addAll(String s,String sp,boolean isMultiToken){
|
||||
this.split(s,sp,items,isMultiToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i 0-based
|
||||
* @return
|
||||
*/
|
||||
public String get(int i){
|
||||
return (String)items.get(i);
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return items.size();
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return toString(sp);
|
||||
}
|
||||
|
||||
public String toString(String sp){
|
||||
StringBuffer sb=new StringBuffer();
|
||||
|
||||
for(int i=0;i<items.size();i++){
|
||||
if(i==0)
|
||||
sb.append(items.get(i));
|
||||
else{
|
||||
sb.append(sp);
|
||||
sb.append(items.get(i));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
public ItemList() {}
|
||||
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
items.clear();
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
sp=",";
|
||||
items.clear();
|
||||
}
|
||||
|
||||
public ItemList(String s) {
|
||||
this.split(s, sp, items);
|
||||
}
|
||||
|
||||
public ItemList(String s, String sp) {
|
||||
this.sp = s;
|
||||
this.split(s, sp, items);
|
||||
}
|
||||
|
||||
public ItemList(String s, String sp, boolean isMultiToken) {
|
||||
split(s, sp, items, isMultiToken);
|
||||
}
|
||||
|
||||
public List getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
public String[] getArray() {
|
||||
return (String[])this.items.toArray();
|
||||
}
|
||||
|
||||
public void split(String s, String sp, List append, boolean isMultiToken) {
|
||||
if (s == null || sp == null)
|
||||
return;
|
||||
if (isMultiToken) {
|
||||
StringTokenizer tokens = new StringTokenizer(s, sp);
|
||||
while (tokens.hasMoreTokens()) {
|
||||
append.add(tokens.nextToken().trim());
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.split(s, sp, append);
|
||||
}
|
||||
}
|
||||
|
||||
public void split(String s, String sp, List append) {
|
||||
if (s == null || sp == null)
|
||||
return;
|
||||
int pos = 0;
|
||||
int prevPos = 0;
|
||||
do {
|
||||
prevPos = pos;
|
||||
pos = s.indexOf(sp, pos);
|
||||
if (pos == -1)
|
||||
break;
|
||||
append.add(s.substring(prevPos, pos).trim());
|
||||
pos += sp.length();
|
||||
} while (pos != -1);
|
||||
append.add(s.substring(prevPos).trim());
|
||||
}
|
||||
|
||||
public void setSP(String sp) {
|
||||
this.sp = sp;
|
||||
}
|
||||
|
||||
public void add(int i, String item) {
|
||||
if (item == null)
|
||||
return;
|
||||
items.add(i, item.trim());
|
||||
}
|
||||
|
||||
public void add(String item) {
|
||||
if (item == null)
|
||||
return;
|
||||
items.add(item.trim());
|
||||
}
|
||||
|
||||
public void addAll(ItemList list) {
|
||||
items.addAll(list.items);
|
||||
}
|
||||
|
||||
public void addAll(String s) {
|
||||
this.split(s, sp, items);
|
||||
}
|
||||
|
||||
public void addAll(String s, String sp) {
|
||||
this.split(s, sp, items);
|
||||
}
|
||||
|
||||
public void addAll(String s, String sp, boolean isMultiToken) {
|
||||
this.split(s, sp, items, isMultiToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i 0-based
|
||||
* @return
|
||||
*/
|
||||
public String get(int i) {
|
||||
return (String)items.get(i);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return toString(sp);
|
||||
}
|
||||
|
||||
public String toString(String sp) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (i == 0)
|
||||
sb.append(items.get(i));
|
||||
else {
|
||||
sb.append(sp);
|
||||
sb.append(items.get(i));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
items.clear();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
sp = ",";
|
||||
items.clear();
|
||||
}
|
||||
}
|
||||
|
@ -13,95 +13,95 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* A JSON array. JSONObject supports java.util.List interface.
|
||||
*
|
||||
*
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public class JSONArray extends ArrayList implements List, JSONAware, JSONStreamAware {
|
||||
private static final long serialVersionUID = 3957988303675231981L;
|
||||
private static final long serialVersionUID = 3957988303675231981L;
|
||||
|
||||
/**
|
||||
* Encode a list into JSON text and write it to out.
|
||||
* Encode a list into JSON text and write it to out.
|
||||
* If this list is also a JSONStreamAware or a JSONAware, JSONStreamAware and JSONAware specific behaviours will be ignored at this top level.
|
||||
*
|
||||
*
|
||||
* @see org.json.simple.JSONValue#writeJSONString(Object, Writer)
|
||||
*
|
||||
*
|
||||
* @param list
|
||||
* @param out
|
||||
*/
|
||||
public static void writeJSONString(List list, Writer out) throws IOException{
|
||||
if(list == null){
|
||||
out.write("null");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean first = true;
|
||||
Iterator iter=list.iterator();
|
||||
|
||||
public static void writeJSONString(List list, Writer out) throws IOException {
|
||||
if (list == null) {
|
||||
out.write("null");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean first = true;
|
||||
Iterator iter = list.iterator();
|
||||
|
||||
out.write('[');
|
||||
while(iter.hasNext()){
|
||||
if(first)
|
||||
while (iter.hasNext()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
out.write(',');
|
||||
|
||||
Object value=iter.next();
|
||||
if(value == null){
|
||||
out.write("null");
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONValue.writeJSONString(value, out);
|
||||
}
|
||||
out.write(']');
|
||||
}
|
||||
|
||||
public void writeJSONString(Writer out) throws IOException{
|
||||
writeJSONString(this, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a list to JSON text. The result is a JSON array.
|
||||
* If this list is also a JSONAware, JSONAware specific behaviours will be omitted at this top level.
|
||||
*
|
||||
* @see org.json.simple.JSONValue#toJSONString(Object)
|
||||
*
|
||||
* @param list
|
||||
* @return JSON text, or "null" if list is null.
|
||||
*/
|
||||
public static String toJSONString(List list){
|
||||
if(list == null)
|
||||
return "null";
|
||||
|
||||
|
||||
Object value = iter.next();
|
||||
if (value == null) {
|
||||
out.write("null");
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONValue.writeJSONString(value, out);
|
||||
}
|
||||
out.write(']');
|
||||
}
|
||||
|
||||
public void writeJSONString(Writer out) throws IOException {
|
||||
writeJSONString(this, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a list to JSON text. The result is a JSON array.
|
||||
* If this list is also a JSONAware, JSONAware specific behaviours will be omitted at this top level.
|
||||
*
|
||||
* @see org.json.simple.JSONValue#toJSONString(Object)
|
||||
*
|
||||
* @param list
|
||||
* @return JSON text, or "null" if list is null.
|
||||
*/
|
||||
public static String toJSONString(List list) {
|
||||
if (list == null)
|
||||
return "null";
|
||||
|
||||
boolean first = true;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Iterator iter=list.iterator();
|
||||
|
||||
Iterator iter = list.iterator();
|
||||
|
||||
sb.append('[');
|
||||
while(iter.hasNext()){
|
||||
if(first)
|
||||
while (iter.hasNext()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
sb.append(',');
|
||||
|
||||
Object value=iter.next();
|
||||
if(value == null){
|
||||
sb.append("null");
|
||||
continue;
|
||||
}
|
||||
sb.append(JSONValue.toJSONString(value));
|
||||
}
|
||||
|
||||
Object value = iter.next();
|
||||
if (value == null) {
|
||||
sb.append("null");
|
||||
continue;
|
||||
}
|
||||
sb.append(JSONValue.toJSONString(value));
|
||||
}
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toJSONString() {
|
||||
return toJSONString(this);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return toJSONString();
|
||||
}
|
||||
|
||||
|
||||
public String toJSONString(){
|
||||
return toJSONString(this);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return toJSONString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package org.json.simple;
|
||||
|
||||
/**
|
||||
* Beans that support customized output of JSON text shall implement this interface.
|
||||
* Beans that support customized output of JSON text shall implement this interface.
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public interface JSONAware {
|
||||
/**
|
||||
* @return JSON text
|
||||
*/
|
||||
String toJSONString();
|
||||
/**
|
||||
* @return JSON text
|
||||
*/
|
||||
String toJSONString();
|
||||
}
|
||||
|
@ -12,118 +12,118 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* A JSON object. Key value pairs are unordered. JSONObject supports java.util.Map interface.
|
||||
*
|
||||
*
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware{
|
||||
private static final long serialVersionUID = -503443796854799292L;
|
||||
public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware {
|
||||
private static final long serialVersionUID = -503443796854799292L;
|
||||
|
||||
/**
|
||||
* Encode a map into JSON text and write it to out.
|
||||
* If this map is also a JSONAware or JSONStreamAware, JSONAware or JSONStreamAware specific behaviours will be ignored at this top level.
|
||||
*
|
||||
*
|
||||
* @see org.json.simple.JSONValue#writeJSONString(Object, Writer)
|
||||
*
|
||||
*
|
||||
* @param map
|
||||
* @param out
|
||||
*/
|
||||
public static void writeJSONString(Map map, Writer out) throws IOException {
|
||||
if(map == null){
|
||||
out.write("null");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean first = true;
|
||||
Iterator iter=map.entrySet().iterator();
|
||||
|
||||
public static void writeJSONString(Map map, Writer out) throws IOException {
|
||||
if (map == null) {
|
||||
out.write("null");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean first = true;
|
||||
Iterator iter = map.entrySet().iterator();
|
||||
|
||||
out.write('{');
|
||||
while(iter.hasNext()){
|
||||
if(first)
|
||||
while (iter.hasNext()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
out.write(',');
|
||||
Map.Entry entry=(Map.Entry)iter.next();
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
out.write('\"');
|
||||
out.write(escape(String.valueOf(entry.getKey())));
|
||||
out.write('\"');
|
||||
out.write(':');
|
||||
JSONValue.writeJSONString(entry.getValue(), out);
|
||||
}
|
||||
out.write('}');
|
||||
}
|
||||
JSONValue.writeJSONString(entry.getValue(), out);
|
||||
}
|
||||
out.write('}');
|
||||
}
|
||||
|
||||
public void writeJSONString(Writer out) throws IOException {
|
||||
writeJSONString(this, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a map to JSON text. The result is a JSON object.
|
||||
* If this map is also a JSONAware, JSONAware specific behaviours will be omitted at this top level.
|
||||
*
|
||||
* @see org.json.simple.JSONValue#toJSONString(Object)
|
||||
*
|
||||
* @param map
|
||||
* @return JSON text, or "null" if map is null.
|
||||
*/
|
||||
public static String toJSONString(Map map) {
|
||||
if (map == null)
|
||||
return "null";
|
||||
|
||||
public void writeJSONString(Writer out) throws IOException{
|
||||
writeJSONString(this, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a map to JSON text. The result is a JSON object.
|
||||
* If this map is also a JSONAware, JSONAware specific behaviours will be omitted at this top level.
|
||||
*
|
||||
* @see org.json.simple.JSONValue#toJSONString(Object)
|
||||
*
|
||||
* @param map
|
||||
* @return JSON text, or "null" if map is null.
|
||||
*/
|
||||
public static String toJSONString(Map map){
|
||||
if(map == null)
|
||||
return "null";
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
boolean first = true;
|
||||
Iterator iter=map.entrySet().iterator();
|
||||
|
||||
Iterator iter = map.entrySet().iterator();
|
||||
|
||||
sb.append('{');
|
||||
while(iter.hasNext()){
|
||||
if(first)
|
||||
while (iter.hasNext()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
sb.append(',');
|
||||
|
||||
Map.Entry entry=(Map.Entry)iter.next();
|
||||
toJSONString(String.valueOf(entry.getKey()),entry.getValue(), sb);
|
||||
}
|
||||
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
toJSONString(String.valueOf(entry.getKey()), entry.getValue(), sb);
|
||||
}
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toJSONString(){
|
||||
return toJSONString(this);
|
||||
}
|
||||
|
||||
private static String toJSONString(String key,Object value, StringBuffer sb){
|
||||
sb.append('\"');
|
||||
if(key == null)
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toJSONString() {
|
||||
return toJSONString(this);
|
||||
}
|
||||
|
||||
private static String toJSONString(String key, Object value, StringBuffer sb) {
|
||||
sb.append('\"');
|
||||
if (key == null)
|
||||
sb.append("null");
|
||||
else
|
||||
JSONValue.escape(key, sb);
|
||||
sb.append('\"').append(':');
|
||||
|
||||
sb.append(JSONValue.toJSONString(value));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return toJSONString();
|
||||
}
|
||||
sb.append('\"').append(':');
|
||||
|
||||
sb.append(JSONValue.toJSONString(value));
|
||||
|
||||
public static String toString(String key,Object value){
|
||||
StringBuffer sb = new StringBuffer();
|
||||
toJSONString(key, value, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
|
||||
* It's the same as JSONValue.escape() only for compatibility here.
|
||||
*
|
||||
* @see org.json.simple.JSONValue#escape(String)
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String escape(String s){
|
||||
return JSONValue.escape(s);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return toJSONString();
|
||||
}
|
||||
|
||||
public static String toString(String key, Object value) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
toJSONString(key, value, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
|
||||
* It's the same as JSONValue.escape() only for compatibility here.
|
||||
*
|
||||
* @see org.json.simple.JSONValue#escape(String)
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String escape(String s) {
|
||||
return JSONValue.escape(s);
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,12 @@ import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Beans that support customized output of JSON text to a writer shall implement this interface.
|
||||
* Beans that support customized output of JSON text to a writer shall implement this interface.
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public interface JSONStreamAware {
|
||||
/**
|
||||
* write JSON string to out.
|
||||
*/
|
||||
void writeJSONString(Writer out) throws IOException;
|
||||
/**
|
||||
* write JSON string to out.
|
||||
*/
|
||||
void writeJSONString(Writer out) throws IOException;
|
||||
}
|
||||
|
@ -19,202 +19,202 @@ import java.util.Map;
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public class JSONValue {
|
||||
/**
|
||||
* Parse JSON text into java object from the input source.
|
||||
* Please use parseWithException() if you don't want to ignore the exception.
|
||||
*
|
||||
* @see org.json.simple.parser.JSONParser#parse(Reader)
|
||||
* @see #parseWithException(Reader)
|
||||
*
|
||||
* @param in
|
||||
* @return Instance of the following:
|
||||
* org.json.simple.JSONObject,
|
||||
* org.json.simple.JSONArray,
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean,
|
||||
* null
|
||||
*
|
||||
*/
|
||||
public static Object parse(Reader in){
|
||||
try{
|
||||
JSONParser parser=new JSONParser();
|
||||
return parser.parse(in);
|
||||
}
|
||||
catch(Exception e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object parse(String s){
|
||||
StringReader in=new StringReader(s);
|
||||
return parse(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON text into java object from the input source.
|
||||
*
|
||||
* @see org.json.simple.parser.JSONParser
|
||||
*
|
||||
* @param in
|
||||
* @return Instance of the following:
|
||||
* org.json.simple.JSONObject,
|
||||
* org.json.simple.JSONArray,
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean,
|
||||
* null
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ParseException
|
||||
*/
|
||||
public static Object parseWithException(Reader in) throws IOException, ParseException{
|
||||
JSONParser parser=new JSONParser();
|
||||
return parser.parse(in);
|
||||
}
|
||||
|
||||
public static Object parseWithException(String s) throws ParseException{
|
||||
JSONParser parser=new JSONParser();
|
||||
return parser.parse(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON text into java object from the input source.
|
||||
* Please use parseWithException() if you don't want to ignore the exception.
|
||||
*
|
||||
* @see org.json.simple.parser.JSONParser#parse(Reader)
|
||||
* @see #parseWithException(Reader)
|
||||
*
|
||||
* @param in
|
||||
* @return Instance of the following:
|
||||
* org.json.simple.JSONObject,
|
||||
* org.json.simple.JSONArray,
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean,
|
||||
* null
|
||||
*
|
||||
*/
|
||||
public static Object parse(Reader in) {
|
||||
try {
|
||||
JSONParser parser = new JSONParser();
|
||||
return parser.parse(in);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object parse(String s) {
|
||||
StringReader in = new StringReader(s);
|
||||
return parse(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON text into java object from the input source.
|
||||
*
|
||||
* @see org.json.simple.parser.JSONParser
|
||||
*
|
||||
* @param in
|
||||
* @return Instance of the following:
|
||||
* org.json.simple.JSONObject,
|
||||
* org.json.simple.JSONArray,
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean,
|
||||
* null
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ParseException
|
||||
*/
|
||||
public static Object parseWithException(Reader in) throws IOException, ParseException {
|
||||
JSONParser parser = new JSONParser();
|
||||
return parser.parse(in);
|
||||
}
|
||||
|
||||
public static Object parseWithException(String s) throws ParseException {
|
||||
JSONParser parser = new JSONParser();
|
||||
return parser.parse(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an object into JSON text and write it to out.
|
||||
* <p>
|
||||
* If this object is a Map or a List, and it's also a JSONStreamAware or a JSONAware, JSONStreamAware or JSONAware will be considered firstly.
|
||||
* <p>
|
||||
* DO NOT call this method from writeJSONString(Writer) of a class that implements both JSONStreamAware and (Map or List) with
|
||||
* "this" as the first parameter, use JSONObject.writeJSONString(Map, Writer) or JSONArray.writeJSONString(List, Writer) instead.
|
||||
*
|
||||
* DO NOT call this method from writeJSONString(Writer) of a class that implements both JSONStreamAware and (Map or List) with
|
||||
* "this" as the first parameter, use JSONObject.writeJSONString(Map, Writer) or JSONArray.writeJSONString(List, Writer) instead.
|
||||
*
|
||||
* @see org.json.simple.JSONObject#writeJSONString(Map, Writer)
|
||||
* @see org.json.simple.JSONArray#writeJSONString(List, Writer)
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
* @param writer
|
||||
*/
|
||||
public static void writeJSONString(Object value, Writer out) throws IOException {
|
||||
if(value == null){
|
||||
out.write("null");
|
||||
return;
|
||||
}
|
||||
|
||||
if(value instanceof String){
|
||||
out.write('\"');
|
||||
out.write(escape((String)value));
|
||||
out.write('\"');
|
||||
return;
|
||||
}
|
||||
|
||||
if(value instanceof Double){
|
||||
if(((Double)value).isInfinite() || ((Double)value).isNaN())
|
||||
out.write("null");
|
||||
else
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(value instanceof Float){
|
||||
if(((Float)value).isInfinite() || ((Float)value).isNaN())
|
||||
out.write("null");
|
||||
else
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(value instanceof Number){
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(value instanceof Boolean){
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if((value instanceof JSONStreamAware)){
|
||||
((JSONStreamAware)value).writeJSONString(out);
|
||||
return;
|
||||
}
|
||||
|
||||
if((value instanceof JSONAware)){
|
||||
out.write(((JSONAware)value).toJSONString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(value instanceof Map){
|
||||
JSONObject.writeJSONString((Map)value, out);
|
||||
return;
|
||||
}
|
||||
|
||||
if(value instanceof List){
|
||||
JSONArray.writeJSONString((List)value, out);
|
||||
public static void writeJSONString(Object value, Writer out) throws IOException {
|
||||
if (value == null) {
|
||||
out.write("null");
|
||||
return;
|
||||
}
|
||||
|
||||
out.write(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an object to JSON text.
|
||||
* <p>
|
||||
* If this object is a Map or a List, and it's also a JSONAware, JSONAware will be considered firstly.
|
||||
* <p>
|
||||
* DO NOT call this method from toJSONString() of a class that implements both JSONAware and Map or List with
|
||||
* "this" as the parameter, use JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead.
|
||||
*
|
||||
* @see org.json.simple.JSONObject#toJSONString(Map)
|
||||
* @see org.json.simple.JSONArray#toJSONString(List)
|
||||
*
|
||||
* @param value
|
||||
* @return JSON text, or "null" if value is null or it's an NaN or an INF number.
|
||||
*/
|
||||
public static String toJSONString(Object value){
|
||||
if(value == null)
|
||||
return "null";
|
||||
|
||||
if(value instanceof String)
|
||||
return "\""+escape((String)value)+"\"";
|
||||
|
||||
if(value instanceof Double){
|
||||
if(((Double)value).isInfinite() || ((Double)value).isNaN())
|
||||
return "null";
|
||||
else
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if(value instanceof Float){
|
||||
if(((Float)value).isInfinite() || ((Float)value).isNaN())
|
||||
return "null";
|
||||
else
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if(value instanceof Number)
|
||||
return value.toString();
|
||||
|
||||
if(value instanceof Boolean)
|
||||
return value.toString();
|
||||
|
||||
if((value instanceof JSONAware))
|
||||
return ((JSONAware)value).toJSONString();
|
||||
|
||||
if(value instanceof Map)
|
||||
return JSONObject.toJSONString((Map)value);
|
||||
|
||||
if(value instanceof List)
|
||||
return JSONArray.toJSONString((List)value);
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
if (value instanceof String) {
|
||||
out.write('\"');
|
||||
out.write(escape((String)value));
|
||||
out.write('\"');
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String escape(String s){
|
||||
if(s==null)
|
||||
return null;
|
||||
if (value instanceof Double) {
|
||||
if (((Double)value).isInfinite() || ((Double)value).isNaN())
|
||||
out.write("null");
|
||||
else
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Float) {
|
||||
if (((Float)value).isInfinite() || ((Float)value).isNaN())
|
||||
out.write("null");
|
||||
else
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Number) {
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Boolean) {
|
||||
out.write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if ((value instanceof JSONStreamAware)) {
|
||||
((JSONStreamAware)value).writeJSONString(out);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((value instanceof JSONAware)) {
|
||||
out.write(((JSONAware)value).toJSONString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Map) {
|
||||
JSONObject.writeJSONString((Map)value, out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof List) {
|
||||
JSONArray.writeJSONString((List)value, out);
|
||||
return;
|
||||
}
|
||||
|
||||
out.write(value.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an object to JSON text.
|
||||
* <p>
|
||||
* If this object is a Map or a List, and it's also a JSONAware, JSONAware will be considered firstly.
|
||||
* <p>
|
||||
* DO NOT call this method from toJSONString() of a class that implements both JSONAware and Map or List with
|
||||
* "this" as the parameter, use JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead.
|
||||
*
|
||||
* @see org.json.simple.JSONObject#toJSONString(Map)
|
||||
* @see org.json.simple.JSONArray#toJSONString(List)
|
||||
*
|
||||
* @param value
|
||||
* @return JSON text, or "null" if value is null or it's an NaN or an INF number.
|
||||
*/
|
||||
public static String toJSONString(Object value) {
|
||||
if (value == null)
|
||||
return "null";
|
||||
|
||||
if (value instanceof String)
|
||||
return "\"" + escape((String)value) + "\"";
|
||||
|
||||
if (value instanceof Double) {
|
||||
if (((Double)value).isInfinite() || ((Double)value).isNaN())
|
||||
return "null";
|
||||
else
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if (value instanceof Float) {
|
||||
if (((Float)value).isInfinite() || ((Float)value).isNaN())
|
||||
return "null";
|
||||
else
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if (value instanceof Number)
|
||||
return value.toString();
|
||||
|
||||
if (value instanceof Boolean)
|
||||
return value.toString();
|
||||
|
||||
if ((value instanceof JSONAware))
|
||||
return ((JSONAware)value).toJSONString();
|
||||
|
||||
if (value instanceof Map)
|
||||
return JSONObject.toJSONString((Map)value);
|
||||
|
||||
if (value instanceof List)
|
||||
return JSONArray.toJSONString((List)value);
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String escape(String s) {
|
||||
if (s == null)
|
||||
return null;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
escape(s, sb);
|
||||
return sb.toString();
|
||||
@ -225,48 +225,48 @@ public class JSONValue {
|
||||
* @param sb
|
||||
*/
|
||||
static void escape(String s, StringBuffer sb) {
|
||||
for(int i=0;i<s.length();i++){
|
||||
char ch=s.charAt(i);
|
||||
switch(ch){
|
||||
case '"':
|
||||
sb.append("\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
sb.append("\\\\");
|
||||
break;
|
||||
case '\b':
|
||||
sb.append("\\b");
|
||||
break;
|
||||
case '\f':
|
||||
sb.append("\\f");
|
||||
break;
|
||||
case '\n':
|
||||
sb.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
sb.append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
sb.append("\\t");
|
||||
break;
|
||||
case '/':
|
||||
sb.append("\\/");
|
||||
break;
|
||||
default:
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
switch (ch) {
|
||||
case '"':
|
||||
sb.append("\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
sb.append("\\\\");
|
||||
break;
|
||||
case '\b':
|
||||
sb.append("\\b");
|
||||
break;
|
||||
case '\f':
|
||||
sb.append("\\f");
|
||||
break;
|
||||
case '\n':
|
||||
sb.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
sb.append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
sb.append("\\t");
|
||||
break;
|
||||
case '/':
|
||||
sb.append("\\/");
|
||||
break;
|
||||
default:
|
||||
//Reference: http://www.unicode.org/versions/Unicode5.1.0/
|
||||
if((ch>='\u0000' && ch<='\u001F') || (ch>='\u007F' && ch<='\u009F') || (ch>='\u2000' && ch<='\u20FF')){
|
||||
String ss=Integer.toHexString(ch);
|
||||
sb.append("\\u");
|
||||
for(int k=0;k<4-ss.length();k++){
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(ss.toUpperCase());
|
||||
}
|
||||
else{
|
||||
sb.append(ch);
|
||||
}
|
||||
}
|
||||
}//for
|
||||
}
|
||||
if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') || (ch >= '\u2000' && ch <= '\u20FF')) {
|
||||
String ss = Integer.toHexString(ch);
|
||||
sb.append("\\u");
|
||||
for (int k = 0; k < 4 - ss.length(); k++) {
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(ss.toUpperCase());
|
||||
}
|
||||
else {
|
||||
sb.append(ch);
|
||||
}
|
||||
}
|
||||
}//for
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Container factory for creating containers for JSON object and JSON array.
|
||||
*
|
||||
*
|
||||
* @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContainerFactory)
|
||||
*
|
||||
*
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public interface ContainerFactory {
|
||||
/**
|
||||
* @return A Map instance to store JSON object, or null if you want to use org.json.simple.JSONObject.
|
||||
*/
|
||||
Map createObjectContainer();
|
||||
|
||||
/**
|
||||
* @return A List instance to store JSON array, or null if you want to use org.json.simple.JSONArray.
|
||||
*/
|
||||
List creatArrayContainer();
|
||||
/**
|
||||
* @return A Map instance to store JSON object, or null if you want to use org.json.simple.JSONObject.
|
||||
*/
|
||||
Map createObjectContainer();
|
||||
|
||||
/**
|
||||
* @return A List instance to store JSON array, or null if you want to use org.json.simple.JSONArray.
|
||||
*/
|
||||
List creatArrayContainer();
|
||||
}
|
||||
|
@ -3,108 +3,108 @@ package org.json.simple.parser;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A simplified and stoppable SAX-like content handler for stream processing of JSON text.
|
||||
*
|
||||
* A simplified and stoppable SAX-like content handler for stream processing of JSON text.
|
||||
*
|
||||
* @see org.xml.sax.ContentHandler
|
||||
* @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContentHandler, boolean)
|
||||
*
|
||||
*
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public interface ContentHandler {
|
||||
/**
|
||||
* Receive notification of the beginning of JSON processing.
|
||||
* The parser will invoke this method only once.
|
||||
*
|
||||
* @throws ParseException
|
||||
* - JSONParser will stop and throw the same exception to the caller when receiving this exception.
|
||||
*/
|
||||
void startJSON() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of JSON processing.
|
||||
*
|
||||
* @throws ParseException
|
||||
*/
|
||||
void endJSON() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the beginning of a JSON object.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
/**
|
||||
* Receive notification of the beginning of JSON processing.
|
||||
* The parser will invoke this method only once.
|
||||
*
|
||||
* @throws ParseException
|
||||
* - JSONParser will stop and throw the same exception to the caller when receiving this exception.
|
||||
*/
|
||||
void startJSON() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of JSON processing.
|
||||
*
|
||||
* @throws ParseException
|
||||
*/
|
||||
void endJSON() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the beginning of a JSON object.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
* - JSONParser will stop and throw the same exception to the caller when receiving this exception.
|
||||
* @see #endJSON
|
||||
*/
|
||||
boolean startObject() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of a JSON object.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
*/
|
||||
boolean startObject() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of a JSON object.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
* @see #startObject
|
||||
*/
|
||||
boolean endObject() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the beginning of a JSON object entry.
|
||||
*
|
||||
* @param key - Key of a JSON object entry.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
*/
|
||||
boolean endObject() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the beginning of a JSON object entry.
|
||||
*
|
||||
* @param key - Key of a JSON object entry.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
* @see #endObjectEntry
|
||||
*/
|
||||
boolean startObjectEntry(String key) throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of the value of previous object entry.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
*/
|
||||
boolean startObjectEntry(String key) throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of the value of previous object entry.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
* @see #startObjectEntry
|
||||
*/
|
||||
boolean endObjectEntry() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the beginning of a JSON array.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
*/
|
||||
boolean endObjectEntry() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the beginning of a JSON array.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
* @see #endArray
|
||||
*/
|
||||
boolean startArray() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of a JSON array.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
*/
|
||||
boolean startArray() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the end of a JSON array.
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*
|
||||
* @see #startArray
|
||||
*/
|
||||
boolean endArray() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the JSON primitive values:
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean
|
||||
* null
|
||||
*
|
||||
* @param value - Instance of the following:
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean
|
||||
* null
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*/
|
||||
boolean primitive(Object value) throws ParseException, IOException;
|
||||
|
||||
*/
|
||||
boolean endArray() throws ParseException, IOException;
|
||||
|
||||
/**
|
||||
* Receive notification of the JSON primitive values:
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean
|
||||
* null
|
||||
*
|
||||
* @param value - Instance of the following:
|
||||
* java.lang.String,
|
||||
* java.lang.Number,
|
||||
* java.lang.Boolean
|
||||
* null
|
||||
*
|
||||
* @return false if the handler wants to stop parsing after return.
|
||||
* @throws ParseException
|
||||
*/
|
||||
boolean primitive(Object value) throws ParseException, IOException;
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,89 +2,89 @@ package org.json.simple.parser;
|
||||
|
||||
/**
|
||||
* ParseException explains why and where the error occurs in source JSON text.
|
||||
*
|
||||
*
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*
|
||||
*/
|
||||
public class ParseException extends Exception {
|
||||
private static final long serialVersionUID = -7880698968187728548L;
|
||||
|
||||
public static final int ERROR_UNEXPECTED_CHAR = 0;
|
||||
public static final int ERROR_UNEXPECTED_TOKEN = 1;
|
||||
public static final int ERROR_UNEXPECTED_EXCEPTION = 2;
|
||||
private static final long serialVersionUID = -7880698968187728548L;
|
||||
|
||||
private int errorType;
|
||||
private Object unexpectedObject;
|
||||
private int position;
|
||||
|
||||
public ParseException(int errorType){
|
||||
this(-1, errorType, null);
|
||||
}
|
||||
|
||||
public ParseException(int errorType, Object unexpectedObject){
|
||||
this(-1, errorType, unexpectedObject);
|
||||
}
|
||||
|
||||
public ParseException(int position, int errorType, Object unexpectedObject){
|
||||
this.position = position;
|
||||
this.errorType = errorType;
|
||||
this.unexpectedObject = unexpectedObject;
|
||||
}
|
||||
|
||||
public int getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public void setErrorType(int errorType) {
|
||||
this.errorType = errorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.json.simple.parser.JSONParser#getPosition()
|
||||
*
|
||||
* @return The character position (starting with 0) of the input where the error occurs.
|
||||
*/
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.json.simple.parser.Yytoken
|
||||
*
|
||||
* @return One of the following base on the value of errorType:
|
||||
* ERROR_UNEXPECTED_CHAR java.lang.Character
|
||||
* ERROR_UNEXPECTED_TOKEN org.json.simple.parser.Yytoken
|
||||
* ERROR_UNEXPECTED_EXCEPTION java.lang.Exception
|
||||
*/
|
||||
public Object getUnexpectedObject() {
|
||||
return unexpectedObject;
|
||||
}
|
||||
|
||||
public void setUnexpectedObject(Object unexpectedObject) {
|
||||
this.unexpectedObject = unexpectedObject;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
switch(errorType){
|
||||
case ERROR_UNEXPECTED_CHAR:
|
||||
sb.append("Unexpected character (").append(unexpectedObject).append(") at position ").append(position).append(".");
|
||||
break;
|
||||
case ERROR_UNEXPECTED_TOKEN:
|
||||
sb.append("Unexpected token ").append(unexpectedObject).append(" at position ").append(position).append(".");
|
||||
break;
|
||||
case ERROR_UNEXPECTED_EXCEPTION:
|
||||
sb.append("Unexpected exception at position ").append(position).append(": ").append(unexpectedObject);
|
||||
break;
|
||||
default:
|
||||
sb.append("Unkown error at position ").append(position).append(".");
|
||||
break;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
public static final int ERROR_UNEXPECTED_CHAR = 0;
|
||||
public static final int ERROR_UNEXPECTED_TOKEN = 1;
|
||||
public static final int ERROR_UNEXPECTED_EXCEPTION = 2;
|
||||
|
||||
private int errorType;
|
||||
private Object unexpectedObject;
|
||||
private int position;
|
||||
|
||||
public ParseException(int errorType) {
|
||||
this(-1, errorType, null);
|
||||
}
|
||||
|
||||
public ParseException(int errorType, Object unexpectedObject) {
|
||||
this(-1, errorType, unexpectedObject);
|
||||
}
|
||||
|
||||
public ParseException(int position, int errorType, Object unexpectedObject) {
|
||||
this.position = position;
|
||||
this.errorType = errorType;
|
||||
this.unexpectedObject = unexpectedObject;
|
||||
}
|
||||
|
||||
public int getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public void setErrorType(int errorType) {
|
||||
this.errorType = errorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.json.simple.parser.JSONParser#getPosition()
|
||||
*
|
||||
* @return The character position (starting with 0) of the input where the error occurs.
|
||||
*/
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.json.simple.parser.Yytoken
|
||||
*
|
||||
* @return One of the following base on the value of errorType:
|
||||
* ERROR_UNEXPECTED_CHAR java.lang.Character
|
||||
* ERROR_UNEXPECTED_TOKEN org.json.simple.parser.Yytoken
|
||||
* ERROR_UNEXPECTED_EXCEPTION java.lang.Exception
|
||||
*/
|
||||
public Object getUnexpectedObject() {
|
||||
return unexpectedObject;
|
||||
}
|
||||
|
||||
public void setUnexpectedObject(Object unexpectedObject) {
|
||||
this.unexpectedObject = unexpectedObject;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
switch (errorType) {
|
||||
case ERROR_UNEXPECTED_CHAR:
|
||||
sb.append("Unexpected character (").append(unexpectedObject).append(") at position ").append(position).append(".");
|
||||
break;
|
||||
case ERROR_UNEXPECTED_TOKEN:
|
||||
sb.append("Unexpected token ").append(unexpectedObject).append(" at position ").append(position).append(".");
|
||||
break;
|
||||
case ERROR_UNEXPECTED_EXCEPTION:
|
||||
sb.append("Unexpected exception at position ").append(position).append(": ").append(unexpectedObject);
|
||||
break;
|
||||
default:
|
||||
sb.append("Unkown error at position ").append(position).append(".");
|
||||
break;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,51 +8,51 @@ package org.json.simple.parser;
|
||||
* @author FangYidong<fangyidong@yahoo.com.cn>
|
||||
*/
|
||||
public class Yytoken {
|
||||
public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null
|
||||
public static final int TYPE_LEFT_BRACE=1;
|
||||
public static final int TYPE_RIGHT_BRACE=2;
|
||||
public static final int TYPE_LEFT_SQUARE=3;
|
||||
public static final int TYPE_RIGHT_SQUARE=4;
|
||||
public static final int TYPE_COMMA=5;
|
||||
public static final int TYPE_COLON=6;
|
||||
public static final int TYPE_EOF=-1;//end of file
|
||||
|
||||
public int type=0;
|
||||
public Object value=null;
|
||||
|
||||
public Yytoken(int type,Object value){
|
||||
this.type=type;
|
||||
this.value=value;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
StringBuffer sb = new StringBuffer();
|
||||
switch(type){
|
||||
case TYPE_VALUE:
|
||||
sb.append("VALUE(").append(value).append(")");
|
||||
break;
|
||||
case TYPE_LEFT_BRACE:
|
||||
sb.append("LEFT BRACE({)");
|
||||
break;
|
||||
case TYPE_RIGHT_BRACE:
|
||||
sb.append("RIGHT BRACE(})");
|
||||
break;
|
||||
case TYPE_LEFT_SQUARE:
|
||||
sb.append("LEFT SQUARE([)");
|
||||
break;
|
||||
case TYPE_RIGHT_SQUARE:
|
||||
sb.append("RIGHT SQUARE(])");
|
||||
break;
|
||||
case TYPE_COMMA:
|
||||
sb.append("COMMA(,)");
|
||||
break;
|
||||
case TYPE_COLON:
|
||||
sb.append("COLON(:)");
|
||||
break;
|
||||
case TYPE_EOF:
|
||||
sb.append("END OF FILE");
|
||||
break;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
public static final int TYPE_VALUE = 0; //JSON primitive value: string,number,boolean,null
|
||||
public static final int TYPE_LEFT_BRACE = 1;
|
||||
public static final int TYPE_RIGHT_BRACE = 2;
|
||||
public static final int TYPE_LEFT_SQUARE = 3;
|
||||
public static final int TYPE_RIGHT_SQUARE = 4;
|
||||
public static final int TYPE_COMMA = 5;
|
||||
public static final int TYPE_COLON = 6;
|
||||
public static final int TYPE_EOF = -1; //end of file
|
||||
|
||||
public int type = 0;
|
||||
public Object value = null;
|
||||
|
||||
public Yytoken(int type, Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
switch (type) {
|
||||
case TYPE_VALUE:
|
||||
sb.append("VALUE(").append(value).append(")");
|
||||
break;
|
||||
case TYPE_LEFT_BRACE:
|
||||
sb.append("LEFT BRACE({)");
|
||||
break;
|
||||
case TYPE_RIGHT_BRACE:
|
||||
sb.append("RIGHT BRACE(})");
|
||||
break;
|
||||
case TYPE_LEFT_SQUARE:
|
||||
sb.append("LEFT SQUARE([)");
|
||||
break;
|
||||
case TYPE_RIGHT_SQUARE:
|
||||
sb.append("RIGHT SQUARE(])");
|
||||
break;
|
||||
case TYPE_COMMA:
|
||||
sb.append("COMMA(,)");
|
||||
break;
|
||||
case TYPE_COLON:
|
||||
sb.append("COLON(:)");
|
||||
break;
|
||||
case TYPE_EOF:
|
||||
sb.append("END OF FILE");
|
||||
break;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user