001package com.thetransactioncompany.jsonrpc2.client; 002 003 004import java.net.Proxy; 005 006import 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 */ 043public 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}