001 package com.thetransactioncompany.jsonrpc2.client;
002
003
004 import java.net.Proxy;
005
006 import java.util.regex.Pattern;
007
008
009 /**
010 * Optional settings for JSON-RPC 2.0 client sessions. The no-argument
011 * constructor specifies the default settings that the {@link JSONRPC2Session}
012 * uses. To apply different ones instantiate a new settings instance, set the
013 * desired ones to your liking, and then {@link JSONRPC2Session#setOptions pass}
014 * it to your {@link JSONRPC2Session} instance.
015 *
016 * <p>Overview of the available session options:
017 *
018 * <ul>
019 * <li>Customise the "Content-Type" header in HTTP POST requests.
020 * <li>Set an "Origin" header in HTTP POST requests to simulate
021 * Cross-Origin Resource Sharing (CORS) requests from a browser.
022 * <li>Accept HTTP cookies (if client sessions are established by this
023 * mean instead of through the JSON-RPC protocol itself).
024 * <li>Customise the allowable "Content-Type" header values in HTTP POST
025 * responses.
026 * <li>Preserve parse order of JSON object members in JSON-RPC 2.0 response
027 * results (for human-facing clients, e.g. the JSON-RPC 2.0 Shell).
028 * <li>Ignore version 2.0 checks when parsing responses to allow client
029 * sessions to older JSON-RPC (1.0) servers.
030 * <li>Parse non-standard attributes in JSON-RPC 2.0 responses.
031 * <li>Set an HTTP connect timeout.
032 * <li>Set an HTTP read timeout.
033 * <li>Set an HTTP proxy.
034 * <li>Enable HTTP response compression (using GZIP or DEFLATE content
035 * encoding).
036 * <li>Trust all X.509 server certificates (for HTTPS connections),
037 * including self-signed.
038 * </ul>
039 *
040 * @since 1.4
041 * @author Vladimir Dzhuvinov
042 */
043 public class JSONRPC2SessionOptions {
044
045
046 /**
047 * The "Content-Type" (MIME) header value of HTTP POST requests. If
048 * {@code null} the header will not be set.
049 */
050 private String requestContentType = DEFAULT_CONTENT_TYPE;
051
052
053 /**
054 * The default "Content-Type" (MIME) header value of HTTP POST
055 * requests. Set to {@code application/json}.
056 */
057 public static final String DEFAULT_CONTENT_TYPE = "application/json";
058
059
060 /**
061 * The allowed "Content-Type" (MIME) header values of HTTP responses.
062 * If {@code null} any header value will be accepted.
063 */
064 private String[] allowedResponseContentTypes =
065 DEFAULT_ALLOWED_RESPONSE_CONTENT_TYPES;
066
067
068 /**
069 * The default allowed "Content-Type" (MIME) header values of HTTP
070 * responses. Set to {@code application/json} and {@code text/plain}.
071 */
072 public static final String[] DEFAULT_ALLOWED_RESPONSE_CONTENT_TYPES =
073 {"application/json", "text/plain"};
074
075
076 /**
077 * Optional CORS "Origin" header. If {@code null} the header will not
078 * be set.
079 */
080 private String origin = DEFAULT_ORIGIN;
081
082
083 /**
084 * The default CORS "Origin" header value. Set to {@code null} (none).
085 */
086 public static final String DEFAULT_ORIGIN = null;
087
088
089 /**
090 * Specifies whether to accept HTTP cookies.
091 */
092 private boolean acceptCookies = DEFAULT_ACCEPT_COOKIES;
093
094
095 /**
096 * The default HTTP cookie acceptance policy.
097 */
098 public static final boolean DEFAULT_ACCEPT_COOKIES = false;
099
100
101 /**
102 * If {@code true} the order of parsed JSON object members must be
103 * preserved.
104 */
105 private boolean preserveObjectMemberOrder =
106 DEFAULT_PRESERVE_OBJECT_MEMBER_ORDER;
107
108
109 /**
110 * The default policy for preserving the order of parsed JSON object
111 * members. Set to {@code false} (no preserve).
112 */
113 public static final boolean DEFAULT_PRESERVE_OBJECT_MEMBER_ORDER = false;
114
115
116 /**
117 * If {@code true} version 2.0 checking of received responses must be
118 * disabled.
119 */
120 private boolean ignoreVersion = DEFAULT_IGNORE_VERSION ;
121
122
123 /**
124 * The default policy for version 2.0 checking. Set to {@code false}
125 * (strict checking).
126 */
127 public static final boolean DEFAULT_IGNORE_VERSION = false;
128
129
130 /**
131 * If {@code true} non-standard attributes appended to the JSON-RPC 2.0
132 * responses must be parsed too.
133 */
134 private boolean parseNonStdAttributes = DEFAULT_PARSE_NON_STD_ATTRIBUTES;
135
136
137 /**
138 * The default policy for parsing non-standard attributes in JSON-RPC
139 * 2.0 messages. Set to {@code false} (non-standard attributes ignored).
140 */
141 public static final boolean DEFAULT_PARSE_NON_STD_ATTRIBUTES = false;
142
143
144 /**
145 * The HTTP connect timeout, in milliseconds. Zero implies the option
146 * is disabled (timeout of infinity).
147 */
148 private int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
149
150
151 /**
152 * The default HTTP connect timeout. Set to zero (disabled).
153 */
154 public static final int DEFAULT_CONNECT_TIMEOUT = 0;
155
156
157 /**
158 * The HTTP read timeout, in milliseconds. Zero implies the option is
159 * disabled (timeout of infinity).
160 */
161 private int readTimeout = DEFAULT_READ_TIMEOUT;
162
163
164 /**
165 * The default HTTP read timeout. Set to zero (disabled).
166 */
167 public static final int DEFAULT_READ_TIMEOUT = 0;
168
169
170 /**
171 * Optional HTTP proxy.
172 */
173 private Proxy proxy = null;
174
175
176 /**
177 * Enable / disable HTTP GZIP and DEFLATE compression.
178 */
179 private boolean enableCompression = DEFAULT_ENABLE_COMPRESSION;
180
181
182 /**
183 * The default HTTP GZIP and DEFLATE compression enable policy.
184 */
185 public static final boolean DEFAULT_ENABLE_COMPRESSION = false;
186
187
188 /**
189 * If {@code true} self-signed certificates presented by the JSON-RPC
190 * 2.0 server must be accepted.
191 */
192 private boolean trustAll = DEFAULT_TRUST_ALL;
193
194
195 /**
196 * The default policy for trusting self-signed certificates. Set to
197 * {@code false} (self-signed certificates not accepted).
198 */
199 public static final boolean DEFAULT_TRUST_ALL = false;
200
201
202 /**
203 * Creates a new default JSON-RPC 2.0 client session options instance.
204 *
205 * <p>The "Content-Type" (MIME) header value of HTTP POST requests will
206 * be set to "application/json". To change it use
207 * {@link #setRequestContentType}.
208 *
209 * <p>"Origin" HTTP headers will not be added. To add one use
210 * {@link #setOrigin}.
211 *
212 * <p>HTTP cookies will be ignored. To accept cookies, e.g. for
213 * browser-like session handling, use {@link #acceptCookies}.
214 *
215 * <p>The allowed HTTP response content types are set to
216 * "application/json" and "text/plain". To change them use
217 * {@link #setAllowedResponseContentTypes}.
218 *
219 * <p>The parse order of JSON object members in JSON-RPC 2.0 response
220 * results will not be preserved. To change this behaviour use
221 * {@link #preserveParseOrder}.
222 *
223 * <p>Strict 2.0 version checking will be performed. To ignore the
224 * JSON-RPC version attribute use {@link #ignoreVersion(boolean)}.
225 *
226 * <p>HTTP connect timeouts will be disabled. To specify a value use
227 * {@link #setConnectTimeout}.
228 *
229 * <p>HTTP read timeouts will be disabled. To specify a value use
230 * {@link #setReadTimeout}.
231 *
232 * <p>No proxy is used. To specify one use {@link #setProxy}.
233 *
234 * <p>HTTP response compression (GZIP or DEFLATE) is disabled. To
235 * enable it use {@link #enableCompression(boolean)}.
236 *
237 * <p>Self-signed X.509 certificates presented by the JSON-RPC 2.0
238 * server will not be accepted. To relax certificate cheking use
239 * {@link #trustAllCerts}.
240 */
241 public JSONRPC2SessionOptions() {
242
243 // check fields for default init values
244 }
245
246
247 /**
248 * Gets the value of the "Content-Type" (MIME) header for HTTP POST
249 * requests.
250 *
251 * @return The "Content-Type" (MIME) header value, {@code null} if the
252 * header is not added to HTTP POST requests.
253 */
254 public String getRequestContentType() {
255
256 return requestContentType;
257 }
258
259
260 /**
261 * Sets the value of the HTTP "Content-Type" (MIME) header. Use this
262 * method if you wish to change the default "application/json" content
263 * type.
264 *
265 * @param contentType The value of the "Content-Type" (MIME) header
266 * in HTTP POST requests, {@code null} to suppress
267 * the header.
268 */
269 public void setRequestContentType(final String contentType) {
270
271 this.requestContentType = contentType;
272 }
273
274
275 /**
276 * Gets the value of the "Origin" HTTP header.
277 *
278 * <p>This header can be used to simulate Cross-Origin Resource Sharing
279 * (CORS) requests from a browser.
280 *
281 * @return The "Origin" header value, {@code null} if the header is not
282 * added to HTTP requests.
283 */
284 public String getOrigin() {
285
286 return origin;
287 }
288
289
290 /**
291 * Sets the value of the "Origin" HTTP header.
292 *
293 * <p>This header can be used to simulate Cross-Origin Resource Sharing
294 * (CORS) requests from a browser.
295 *
296 * @param origin The value of the "Origin" header in HTTP requests,
297 * {@code null} to suppress the header.
298 */
299 public void setOrigin(final String origin) {
300
301 this.origin = origin;
302 }
303
304
305 /**
306 * Returns {@code true} if HTTP cookies are accepted, else
307 * {@code false} if they are ignored.
308 *
309 * @return {@code true} if HTTP cookies are accepted, else
310 * {@code false}.
311 */
312 public boolean acceptCookies() {
313
314 return acceptCookies;
315 }
316
317
318 /**
319 * Specifies whether to accept HTTP cookies contained in the server
320 * response. Some JSON-RPC servers may use cookies instead of tokens
321 * passed through the JSON-RPC protocol itself to establish client
322 * sessions.
323 *
324 * @param acceptCookies {@code true} to accept HTTP cookies, else
325 * {@code false} to ignore them.
326 */
327 public void acceptCookies(final boolean acceptCookies) {
328
329 this.acceptCookies = acceptCookies;
330 }
331
332
333 /**
334 * Gets the allowed "Content-Type" (MIME) header values of HTTP
335 * responses.
336 *
337 * <p>The {@code JSONRPC2Session.send(...)} method will throw a
338 * {@link JSONRPC2SessionException#UNEXPECTED_CONTENT_TYPE} if the
339 * received HTTP response "Content-Type" (MIME) header value is not
340 * allowed.
341 *
342 * @return The allowed header values, if {@code null} any header value
343 * is allowed.
344 */
345 public String[] getAllowedResponseContentTypes() {
346
347 return allowedResponseContentTypes;
348 }
349
350
351 /**
352 * Sets the allowed "Content-Type" (MIME) header values of HTTP
353 * responses.
354 *
355 * <p>The {@code JSONRPC2Session.send(...)} method will throw a
356 * {@link JSONRPC2SessionException#UNEXPECTED_CONTENT_TYPE} if the
357 * received HTTP response "Content-Type" (MIME) header value is not
358 * allowed.
359 *
360 * @param contentTypes The allowed header values, {@code null} to allow
361 * any header value.
362 */
363 public void setAllowedResponseContentTypes(final String[] contentTypes) {
364
365 this.allowedResponseContentTypes = contentTypes;
366 }
367
368
369 /**
370 * Checks if the specified HTTP "Content-Type" (MIME) header value is
371 * allowed.
372 *
373 * @param contentType The "Content-Type" (MIME) header value.
374 *
375 * @return {@code true} if the content type is allowed, else
376 * {@code false}.
377 */
378 public boolean isAllowedResponseContentType(final String contentType) {
379
380 // Allow any?
381 if (allowedResponseContentTypes == null)
382 return true;
383
384 if (contentType == null)
385 return false; // missing
386
387 for (String t: allowedResponseContentTypes) {
388
389 // Note: the content type may include optional parameters,
390 // which must be ignored during matching, e.g.
391 // "application/json; charset=ISO-8859-1; ..."
392 if (contentType.matches("^" + Pattern.quote(t) + "(\\s|;|$)?.*"))
393 return true;
394 }
395
396 return false; // nothing matched
397 }
398
399
400 /**
401 * Returns {@code true} if the member order of parsed JSON objects in
402 * JSON-RPC 2.0 response results is preserved.
403 *
404 * @return {@code true} if the parse order of JSON object members is
405 * preserved, else {@code false}.
406 */
407 public boolean preservesParseOrder() {
408
409 return preserveObjectMemberOrder;
410 }
411
412
413 /**
414 * Controls the behaviour of the JSON parser when processing object
415 * members in JSON-RPC 2.0 response results. The default behaviour is
416 * to store the members in a {@code java.util.HashMap} in a
417 * non-deterministic order. To preserve the original parse order pass a
418 * boolean {@code true} to this method. Note that this will slow down
419 * parsing and retrieval performance somewhat.
420 *
421 * @param preserve If {@code true} the parse order of JSON object
422 * members will be preserved, else not.
423 */
424 public void preserveParseOrder(final boolean preserve) {
425
426 preserveObjectMemberOrder = preserve;
427 }
428
429
430 /**
431 * Returns {@code true} if strict parsing of received JSON-RPC 2.0
432 * responses is disabled and the "jsonrpc" version attribute is not
433 * checked for "2.0" equality. Returns {@code false} if received
434 * JSON-RPC 2.0 responses must strictly conform to the JSON-RPC 2.0
435 * specification.
436 *
437 * @return {@code true} if the {@code "jsonrpc":"2.0"} version
438 * attribute is ignored, {@code false} if parsing is strict.
439 */
440 public boolean ignoresVersion() {
441
442 return ignoreVersion;
443 }
444
445
446 /**
447 * Controls the strictness of the JSON-RPC 2.0 response parser. The
448 * default behaviour is to check responses for strict compliance to
449 * the JSON-RPC 2.0 specification. By passing a boolean {@code true}
450 * parsing is relaxed and the "jsonrpc" version attribute will not be
451 * checked for "2.0" equality.
452 *
453 * @param ignore {@code true} to ignore the 2.0 {@code "jsonrpc":"2.0"}
454 * version attribute, {@code false} for strict parsing.
455 */
456 public void ignoreVersion(final boolean ignore) {
457
458 ignoreVersion = ignore;
459 }
460
461
462 /**
463 * Specifies whether to parse non-standard attributes found in JSON-RPC
464 * 2.0 responses.
465 *
466 * @param enable {@code true} to parse non-standard attributes, else
467 * {@code false}.
468 */
469 public void parseNonStdAttributes(final boolean enable) {
470
471 parseNonStdAttributes = enable;
472 }
473
474
475 /**
476 * Returns {@code true} if non-standard attributes in JSON-RPC 2.0
477 * responses are parsed.
478 *
479 * @return {@code true} if non-standard attributes are parsed, else
480 * {@code false}.
481 */
482 public boolean parsesNonStdAttributes() {
483
484 return parseNonStdAttributes;
485 }
486
487
488 /**
489 * Sets the HTTP connect timeout.
490 *
491 * @since 1.8
492 *
493 * @param timeout The HTTP connect timeout, in milliseconds. Zero
494 * implies the option is disabled (timeout of infinity).
495 */
496 public void setConnectTimeout(final int timeout) {
497
498 if (timeout < 0)
499 throw new IllegalArgumentException("The HTTP connect timeout must be zero or positive");
500
501 connectTimeout = timeout;
502 }
503
504
505 /**
506 * Gets the HTTP connect timeout.
507 *
508 * @since 1.8
509 *
510 * @return The HTTP connect timeout, in milliseconds. Zero implies the
511 * option is disabled (timeout of infinity).
512 */
513 public int getConnectTimeout() {
514
515 return connectTimeout;
516 }
517
518
519 /**
520 * Sets the HTTP read timeout.
521 *
522 * @since 1.8
523 *
524 * @param timeout The HTTP read timeout, in milliseconds. Zero implies
525 * the option is disabled (timeout of infinity).
526 */
527 public void setReadTimeout(final int timeout) {
528
529 if (timeout < 0)
530 throw new IllegalArgumentException("The HTTP read timeout must be zero or positive");
531
532 readTimeout = timeout;
533 }
534
535
536 /**
537 * Gets the HTTP read timeout.
538 *
539 * @since 1.8
540 *
541 * @return The HTTP read timeout, in milliseconds. Zero implies the
542 * option is disabled (timeout of infinity).
543 */
544 public int getReadTimeout() {
545
546 return readTimeout;
547 }
548
549
550 /**
551 * Sets an HTTP proxy.
552 *
553 * @since 1.10
554 *
555 * @param proxy The HTTP proxy to use, {@code null} if none.
556 */
557 public void setProxy(final Proxy proxy) {
558
559 this.proxy = proxy;
560 }
561
562
563 /**
564 * Gets the HTTP proxy.
565 *
566 * @since 1.10
567 *
568 * @return The HTTP proxy to use, {@code null} if none.
569 */
570 public Proxy getProxy() {
571
572 return proxy;
573 }
574
575
576 /**
577 * Enables or disables HTTP response compression using GZIP or DEFLATE
578 * content encoding. If compression is enabled but the HTTP server
579 * doesn't support compression this setting will have no effect.
580 *
581 * @param enable If {@code true} HTTP compression will be enabled,
582 * else compression will be disabled.
583 */
584 public void enableCompression(final boolean enable) {
585
586 enableCompression = enable;
587 }
588
589
590 /**
591 * Checks if HTTP response compression using GZIP or DEFLATE content
592 * encoding is enabled or disabled. If compression is enabled but the
593 * HTTP server doesn't support compression this setting will have no
594 * effect.
595 *
596 * @return {@code true} if HTTP compression is enabled, else
597 * {@code false}.
598 */
599 public boolean enableCompression() {
600
601 return enableCompression;
602 }
603
604
605 /**
606 * Controls checking of X.509 certificates presented by the server when
607 * establishing a secure HTTPS connection. The default behaviour is to
608 * accept only certicates issued by a trusted certificate authority
609 * (CA), as determined by the default Java trust store. By passing a
610 * boolean {@code false} this security check is disabled and all
611 * certificates will be trusted, including self-signed ones. Use this
612 * for testing and development purposes only.
613 *
614 * @param trustAll If {@code true} all X.509 certificates presented by
615 * the web server will be trusted, including self-signed
616 * ones. If {@code false} the default security policy
617 * will be restored.
618 */
619 public void trustAllCerts(final boolean trustAll) {
620
621 this.trustAll = trustAll;
622 }
623
624
625 /**
626 * Returns {@code true} if all X.509 certificates presented by the web
627 * server will be trusted, including self-signed ones. If {@code false}
628 * the default security policy applies.
629 *
630 * @return {@code true} if all X.509 certificates are trusted, else
631 * {@code false}.
632 */
633 public boolean trustsAllCerts() {
634
635 return trustAll;
636 }
637 }