001    package com.thetransactioncompany.jsonrpc2;
002    
003    
004    import net.minidev.json.JSONObject;
005    
006    
007    /** 
008     * Represents a JSON-RPC 2.0 error that occurred during the processing of a 
009     * request. This class is immutable.
010     *
011     * <p>The protocol expects error objects to be structured like this:
012     *
013     * <ul>
014     *     <li>{@code code} An integer that indicates the error type.
015     *     <li>{@code message} A string providing a short description of the 
016     *         error. The message should be limited to a concise single sentence.
017     *     <li>{@code data} Additional information, which may be omitted. Its 
018     *         contents is entirely defined by the application.
019     * </ul>
020     * 
021     * <p>Note that the "Error" word in the class name was put there solely to
022     * comply with the parlance of the JSON-RPC spec. This class doesn't inherit 
023     * from {@code java.lang.Error}. It's a regular subclass of 
024     * {@code java.lang.Exception} and, if thrown, it's to indicate a condition 
025     * that a reasonable application might want to catch.
026     *
027     * <p>This class also includes convenient final static instances for all 
028     * standard JSON-RPC 2.0 errors:
029     *
030     * <ul>
031     *     <li>{@link #PARSE_ERROR} JSON parse error (-32700)
032     *     <li>{@link #INVALID_REQUEST} Invalid JSON-RPC 2.0 Request (-32600)
033     *     <li>{@link #METHOD_NOT_FOUND} Method not found (-32601)
034     *     <li>{@link #INVALID_PARAMS} Invalid parameters (-32602)
035     *     <li>{@link #INTERNAL_ERROR} Internal error (-32603)
036     * </ul>
037     *
038     * <p>Note that the range -32099..-32000 is reserved for additional server 
039     * errors.
040     *
041     * <p id="map">The mapping between JSON and Java entities (as defined by the 
042     * underlying JSON Smart library): 
043     * <pre>
044     *     true|false  <--->  java.lang.Boolean
045     *     number      <--->  java.lang.Number
046     *     string      <--->  java.lang.String
047     *     array       <--->  java.util.List
048     *     object      <--->  java.util.Map
049     *     null        <--->  null
050     * </pre>
051     *
052     * <p>The JSON-RPC 2.0 specification and user group forum can be found 
053     * <a href="http://groups.google.com/group/json-rpc">here</a>.
054     *
055     * @author Vladimir Dzhuvinov
056     */
057    public class JSONRPC2Error extends Exception {
058            
059            
060            /**
061             * Serial version UID.
062             */
063            private static final long serialVersionUID = 4682571044532698806l;
064    
065    
066            /** 
067             * JSON parse error (-32700).
068             */
069            public static final JSONRPC2Error PARSE_ERROR = new JSONRPC2Error(-32700, "JSON parse error");
070            
071            
072            /** 
073             * Invalid JSON-RPC 2.0 request error (-32600).
074             */
075            public static final JSONRPC2Error INVALID_REQUEST = new JSONRPC2Error(-32600, "Invalid request");
076            
077            
078            /** 
079             * Method not found error (-32601). 
080             */
081            public static final JSONRPC2Error METHOD_NOT_FOUND = new JSONRPC2Error(-32601, "Method not found");
082            
083            
084            /** 
085             * Invalid parameters error (-32602).
086             */
087            public static final JSONRPC2Error INVALID_PARAMS = new JSONRPC2Error(-32602, "Invalid parameters");
088            
089            
090            /** 
091             * Internal JSON-RPC 2.0 error (-32603).
092             */
093            public static final JSONRPC2Error INTERNAL_ERROR = new JSONRPC2Error(-32603, "Internal error");
094            
095            
096            /**
097             * The error code.
098             */
099            private final int code;
100            
101            
102            /**
103             * The optional error data.
104             */
105            private final Object data;
106    
107    
108            /**
109             * Appends the specified string to the message of a JSON-RPC 2.0 error.
110             *
111             * @param err The JSON-RPC 2.0 error. Must not be {@code null}.
112             * @param apx The string to append to the original error message.
113             *
114             * @return A new JSON-RPC 2.0 error with the appended message.
115             */
116            @Deprecated
117            public static JSONRPC2Error appendMessage(final JSONRPC2Error err, final String apx) {
118    
119                    return new JSONRPC2Error(err.getCode(), err.getMessage() + apx, err.getData());
120            }
121    
122    
123            /**
124             * Sets the specified data to a JSON-RPC 2.0 error.
125             *
126             * @param err  The JSON-RPC 2.0 error to have its data field set. Must
127             *             not be {@code null}.
128             * @param data Optional error data, must <a href="#map">map</a> to a 
129             *             valid JSON type.
130             *
131             * @return A new JSON-RPC 2.0 error with the set data.
132             */
133            @Deprecated
134            public static JSONRPC2Error setData(final JSONRPC2Error err, final Object data) {
135    
136                    return new JSONRPC2Error(err.getCode(), err.getMessage(), data);
137            }
138            
139            
140            /** 
141             * Creates a new JSON-RPC 2.0 error with the specified code and 
142             * message. The optional data is omitted.
143             * 
144             * @param code    The error code (standard pre-defined or
145             *                application-specific).
146             * @param message The error message.
147             */
148            public JSONRPC2Error(int code, String message) {
149                    
150                    this(code, message, null);
151            }
152            
153            
154            /** 
155             * Creates a new JSON-RPC 2.0 error with the specified code,
156             * message and data.
157             * 
158             * @param code    The error code (standard pre-defined or
159             *                application-specific).
160             * @param message The error message.
161             * @param data    Optional error data, must <a href="#map">map</a>
162             *                to a valid JSON type.
163             */
164            public JSONRPC2Error(int code, String message, Object data) {
165                    
166                    super(message);
167                    this.code = code;
168                    this.data = data;
169            }
170            
171            
172            /** 
173             * Gets the JSON-RPC 2.0 error code.
174             *
175             * @return The error code.
176             */
177            public int getCode() {
178                    
179                    return code;
180            }
181            
182            
183            /**
184             * Gets the JSON-RPC 2.0 error data.
185             *
186             * @return The error data, {@code null} if none was specified.
187             */
188            public Object getData() {
189                    
190                    return data;    
191            }
192    
193    
194            /**
195             * Sets the specified data to a JSON-RPC 2.0 error.
196             *
197             * @param data Optional error data, must <a href="#map">map</a> to a 
198             *             valid JSON type.
199             *
200             * @return A new JSON-RPC 2.0 error with the set data.
201             */
202            public JSONRPC2Error setData(final Object data) {
203    
204                    return new JSONRPC2Error(code, getMessage(), data);
205            }
206    
207    
208            /**
209             * Appends the specified string to the message of this JSON-RPC 2.0 
210             * error.
211             *
212             * @param apx The string to append to the original error message.
213             *
214             * @return A new JSON-RPC 2.0 error with the appended message.
215             */
216            public JSONRPC2Error appendMessage(final String apx) {
217    
218                    return new JSONRPC2Error(code, getMessage() + apx, data);
219            }
220            
221            
222            /** 
223             * @see #toJSONObject
224             */
225            @Deprecated
226            public JSONObject toJSON() {
227            
228                    return toJSONObject();
229            }
230            
231            
232            /** 
233             * Returns a JSON object representation of this JSON-RPC 2.0 error.
234             *
235             * @return A JSON object representing this error object.
236             */
237            public JSONObject toJSONObject() {
238            
239                    JSONObject out = new JSONObject();
240                    
241                    out.put("code", code);
242                    out.put("message", super.getMessage());
243                    if (data != null)
244                            out.put("data", data);
245                                    
246                    return out;
247            }
248            
249            
250            /** 
251             * Serialises the error object to a JSON string.
252             *
253             * @return A JSON-encoded string representing this error object.
254             */
255            @Override
256            public String toString() {
257                    
258                    return toJSON().toString();
259            }
260            
261            
262            /**
263             * Overrides {@code Object.equals()}.
264             *
265             * @param object The object to compare to.
266             *
267             * @return {@code true} if both objects are instances if this class and
268             *         their error codes are identical, {@code false} if not.
269             */
270            @Override
271            public boolean equals(Object object) {
272            
273                    return object != null &&
274                           object instanceof JSONRPC2Error && 
275                           code == ((JSONRPC2Error)object).getCode();
276            }
277    }