http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java b/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java index 3cd0ed3..f7615af 100644 --- a/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java +++ b/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java @@ -39,21 +39,29 @@ import org.xml.sax.*; public class TestUtils { - private static JsonSerializer js = new JsonSerializer.Simple() - .setTrimNullProperties(false); - - private static JsonSerializer jsSorted = new JsonSerializer.Simple() - .setSortCollections(true) - .setSortMaps(true) - .setTrimNullProperties(false); - - - private static JsonSerializer js2 = new JsonSerializer.Simple() - .addPojoSwaps(IteratorSwap.class, EnumerationSwap.class); - - private static JsonSerializer js3 = new JsonSerializer.Simple() - .addPojoSwaps(IteratorSwap.class, EnumerationSwap.class) - .setSortProperties(true); + private static JsonSerializer js = new JsonSerializerBuilder() + .simple() + .trimNullProperties(false) + .build(); + + private static JsonSerializer jsSorted = new JsonSerializerBuilder() + .simple() + .sortCollections(true) + .sortMaps(true) + .trimNullProperties(false) + .build(); + + + private static JsonSerializer js2 = new JsonSerializerBuilder() + .simple() + .pojoSwaps(IteratorSwap.class, EnumerationSwap.class) + .build(); + + private static JsonSerializer js3 = new JsonSerializerBuilder() + .simple() + .pojoSwaps(IteratorSwap.class, EnumerationSwap.class) + .sortProperties(true) + .build(); /** * Verifies that two objects are equivalent. @@ -221,7 +229,7 @@ public class TestUtils { * Test whitespace and generated schema. */ public static void validateXml(Object o, XmlSerializer s) throws Exception { - s = s.clone().setUseWhitespace(true).setEnableNamespaces(true).setAddNamespaceUrisToRoot(true); + s = s.builder().ws().ns().addNamespaceUrisToRoot(true).build(); String xml = s.serialize(o); String xmlSchema = null;
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java b/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java index 4bbc700..d902804 100644 --- a/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java +++ b/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/_TestSuite.java @@ -33,11 +33,11 @@ public class _TestSuite { @BeforeClass public static void setUp() { - TestMicroservice.startMicroservice(); + SamplesMicroservice.startMicroservice(); } @AfterClass public static void tearDown() { - TestMicroservice.stopMicroservice(); + SamplesMicroservice.stopMicroservice(); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/json/JsonConfigurationExample.java ---------------------------------------------------------------------- diff --git a/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/json/JsonConfigurationExample.java b/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/json/JsonConfigurationExample.java index 8adb404..77febad 100644 --- a/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/json/JsonConfigurationExample.java +++ b/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/json/JsonConfigurationExample.java @@ -27,15 +27,11 @@ public class JsonConfigurationExample { public static void main(String[] args) throws Exception { Pojo aPojo = new Pojo("a","</pojo>"); // Json Serializers can be configured using properties defined in JsonSerializerContext - String withWhitespace = new JsonSerializer() - .setProperty(JsonSerializerContext.JSON_useWhitespace, true) - .serialize(aPojo); + String withWhitespace = new JsonSerializerBuilder().ws().build().serialize(aPojo); // the output will be padded with spaces after format characters System.out.println(withWhitespace); - String escaped = new JsonSerializer() - .setProperty(JsonSerializerContext.JSON_escapeSolidus, true) - .serialize(aPojo); + String escaped = new JsonSerializerBuilder().escapeSolidus(true).build().serialize(aPojo); // the output will have escaped / System.out.println(escaped); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java ---------------------------------------------------------------------- diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java index 66a9c7d..e643f97 100755 --- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java +++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java @@ -252,12 +252,15 @@ public abstract class Microservice { * * @return A new {@link VarResolver}. */ - protected VarResolver createVarResolver() { - return new VarResolver() - .addVars(SystemPropertiesVar.class, EnvVariablesVar.class, ConfigFileVar.class, ManifestFileVar.class, ArgsVar.class, SwitchVar.class, IfVar.class) - .setContextObject(ConfigFileVar.SESSION_config, cf) - .setContextObject(ManifestFileVar.SESSION_manifest, mf) - .setContextObject(ArgsVar.SESSION_args, args); + protected VarResolverBuilder createVarResolver() { + VarResolverBuilder b = new VarResolverBuilder() + .defaultVars() + .vars(ConfigFileVar.class, ManifestFileVar.class, ArgsVar.class, SwitchVar.class, IfVar.class) + .contextObject(ManifestFileVar.SESSION_manifest, mf) + .contextObject(ArgsVar.SESSION_args, args); + if (cf != null) + b.contextObject(ConfigFileVar.SESSION_config, cf); + return b; } /** @@ -436,7 +439,7 @@ public abstract class Microservice { // Resolve the config file if the path was specified. // -------------------------------------------------------------------------------- if (cfPath != null) - cf = ConfigMgr.DEFAULT.get(cfPath).getResolving(createVarResolver()); + cf = ConfigMgr.DEFAULT.get(cfPath).getResolving(createVarResolver().build()); // -------------------------------------------------------------------------------- // Find config file. @@ -459,7 +462,7 @@ public abstract class Microservice { cf = ConfigMgr.DEFAULT.create(); } else { System.out.println("Running class ["+getClass().getSimpleName()+"] using config file ["+cfPath+"]"); - cf = ConfigMgr.DEFAULT.get(cfPath).getResolving(createVarResolver()); + cf = ConfigMgr.DEFAULT.get(cfPath).getResolving(createVarResolver().build()); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java ---------------------------------------------------------------------- diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java index a67199a..c0b9326 100755 --- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java +++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/Resource.java @@ -52,10 +52,10 @@ public abstract class Resource extends RestServletDefault { * Adds $ARG and $MF variables to variable resolver defined on {@link RestServlet#createVarResolver()}. */ @Override - protected VarResolver createVarResolver() { + protected VarResolverBuilder createVarResolver() { return super.createVarResolver() - .addVars(ArgsVar.class, ManifestFileVar.class) - .setContextObject(ArgsVar.SESSION_args, Microservice.getArgs()) - .setContextObject(ManifestFileVar.SESSION_manifest, Microservice.getManifest()); + .vars(ArgsVar.class, ManifestFileVar.class) + .contextObject(ArgsVar.SESSION_args, Microservice.getArgs()) + .contextObject(ManifestFileVar.SESSION_manifest, Microservice.getManifest()); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java ---------------------------------------------------------------------- diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java index 6ccbffd..610575d 100755 --- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java +++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/ResourceGroup.java @@ -53,10 +53,10 @@ public abstract class ResourceGroup extends RestServletGroupDefault { * Adds $ARG and $MF variables to variable resolver defined on {@link RestServlet#createVarResolver()}. */ @Override - protected VarResolver createVarResolver() { + protected VarResolverBuilder createVarResolver() { return super.createVarResolver() - .addVars(ArgsVar.class, ManifestFileVar.class) - .setContextObject(ArgsVar.SESSION_args, Microservice.getArgs()) - .setContextObject(ManifestFileVar.SESSION_manifest, Microservice.getManifest()); + .vars(ArgsVar.class, ManifestFileVar.class) + .contextObject(ArgsVar.SESSION_args, Microservice.getArgs()) + .contextObject(ManifestFileVar.SESSION_manifest, Microservice.getManifest()); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-microservice/src/main/java/org/apache/juneau/microservice/RestMicroservice.java ---------------------------------------------------------------------- diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/RestMicroservice.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/RestMicroservice.java index 56e9789..cc30dcd 100755 --- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/RestMicroservice.java +++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/RestMicroservice.java @@ -121,9 +121,10 @@ public class RestMicroservice extends Microservice { @Override /* Thread */ public void run() { try { + if (server.isStopping() || server.isStopped()) + return; onStopServer(); logger.warning("Stopping server."); - System.out.println(); server.stop(); logger.warning("Server stopped."); onPostStopServer(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html ---------------------------------------------------------------------- diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html b/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html index a49aeff..b546032 100755 --- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html +++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/package.html @@ -366,6 +366,8 @@ <cs>[REST]</cs> <cc># The HTTP port number to use. + # Can be a comma-delimited list of ports to try. + # 0 means try a random port. # Default is Rest-Port setting in manifest file, or 8000.</cc> <ck>port</ck> = <cv>10000</cv> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java ---------------------------------------------------------------------- diff --git a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java index 5419514..c7f1b08 100755 --- a/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java +++ b/juneau-microservice/src/main/java/org/apache/juneau/microservice/resources/ConfigResource.java @@ -13,8 +13,8 @@ package org.apache.juneau.microservice.resources; import static javax.servlet.http.HttpServletResponse.*; -import static org.apache.juneau.html.HtmlDocSerializerContext.*; import static org.apache.juneau.dto.html5.HtmlBuilder.*; +import static org.apache.juneau.html.HtmlDocSerializerContext.*; import java.io.*; import java.util.Map; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponsePattern.java ---------------------------------------------------------------------- diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponsePattern.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponsePattern.java index b56797f..ce49c5e 100644 --- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponsePattern.java +++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponsePattern.java @@ -18,7 +18,7 @@ import java.util.regex.*; /** * Used to find regular expression matches in REST responses made through {@link RestCall}. * <p> - * Response patterns are applied to REST calls through the {@link RestCall#addResponsePattern(ResponsePattern)} method. + * Response patterns are applied to REST calls through the {@link RestCall#responsePattern(ResponsePattern)} method. * * <h5 class='section'>Example:</h5> * This example shows how to use a response pattern finder to find and capture patterns for <js>"x=number"</js> and <js>"y=string"</js> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java ---------------------------------------------------------------------- diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java index b3c33a5..9aba208 100644 --- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java +++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java @@ -65,7 +65,7 @@ public final class RestCall { private int retries = 1; private int redirectOnPostsTries = 5; private long retryInterval = -1; - private RetryOn retryOn = RetryOn.DEFAULT; + private RetryOn retryOn; private boolean ignoreErrors; private boolean byLines = false; private TeeWriter writers = new TeeWriter(); @@ -85,8 +85,11 @@ public final class RestCall { protected RestCall(RestClient client, HttpRequestBase request) throws RestCallException { this.client = client; this.request = request; - for (RestCallInterceptor i : this.client.interceptors) - addInterceptor(i); + for (RestCallInterceptor i : this.client.getInterceptors()) + interceptor(i); + this.retryOn = client.retryOn; + this.retries = client.retries; + this.retryInterval = client.retryInterval; } /** @@ -103,16 +106,26 @@ public final class RestCall { * @return This object (for method chaining). * @throws RestCallException If a retry was attempted, but the entity was not repeatable. */ - public RestCall setInput(final Object input) throws RestCallException { + public RestCall input(final Object input) throws RestCallException { + if (! (request instanceof HttpEntityEnclosingRequestBase)) throw new RestCallException(0, "Method does not support content entity.", request.getMethod(), request.getURI(), null); - HttpEntity entity = (input instanceof HttpEntity ? (HttpEntity)input : new RestRequestEntity(input, client.serializer)); + + HttpEntity entity = (input instanceof HttpEntity) ? (HttpEntity)input : new RestRequestEntity(input, client.getSerializer()); + ((HttpEntityEnclosingRequestBase)request).setEntity(entity); + if (retries > 1 && ! entity.isRepeatable()) throw new RestCallException("Rest call set to retryable, but entity is not repeatable."); + return this; } + + //-------------------------------------------------------------------------------- + // HTTP headers + //-------------------------------------------------------------------------------- + /** * Convenience method for setting a header value on the request. * <p> @@ -122,12 +135,382 @@ public final class RestCall { * @param value The header value. * @return This object (for method chaining). */ - public RestCall setHeader(String name, Object value) { + public RestCall header(String name, Object value) { request.setHeader(name, value.toString()); return this; } /** + * Sets the value for the <code>Accept</code> request header. + * <p> + * This overrides the media type specified on the parser, but is overridden by calling <code>header(<js>"Accept"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall accept(Object value) { + return header("Accept", value); + } + + /** + * Sets the value for the <code>Accept-Charset</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Accept-Charset"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall acceptCharset(Object value) { + return header("Accept-Charset", value); + } + + /** + * Sets the value for the <code>Accept-Encoding</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Accept-Encoding"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall acceptEncoding(Object value) { + return header("Accept-Encoding", value); + } + + /** + * Sets the value for the <code>Accept-Language</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Accept-Language"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall acceptLanguage(Object value) { + return header("Accept-Language", value); + } + + /** + * Sets the value for the <code>Authorization</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Authorization"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall authorization(Object value) { + return header("Authorization", value); + } + + /** + * Sets the value for the <code>Cache-Control</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Cache-Control"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall cacheControl(Object value) { + return header("Cache-Control", value); + } + + /** + * Sets the value for the <code>Connection</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Connection"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall connection(Object value) { + return header("Connection", value); + } + + /** + * Sets the value for the <code>Content-Length</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Content-Length"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall contentLength(Object value) { + return header("Content-Length", value); + } + + /** + * Sets the value for the <code>Content-Type</code> request header. + * <p> + * This overrides the media type specified on the serializer, but is overridden by calling <code>header(<js>"Content-Type"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall contentType(Object value) { + return header("Content-Type", value); + } + + /** + * Sets the value for the <code>Date</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Date"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall date(Object value) { + return header("Date", value); + } + + /** + * Sets the value for the <code>Expect</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Expect"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall expect(Object value) { + return header("Expect", value); + } + + /** + * Sets the value for the <code>Forwarded</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Forwarded"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall forwarded(Object value) { + return header("Forwarded", value); + } + + /** + * Sets the value for the <code>From</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"From"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall from(Object value) { + return header("From", value); + } + + /** + * Sets the value for the <code>Host</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Host"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall host(Object value) { + return header("Host", value); + } + + /** + * Sets the value for the <code>If-Match</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"If-Match"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall ifMatch(Object value) { + return header("If-Match", value); + } + + /** + * Sets the value for the <code>If-Modified-Since</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"If-Modified-Since"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall ifModifiedSince(Object value) { + return header("If-Modified-Since", value); + } + + /** + * Sets the value for the <code>If-None-Match</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"If-None-Match"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall ifNoneMatch(Object value) { + return header("If-None-Match", value); + } + + /** + * Sets the value for the <code>If-Range</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"If-Range"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall ifRange(Object value) { + return header("If-Range", value); + } + + /** + * Sets the value for the <code>If-Unmodified-Since</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"If-Unmodified-Since"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall ifUnmodifiedSince(Object value) { + return header("If-Unmodified-Since", value); + } + + /** + * Sets the value for the <code>Max-Forwards</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Max-Forwards"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall maxForwards(Object value) { + return header("If-Unmodified-Since", value); + } + + /** + * Sets the value for the <code>Origin</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Origin"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall origin(Object value) { + return header("If-Unmodified-Since", value); + } + + /** + * Sets the value for the <code>Pragma</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Pragma"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall pragma(Object value) { + return header("Pragma", value); + } + + /** + * Sets the value for the <code>Proxy-Authorization</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Proxy-Authorization"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall proxyAuthorization(Object value) { + return header("Proxy-Authorization", value); + } + + /** + * Sets the value for the <code>Range</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Range"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall range(Object value) { + return header("Range", value); + } + + /** + * Sets the value for the <code>Referer</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Referer"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall referer(Object value) { + return header("Referer", value); + } + + /** + * Sets the value for the <code>TE</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"TE"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall te(Object value) { + return header("TE", value); + } + + /** + * Sets the value for the <code>User-Agent</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"User-Agent"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall userAgent(Object value) { + return header("User-Agent", value); + } + + /** + * Sets the value for the <code>Upgrade</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Upgrade"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall upgrade(Object value) { + return header("Upgrade", value); + } + + /** + * Sets the value for the <code>Via</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Via"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall via(Object value) { + return header("Via", value); + } + + /** + * Sets the value for the <code>Warning</code> request header. + * <p> + * This is a shortcut for calling <code>header(<js>"Warning"</js>, value);</code> + * + * @param value The new header value. + * @return This object (for method chaining). + */ + public RestCall warning(Object value) { + return header("Warning", value); + } + + /** + * Sets the client version by setting the value for the <js>"X-Client-Version"</js> header. + * + * @param version The version string (e.g. <js>"1.2.3"</js>) + * @return This object (for method chaining). + */ + public RestCall clientVersion(String version) { + return header("X-Client-Version", version); + } + + /** * Make this call retryable if an error response (>=400) is received. * * @param retries The number of retries to attempt. @@ -137,7 +520,8 @@ public final class RestCall { * @return This object (for method chaining). * @throws RestCallException If current entity is not repeatable. */ - public RestCall setRetryable(int retries, long interval, RetryOn retryOn) throws RestCallException { + @SuppressWarnings("hiding") + public RestCall retryable(int retries, long interval, RetryOn retryOn) throws RestCallException { if (request instanceof HttpEntityEnclosingRequestBase) { HttpEntity e = ((HttpEntityEnclosingRequestBase)request).getEntity(); if (e != null && ! e.isRepeatable()) @@ -174,7 +558,7 @@ public final class RestCall { * @param maxAttempts Allow a redirect to occur this number of times. * @return This object (for method chaining). */ - public RestCall setRedirectMaxAttempts(int maxAttempts) { + public RestCall redirectMaxAttempts(int maxAttempts) { this.redirectOnPostsTries = maxAttempts; return this; } @@ -185,7 +569,7 @@ public final class RestCall { * @param interceptor The interceptor to add to this call. * @return This object (for method chaining). */ - public RestCall addInterceptor(RestCallInterceptor interceptor) { + public RestCall interceptor(RestCallInterceptor interceptor) { interceptors.add(interceptor); interceptor.onInit(this); return this; @@ -352,7 +736,7 @@ public final class RestCall { * @return This object (for method chaining). */ public RestCall failurePattern(final String errorPattern) { - addResponsePattern( + responsePattern( new ResponsePattern(errorPattern) { @Override public void onMatch(RestCall rc, Matcher m) throws RestCallException { @@ -383,7 +767,7 @@ public final class RestCall { * @return This object (for method chaining). */ public RestCall successPattern(String successPattern) { - addResponsePattern( + responsePattern( new ResponsePattern(successPattern) { @Override public void onNoMatch(RestCall rc) throws RestCallException { @@ -405,9 +789,9 @@ public final class RestCall { * @param responsePattern The response pattern finder. * @return This object (for method chaining). */ - public RestCall addResponsePattern(final ResponsePattern responsePattern) { + public RestCall responsePattern(final ResponsePattern responsePattern) { captureResponse(); - addInterceptor( + interceptor( new RestCallInterceptor() { @Override public void onClose(RestCall restCall) throws RestCallException { @@ -506,7 +890,7 @@ public final class RestCall { retries--; Exception ex = null; try { - response = client.execute(request); + response = client.execute(request); sc = (response == null || response.getStatusLine() == null) ? -1 : response.getStatusLine().getStatusCode(); } catch (Exception e) { ex = e; @@ -644,9 +1028,9 @@ public final class RestCall { * @throws RestCallException If no parser was defined on the client. */ protected Parser getParser() throws RestCallException { - if (client.parser == null) + if (client.getParser() == null) throw new RestCallException(0, "No parser defined on client", request.getMethod(), request.getURI(), null); - return client.parser; + return client.getParser(); } /** @@ -656,9 +1040,9 @@ public final class RestCall { * @throws RestCallException If no serializer was defined on the client. */ protected Serializer getSerializer() throws RestCallException { - if (client.serializer == null) + if (client.getSerializer() == null) throw new RestCallException(0, "No serializer defined on client", request.getMethod(), request.getURI(), null); - return client.serializer; + return client.getSerializer(); } /** @@ -861,7 +1245,7 @@ public final class RestCall { * @param header The header to set on the request. * @return This object (for method chaining). */ - public RestCall setHeader(Header header) { + public RestCall header(Header header) { request.setHeader(header); return this; } @@ -897,7 +1281,7 @@ public final class RestCall { * @return This object (for method chaining). */ public RestCall logTo(Level level, Logger log) { - addInterceptor(new RestCallLogger(level, log)); + interceptor(new RestCallLogger(level, log)); return this; } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCallLogger.java ---------------------------------------------------------------------- diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCallLogger.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCallLogger.java index 7bd7bc4..2eb8a55 100644 --- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCallLogger.java +++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCallLogger.java @@ -26,7 +26,7 @@ import org.apache.http.util.*; * Causes a log entry to be created that shows all the request and response headers and content * at the end of the request. * <p> - * Use the {@link RestClient#logTo(Level, Logger)} and {@link RestCall#logTo(Level, Logger)} + * Use the {@link RestClientBuilder#logTo(Level, Logger)} and {@link RestCall#logTo(Level, Logger)} * <p> * methods to create instances of this class. */ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java ---------------------------------------------------------------------- diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java index 6f175cc..8d4748d 100644 --- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java +++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java @@ -18,32 +18,14 @@ import java.io.*; import java.lang.reflect.*; import java.lang.reflect.Proxy; import java.net.*; -import java.security.*; import java.util.*; import java.util.concurrent.*; -import java.util.logging.*; import java.util.regex.*; -import javax.net.ssl.*; - import org.apache.http.*; -import org.apache.http.auth.*; -import org.apache.http.client.*; -import org.apache.http.client.CookieStore; -import org.apache.http.client.config.*; -import org.apache.http.client.entity.*; import org.apache.http.client.methods.*; -import org.apache.http.config.*; -import org.apache.http.conn.*; -import org.apache.http.conn.routing.*; -import org.apache.http.conn.socket.*; -import org.apache.http.conn.ssl.*; -import org.apache.http.conn.util.*; -import org.apache.http.cookie.*; import org.apache.http.entity.*; import org.apache.http.impl.client.*; -import org.apache.http.impl.conn.*; -import org.apache.http.protocol.*; import org.apache.juneau.*; import org.apache.juneau.internal.*; import org.apache.juneau.json.*; @@ -68,246 +50,79 @@ import org.apache.juneau.urlencoding.*; * <li><a class="doclink" href="package-summary.html#RestClient">org.apache.juneau.rest.client > REST client API</a> for more information and code examples. * </ul> */ -public class RestClient extends CoreApi { - - Map<String,Object> headers = new TreeMap<String,Object>(String.CASE_INSENSITIVE_ORDER); - volatile CloseableHttpClient httpClient; - HttpClientConnectionManager httpClientConnectionManager; - Serializer serializer; - UrlEncodingSerializer urlEncodingSerializer = new UrlEncodingSerializer(); // Used for form posts only. - Parser parser; - String accept, contentType; - List<RestCallInterceptor> interceptors = new ArrayList<RestCallInterceptor>(); - String remoteableServletUri; - private Map<Method,String> remoteableServiceUriMap = new ConcurrentHashMap<Method,String>(); - private String rootUrl; - private SSLOpts sslOpts; - private boolean pooled; +public class RestClient extends CoreObject { + + private final Map<String,String> headers; + private final CloseableHttpClient httpClient; + private final boolean keepHttpClientOpen; + private final Serializer serializer; + private final UrlEncodingSerializer urlEncodingSerializer; // Used for form posts only. + private final Parser parser; + private final RestCallInterceptor[] interceptors; + private final String remoteableServletUri; + private final Map<Method,String> remoteableServiceUriMap; + private final String rootUrl; private volatile boolean isClosed = false; - private StackTraceElement[] creationStack; - - /** - * The {@link HttpClientBuilder} returned by {@link #createHttpClientBuilder()}. - */ - protected HttpClientBuilder httpClientBuilder; - - /** - * Create a new client with no serializer, parser, or HTTP client. - * <p> - * If you do not specify an {@link HttpClient} via the {@link #setHttpClient(CloseableHttpClient)}, one - * will be created using the {@link #createHttpClient()} method. - */ - public RestClient() { - httpClientBuilder = createHttpClientBuilder(); - if (Boolean.getBoolean("org.apache.juneau.rest.client.RestClient.trackCreation")) - creationStack = Thread.currentThread().getStackTrace(); - } - - /** - * Create a new client with the specified HTTP client. - * <p> - * Equivalent to calling the following: - * <p class='bcode'> - * RestClient rc = <jk>new</jk> RestClient().setHttpClient(httpClient); - * </p> - * - * @param httpClient The HTTP client to use for communicating with remote server. - */ - public RestClient(CloseableHttpClient httpClient) { - this(); - setHttpClient(httpClient); - } - - /** - * Create a new client with the specified serializer and parser instances. - * <p> - * Equivalent to calling the following: - * <p class='bcode'> - * RestClient rc = <jk>new</jk> RestClient().setSerializer(s).setParser(p); - * </p> - * <p> - * If you do not specify an {@link HttpClient} via the {@link #setHttpClient(CloseableHttpClient)}, one - * will be created using the {@link #createHttpClient()} method. - * - * @param s The serializer for converting POJOs to HTTP request message body text. - * @param p The parser for converting HTTP response message body text to POJOs. - */ - public RestClient(Serializer s, Parser p) { - this(); - setSerializer(s); - setParser(p); - } - - /** - * Create a new client with the specified serializer and parser instances. - * <p> - * Equivalent to calling the following: - * <p class='bcode'> - * RestClient rc = <jk>new</jk> RestClient().setHttpClient(httpClient).setSerializer(s).setParser(p); - * </p> - * - * @param httpClient The HTTP client to use for communicating with remote server. - * @param s The serializer for converting POJOs to HTTP request message body text. - * @param p The parser for converting HTTP response message body text to POJOs. - */ - public RestClient(CloseableHttpClient httpClient, Serializer s, Parser p) { - this(); - setHttpClient(httpClient); - setSerializer(s); - setParser(p); - } - - /** - * Create a new client with the specified serializer and parser classes. - * <p> - * Equivalent to calling the following: - * <p class='bcode'> - * RestClient rc = <jk>new</jk> RestClient().setSerializer(s).setParser(p); - * </p> - * <p> - * If you do not specify an {@link HttpClient} via the {@link #setHttpClient(CloseableHttpClient)}, one - * will be created using the {@link #createHttpClient()} method. - * - * @param s The serializer for converting POJOs to HTTP request message body text. - * @param p The parser for converting HTTP response message body text to POJOs. - * @throws InstantiationException If serializer or parser could not be instantiated. - */ - public RestClient(Class<? extends Serializer> s, Class<? extends Parser> p) throws InstantiationException { - this(); - setSerializer(s); - setParser(p); - } - - /** - * Create a new client with the specified serializer and parser classes. - * <p> - * Equivalent to calling the following: - * <p class='bcode'> - * RestClient rc = <jk>new</jk> RestClient().setHttpClient(httpClient).setSerializer(s).setParser(p); - * </p> - * - * @param httpClient The HTTP client to use for communicating with remote server. - * @param s The serializer for converting POJOs to HTTP request message body text. - * @param p The parser for converting HTTP response message body text to POJOs. - * @throws InstantiationException If serializer or parser could not be instantiated. - */ - public RestClient(CloseableHttpClient httpClient, Class<? extends Serializer> s, Class<? extends Parser> p) throws InstantiationException { - this(); - setHttpClient(httpClient); - setSerializer(s); - setParser(p); - } - - /** - * Creates an instance of an {@link HttpClient} to be used to handle all HTTP communications with the target server. - * <p> - * This HTTP client is used when the HTTP client is not specified through one of the constructors or the - * {@link #setHttpClient(CloseableHttpClient)} method. - * <p> - * Subclasses can override this method to provide specially-configured HTTP clients to handle - * stuff such as SSL/TLS certificate handling, authentication, etc. - * <p> - * The default implementation returns an instance of {@link HttpClient} using the client builder - * returned by {@link #createHttpClientBuilder()}. - * - * @return The HTTP client to use. - * @throws Exception - */ - protected CloseableHttpClient createHttpClient() throws Exception { - // Don't call createConnectionManager() if RestClient.setConnectionManager() was called. - if (httpClientConnectionManager == null) - httpClientBuilder.setConnectionManager(createConnectionManager()); - return httpClientBuilder.build(); - } - - /** - * Creates an instance of an {@link HttpClientBuilder} to be used to create - * the {@link HttpClient}. - * <p> - * Subclasses can override this method to provide their own client builder. - * <p> - * The predefined method returns an {@link HttpClientBuilder} with the following settings: - * <ul> - * <li>Lax redirect strategy. - * <li>The connection manager returned by {@link #createConnectionManager()}. - * </ul> - * - * @return The HTTP client builder to use to create the HTTP client. - */ - protected HttpClientBuilder createHttpClientBuilder() { - HttpClientBuilder b = HttpClientBuilder.create(); - b.setRedirectStrategy(new AllowAllRedirects()); - return b; - } - - /** - * Creates the {@link HttpClientConnectionManager} returned by {@link #createConnectionManager()}. - * <p> - * Subclasses can override this method to provide their own connection manager. - * <p> - * The default implementation returns an instance of a {@link PoolingHttpClientConnectionManager}. - * - * @return The HTTP client builder to use to create the HTTP client. - */ - protected HttpClientConnectionManager createConnectionManager() { - if (sslOpts != null) { - HostnameVerifier hv = null; - switch (sslOpts.getHostVerify()) { - case LAX: hv = new NoopHostnameVerifier(); break; - case DEFAULT: hv = new DefaultHostnameVerifier(); break; - } - - for (String p : StringUtils.split(sslOpts.getProtocols(), ',')) { - try { - TrustManager tm = new SimpleX509TrustManager(sslOpts.getCertValidate() == SSLOpts.CertValidate.LAX); - - SSLContext ctx = SSLContext.getInstance(p); - ctx.init(null, new TrustManager[] { tm }, null); - - // Create a socket to ensure this algorithm is acceptable. - // This will correctly disallow certain configurations (such as SSL_TLS under FIPS) - ctx.getSocketFactory().createSocket().close(); - SSLConnectionSocketFactory sf = new SSLConnectionSocketFactory(ctx, hv); - setSSLSocketFactory(sf); - - Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory> create().register("https", sf).build(); - - return (pooled ? new PoolingHttpClientConnectionManager(r) : new BasicHttpClientConnectionManager(r)); - } catch (Throwable t) {} - } - } + private final StackTraceElement[] creationStack; + private StackTraceElement[] closedStack; + final RetryOn retryOn; + final int retries; + final long retryInterval; + + /** + * Create a new REST client. + * @param propertyStore + * @param httpClient + * @param keepHttpClientOpen + * @param serializer + * @param parser + * @param urlEncodingSerializer + * @param headers + * @param interceptors + * @param remoteableServletUri + * @param remoteableServiceUriMap + * @param rootUri + * @param retryOn + * @param retries + * @param retryInterval + */ + public RestClient( + PropertyStore propertyStore, + CloseableHttpClient httpClient, + boolean keepHttpClientOpen, + Serializer serializer, + Parser parser, + UrlEncodingSerializer urlEncodingSerializer, + Map<String,String> headers, + List<RestCallInterceptor> interceptors, + String remoteableServletUri, + Map<Method,String> remoteableServiceUriMap, + String rootUri, + RetryOn retryOn, + int retries, + long retryInterval) { + super(propertyStore); + this.httpClient = httpClient; + this.keepHttpClientOpen = keepHttpClientOpen; + this.serializer = serializer; + this.parser = parser; + this.urlEncodingSerializer = urlEncodingSerializer; - // Using pooling connection so that this client is threadsafe. - return (pooled ? new PoolingHttpClientConnectionManager() : new BasicHttpClientConnectionManager()); - } + Map<String,String> h2 = new ConcurrentHashMap<String,String>(headers); - /** - * Set up this client to use BASIC auth. - * - * @param host The auth scope hostname. - * @param port The auth scope port. - * @param user The username. - * @param pw The password. - * @return This object (for method chaining). - */ - public RestClient setBasicAuth(String host, int port, String user, String pw) { - AuthScope scope = new AuthScope(host, port); - Credentials up = new UsernamePasswordCredentials(user, pw); - CredentialsProvider p = new BasicCredentialsProvider(); - p.setCredentials(scope, up); - setDefaultCredentialsProvider(p); - return this; - } + this.headers = Collections.unmodifiableMap(h2); + this.interceptors = interceptors.toArray(new RestCallInterceptor[interceptors.size()]); + this.remoteableServletUri = remoteableServletUri; + this.remoteableServiceUriMap = new ConcurrentHashMap<Method,String>(remoteableServiceUriMap); + this.rootUrl = rootUri; + this.retryOn = retryOn; + this.retries = retries; + this.retryInterval = retryInterval; - /** - * When called, the {@link #createConnectionManager()} method will return a {@link PoolingHttpClientConnectionManager} - * instead of a {@link BasicHttpClientConnectionManager}. - * - * @return This object (for method chaining). - */ - public RestClient setPooled() { - this.pooled = true; - return this; + if (Boolean.getBoolean("org.apache.juneau.rest.client.RestClient.trackLifecycle")) + creationStack = Thread.currentThread().getStackTrace(); + else + creationStack = null; } /** @@ -318,8 +133,10 @@ public class RestClient extends CoreApi { */ public void close() throws IOException { isClosed = true; - if (httpClient != null) + if (httpClient != null && ! keepHttpClientOpen) httpClient.close(); + if (Boolean.getBoolean("org.apache.juneau.rest.client.RestClient.trackLifecycle")) + closedStack = Thread.currentThread().getStackTrace(); } /** @@ -328,120 +145,11 @@ public class RestClient extends CoreApi { public void closeQuietly() { isClosed = true; try { - if (httpClient != null) + if (httpClient != null && ! keepHttpClientOpen) httpClient.close(); } catch (Throwable t) {} - } - - /** - * Specifies a request header property to add to all requests created by this client. - * - * @param name The HTTP header name. - * @param value The HTTP header value. - * @return This object (for method chaining). - */ - public RestClient setHeader(String name, Object value) { - this.headers.put(name, value); - return this; - } - - /** - * Sets the serializer used for serializing POJOs to the HTTP request message body. - * - * @param serializer The serializer. - * @return This object (for method chaining). - */ - public RestClient setSerializer(Serializer serializer) { - this.serializer = serializer; - return this; - } - - /** - * Same as {@link #setSerializer(Serializer)}, except takes in a serializer class that - * will be instantiated through a no-arg constructor. - * - * @param c The serializer class. - * @return This object (for method chaining). - * @throws InstantiationException If serializer could not be instantiated. - */ - public RestClient setSerializer(Class<? extends Serializer> c) throws InstantiationException { - try { - return setSerializer(c.newInstance()); - } catch (IllegalAccessException e) { - throw new InstantiationException(e.getLocalizedMessage()); - } - } - - /** - * Sets the parser used for parsing POJOs from the HTTP response message body. - * - * @param parser The parser. - * @return This object (for method chaining). - */ - public RestClient setParser(Parser parser) { - this.parser = parser; - this.accept = StringUtils.toString(parser.getPrimaryMediaType()); - return this; - } - - /** - * Same as {@link #setParser(Parser)}, except takes in a parser class that - * will be instantiated through a no-arg constructor. - * - * @param c The parser class. - * @return This object (for method chaining). - * @throws InstantiationException If parser could not be instantiated. - */ - public RestClient setParser(Class<? extends Parser> c) throws InstantiationException { - try { - return setParser(c.newInstance()); - } catch (IllegalAccessException e) { - throw new InstantiationException(e.getLocalizedMessage()); - } - } - - /** - * Sets the internal {@link HttpClient} to use for handling HTTP communications. - * - * @param httpClient The HTTP client. - * @return This object (for method chaining). - */ - public RestClient setHttpClient(CloseableHttpClient httpClient) { - this.httpClient = httpClient; - return this; - } - - /** - * Sets the client version by setting the value for the <js>"X-Client-Version"</js> header. - * - * @param version The version string (e.g. <js>"1.2.3"</js>) - * @return This object (for method chaining). - */ - public RestClient setClientVersion(String version) { - return setHeader("X-Client-Version", version); - } - - /** - * Adds an interceptor that gets called immediately after a connection is made. - * - * @param interceptor The interceptor. - * @return This object (for method chaining). - */ - public RestClient addInterceptor(RestCallInterceptor interceptor) { - interceptors.add(interceptor); - return this; - } - - /** - * Adds a {@link RestCallLogger} to the list of interceptors on this class. - * - * @param level The log level to log messsages at. - * @param log The logger to log messages to. - * @return This object (for method chaining). - */ - public RestClient logTo(Level level, Logger log) { - addInterceptor(new RestCallLogger(level, log)); - return this; + if (Boolean.getBoolean("org.apache.juneau.rest.client.RestClient.trackLifecycle")) + closedStack = Thread.currentThread().getStackTrace(); } /** @@ -463,15 +171,12 @@ public class RestClient extends CoreApi { } /** - * Returns the {@link HttpClient} currently associated with this client. + * Returns the list of interceptors on this client. * - * @return The HTTP client currently associated with this client. - * @throws Exception + * @return The list of interceptors on this client. */ - public HttpClient getHttpClient() throws Exception { - if (httpClient == null) - httpClient = createHttpClient(); - return httpClient; + public RestCallInterceptor[] getInterceptors() { + return interceptors; } /** @@ -483,91 +188,7 @@ public class RestClient extends CoreApi { * @throws Exception */ protected HttpResponse execute(HttpUriRequest req) throws Exception { - return getHttpClient().execute(req); - } - - /** - * Sets the value for the <code>Accept</code> request header. - * <p> - * This overrides the media type specified on the parser, but is overridden by calling <code>setHeader(<js>"Accept"</js>, newvalue);</code> - * - * @param accept The new header value. - * @return This object (for method chaining). - */ - public RestClient setAccept(String accept) { - this.accept = accept; - return this; - } - - /** - * Sets the value for the <code>Content-Type</code> request header. - * <p> - * This overrides the media type specified on the serializer, but is overridden by calling <code>setHeader(<js>"Content-Type"</js>, newvalue);</code> - * - * @param contentType The new header value. - * @return This object (for method chaining). - */ - public RestClient setContentType(String contentType) { - this.contentType = contentType; - return this; - } - - /** - * Sets the URI of the remoteable services REST servlet for invoking remoteable services. - * - * @param remoteableServletUri The URI of the REST resource implementing a remoteable services servlet. - * (typically an instance of <code>RemoteableServlet</code>). - * @return This object (for method chaining). - */ - public RestClient setRemoteableServletUri(String remoteableServletUri) { - this.remoteableServletUri = remoteableServletUri; - return this; - } - - /** - * Set a root URL for this client. - * <p> - * When set, URL strings passed in through the various rest call methods (e.g. {@link #doGet(Object)} - * will be prefixed with the specified root. - * This root URL is ignored on those methods if you pass in a {@link URL}, {@link URI}, or an absolute URL string. - * - * @param rootUrl The root URL to prefix to relative URL strings. Trailing slashes are trimmed. - * Usually a <code>String<code> but you can also pass in <code>URI</code> and <code>URL</code> objects as well. - * @return This object (for method chaining). - */ - public RestClient setRootUrl(Object rootUrl) { - String s = rootUrl.toString(); - if (s.endsWith("/")) - s = s.replaceAll("\\/$", ""); - this.rootUrl = s; - return this; - } - - /** - * Enable SSL support on this client. - * - * @param opts The SSL configuration options. See {@link SSLOpts} for details. - * This method is a no-op if <code>sslConfig</code> is <jk>null</jk>. - * @return This object (for method chaining). - * @throws KeyStoreException - * @throws NoSuchAlgorithmException - */ - public RestClient enableSSL(SSLOpts opts) throws KeyStoreException, NoSuchAlgorithmException { - this.sslOpts = opts; - return this; - } - - /** - * Enable LAX SSL support. - * <p> - * Certificate chain validation and hostname verification is disabled. - * - * @return This object (for method chaining). - * @throws KeyStoreException - * @throws NoSuchAlgorithmException - */ - public RestClient enableLaxSSL() throws KeyStoreException, NoSuchAlgorithmException { - return enableSSL(SSLOpts.LAX); + return httpClient.execute(req); } /** @@ -599,7 +220,7 @@ public class RestClient extends CoreApi { * @throws RestCallException If any authentication errors occurred. */ public RestCall doPut(Object url, Object o) throws RestCallException { - return doCall("PUT", url, true).setInput(o); + return doCall("PUT", url, true).input(o); } /** @@ -619,7 +240,7 @@ public class RestClient extends CoreApi { * @throws RestCallException If any authentication errors occurred. */ public RestCall doPost(Object url, Object o) throws RestCallException { - return doCall("POST", url, true).setInput(o); + return doCall("POST", url, true).input(o); } /** @@ -658,7 +279,7 @@ public class RestClient extends CoreApi { */ public RestCall doFormPost(Object url, Object o) throws RestCallException { return doCall("POST", url, true) - .setInput(o instanceof HttpEntity ? o : new RestRequestEntity(o, urlEncodingSerializer)); + .input(o instanceof HttpEntity ? o : new RestRequestEntity(o, urlEncodingSerializer)); } /** @@ -716,10 +337,10 @@ public class RestClient extends CoreApi { if (method != null && uri != null) { rc = doCall(method, uri, content != null); if (content != null) - rc.setInput(new StringEntity(content)); + rc.input(new StringEntity(content)); if (h != null) for (Map.Entry<String,Object> e : h.entrySet()) - rc.setHeader(e.getKey(), e.getValue()); + rc.header(e.getKey(), e.getValue()); return rc; } } catch (Exception e) { @@ -749,7 +370,7 @@ public class RestClient extends CoreApi { public RestCall doCall(HttpMethod method, Object url, Object content) throws RestCallException { RestCall rc = doCall(method.name(), url, method.hasContent()); if (method.hasContent()) - rc.setInput(content); + rc.input(content); return rc; } @@ -764,6 +385,16 @@ public class RestClient extends CoreApi { * @throws RestCallException If any authentication errors occurred. */ public RestCall doCall(String method, Object url, boolean hasContent) throws RestCallException { + if (isClosed) { + Exception e2 = null; + if (closedStack != null) { + e2 = new Exception("Creation stack:"); + e2.setStackTrace(closedStack); + throw new RestCallException("RestClient.close() has already been called. This client cannot be reused.").initCause(e2); + } + throw new RestCallException("RestClient.close() has already been called. This client cannot be reused. Closed location stack trace can be displayed by setting the system property 'org.apache.juneau.rest.client.RestClient.trackCreation' to true."); + } + HttpRequestBase req = null; RestCall restCall = null; final String methodUC = method.toUpperCase(Locale.ENGLISH); @@ -775,8 +406,6 @@ public class RestClient extends CoreApi { } }; restCall = new RestCall(this, req); - if (contentType != null) - restCall.setHeader("Content-Type", contentType); } else { req = new HttpRequestBase() { @Override /* HttpRequest */ @@ -791,10 +420,12 @@ public class RestClient extends CoreApi { } catch (URISyntaxException e) { throw new RestCallException(e); } - if (accept != null) - restCall.setHeader("Accept", accept); for (Map.Entry<String,? extends Object> e : headers.entrySet()) - restCall.setHeader(e.getKey(), e.getValue()); + restCall.header(e.getKey(), e.getValue()); + + if (parser != null && ! req.containsHeader("Accept")) + req.setHeader("Accept", parser.getPrimaryMediaType().toString()); + return restCall; } @@ -804,7 +435,7 @@ public class RestClient extends CoreApi { * @param interfaceClass The interface to create a proxy for. * @return The new proxy interface. * @throws RuntimeException If the Remotable service URI has not been specified on this - * client by calling {@link #setRemoteableServletUri(String)}. + * client by calling {@link RestClientBuilder#remoteableServletUri(String)}. */ @SuppressWarnings("unchecked") public <T> T getRemoteableProxy(final Class<T> interfaceClass) { @@ -854,587 +485,16 @@ public class RestClient extends CoreApi { return new URI(s); } - - //-------------------------------------------------------------------------------- - // Overridden methods - //-------------------------------------------------------------------------------- - - @Override /* CoreAPI */ - public RestClient setProperty(String property, Object value) throws LockedException { - super.setProperty(property, value); - if (serializer != null) - serializer.setProperty(property, value); - if (parser != null) - parser.setProperty(property, value); - if (urlEncodingSerializer != null) - urlEncodingSerializer.setProperty(property, value); - return this; - } - - @Override /* CoreAPI */ - public RestClient setProperties(ObjectMap properties) throws LockedException { - super.setProperties(properties); - if (serializer != null) - serializer.setProperties(properties); - if (parser != null) - parser.setProperties(properties); - if (urlEncodingSerializer != null) - urlEncodingSerializer.setProperties(properties); - return this; - } - - @Override /* CoreAPI */ - public RestClient addNotBeanClasses(Class<?>...classes) throws LockedException { - super.addNotBeanClasses(classes); - if (serializer != null) - serializer.addNotBeanClasses(classes); - if (parser != null) - parser.addNotBeanClasses(classes); - if (urlEncodingSerializer != null) - urlEncodingSerializer.addNotBeanClasses(classes); - return this; - } - - @Override /* CoreAPI */ - public RestClient addBeanFilters(Class<?>...classes) throws LockedException { - super.addBeanFilters(classes); - if (serializer != null) - serializer.addBeanFilters(classes); - if (parser != null) - parser.addBeanFilters(classes); - if (urlEncodingSerializer != null) - urlEncodingSerializer.addBeanFilters(classes); - return this; - } - - @Override /* CoreAPI */ - public RestClient addPojoSwaps(Class<?>...classes) throws LockedException { - super.addPojoSwaps(classes); - if (serializer != null) - serializer.addPojoSwaps(classes); - if (parser != null) - parser.addPojoSwaps(classes); - if (urlEncodingSerializer != null) - urlEncodingSerializer.addPojoSwaps(classes); - return this; - } - - @Override /* CoreAPI */ - public RestClient addToBeanDictionary(Class<?>...classes) throws LockedException { - super.addToBeanDictionary(classes); - if (serializer != null) - serializer.addToBeanDictionary(classes); - if (parser != null) - parser.addToBeanDictionary(classes); - if (urlEncodingSerializer != null) - urlEncodingSerializer.addToBeanDictionary(classes); - return this; - } - - @Override /* CoreAPI */ - public <T> RestClient addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException { - super.addImplClass(interfaceClass, implClass); - if (serializer != null) - serializer.addImplClass(interfaceClass, implClass); - if (parser != null) - parser.addImplClass(interfaceClass, implClass); - if (urlEncodingSerializer != null) - urlEncodingSerializer.addImplClass(interfaceClass, implClass); - return this; - } - - @Override /* CoreAPI */ - public RestClient setClassLoader(ClassLoader classLoader) throws LockedException { - super.setClassLoader(classLoader); - if (serializer != null) - serializer.setClassLoader(classLoader); - if (parser != null) - parser.setClassLoader(classLoader); - if (urlEncodingSerializer != null) - urlEncodingSerializer.setClassLoader(classLoader); - return this; - } - - - //------------------------------------------------------------------------------------------------ - // Passthrough methods for HttpClientBuilder. - //------------------------------------------------------------------------------------------------ - - /** - * @param redirectStrategy - * @return This object (for method chaining). - * @see HttpClientBuilder#setRedirectStrategy(RedirectStrategy) - */ - public RestClient setRedirectStrategy(RedirectStrategy redirectStrategy) { - httpClientBuilder.setRedirectStrategy(redirectStrategy); - return this; - } - - /** - * @param cookieSpecRegistry - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultCookieSpecRegistry(Lookup) - */ - public RestClient setDefaultCookieSpecRegistry(Lookup<CookieSpecProvider> cookieSpecRegistry) { - httpClientBuilder.setDefaultCookieSpecRegistry(cookieSpecRegistry); - return this; - } - - /** - * @param requestExec - * @return This object (for method chaining). - * @see HttpClientBuilder#setRequestExecutor(HttpRequestExecutor) - */ - public RestClient setRequestExecutor(HttpRequestExecutor requestExec) { - httpClientBuilder.setRequestExecutor(requestExec); - return this; - } - - /** - * @param hostnameVerifier - * @return This object (for method chaining). - * @see HttpClientBuilder#setSSLHostnameVerifier(HostnameVerifier) - */ - public RestClient setSSLHostnameVerifier(HostnameVerifier hostnameVerifier) { - httpClientBuilder.setSSLHostnameVerifier(hostnameVerifier); - return this; - } - - /** - * @param publicSuffixMatcher - * @return This object (for method chaining). - * @see HttpClientBuilder#setPublicSuffixMatcher(PublicSuffixMatcher) - */ - public RestClient setPublicSuffixMatcher(PublicSuffixMatcher publicSuffixMatcher) { - httpClientBuilder.setPublicSuffixMatcher(publicSuffixMatcher); - return this; - } - - /** - * @param sslContext - * @return This object (for method chaining). - * @see HttpClientBuilder#setSSLContext(SSLContext) - */ - public RestClient setSSLContext(SSLContext sslContext) { - httpClientBuilder.setSSLContext(sslContext); - return this; - } - - /** - * @param sslSocketFactory - * @return This object (for method chaining). - * @see HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory) - */ - public RestClient setSSLSocketFactory(LayeredConnectionSocketFactory sslSocketFactory) { - httpClientBuilder.setSSLSocketFactory(sslSocketFactory); - return this; - } - - /** - * @param maxConnTotal - * @return This object (for method chaining). - * @see HttpClientBuilder#setMaxConnTotal(int) - */ - public RestClient setMaxConnTotal(int maxConnTotal) { - httpClientBuilder.setMaxConnTotal(maxConnTotal); - return this; - } - - /** - * @param maxConnPerRoute - * @return This object (for method chaining). - * @see HttpClientBuilder#setMaxConnPerRoute(int) - */ - public RestClient setMaxConnPerRoute(int maxConnPerRoute) { - httpClientBuilder.setMaxConnPerRoute(maxConnPerRoute); - return this; - } - - /** - * @param config - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultSocketConfig(SocketConfig) - */ - public RestClient setDefaultSocketConfig(SocketConfig config) { - httpClientBuilder.setDefaultSocketConfig(config); - return this; - } - - /** - * @param config - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultConnectionConfig(ConnectionConfig) - */ - public RestClient setDefaultConnectionConfig(ConnectionConfig config) { - httpClientBuilder.setDefaultConnectionConfig(config); - return this; - } - - /** - * @param connTimeToLive - * @param connTimeToLiveTimeUnit - * @return This object (for method chaining). - * @see HttpClientBuilder#setConnectionTimeToLive(long,TimeUnit) - */ - public RestClient setConnectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) { - httpClientBuilder.setConnectionTimeToLive(connTimeToLive, connTimeToLiveTimeUnit); - return this; - } - - /** - * @param connManager - * @return This object (for method chaining). - * @see HttpClientBuilder#setConnectionManager(HttpClientConnectionManager) - */ - public RestClient setConnectionManager(HttpClientConnectionManager connManager) { - this.httpClientConnectionManager = connManager; - httpClientBuilder.setConnectionManager(connManager); - return this; - } - - /** - * @param shared - * @return This object (for method chaining). - * @see HttpClientBuilder#setConnectionManagerShared(boolean) - */ - public RestClient setConnectionManagerShared(boolean shared) { - httpClientBuilder.setConnectionManagerShared(shared); - return this; - } - - /** - * @param reuseStrategy - * @return This object (for method chaining). - * @see HttpClientBuilder#setConnectionReuseStrategy(ConnectionReuseStrategy) - */ - public RestClient setConnectionReuseStrategy(ConnectionReuseStrategy reuseStrategy) { - httpClientBuilder.setConnectionReuseStrategy(reuseStrategy); - return this; - } - - /** - * @param keepAliveStrategy - * @return This object (for method chaining). - * @see HttpClientBuilder#setKeepAliveStrategy(ConnectionKeepAliveStrategy) - */ - public RestClient setKeepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) { - httpClientBuilder.setKeepAliveStrategy(keepAliveStrategy); - return this; - } - - /** - * @param targetAuthStrategy - * @return This object (for method chaining). - * @see HttpClientBuilder#setTargetAuthenticationStrategy(AuthenticationStrategy) - */ - public RestClient setTargetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy) { - httpClientBuilder.setTargetAuthenticationStrategy(targetAuthStrategy); - return this; - } - - /** - * @param proxyAuthStrategy - * @return This object (for method chaining). - * @see HttpClientBuilder#setProxyAuthenticationStrategy(AuthenticationStrategy) - */ - public RestClient setProxyAuthenticationStrategy(AuthenticationStrategy proxyAuthStrategy) { - httpClientBuilder.setProxyAuthenticationStrategy(proxyAuthStrategy); - return this; - } - - /** - * @param userTokenHandler - * @return This object (for method chaining). - * @see HttpClientBuilder#setUserTokenHandler(UserTokenHandler) - */ - public RestClient setUserTokenHandler(UserTokenHandler userTokenHandler) { - httpClientBuilder.setUserTokenHandler(userTokenHandler); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#disableConnectionState() - */ - public RestClient disableConnectionState() { - httpClientBuilder.disableConnectionState(); - return this; - } - - /** - * @param schemePortResolver - * @return This object (for method chaining). - * @see HttpClientBuilder#setSchemePortResolver(SchemePortResolver) - */ - public RestClient setSchemePortResolver(SchemePortResolver schemePortResolver) { - httpClientBuilder.setSchemePortResolver(schemePortResolver); - return this; - } - - /** - * @param userAgent - * @return This object (for method chaining). - * @see HttpClientBuilder#setUserAgent(String) - */ - public RestClient setUserAgent(String userAgent) { - httpClientBuilder.setUserAgent(userAgent); - return this; - } - - /** - * @param defaultHeaders - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultHeaders(Collection) - */ - public RestClient setDefaultHeaders(Collection<? extends Header> defaultHeaders) { - httpClientBuilder.setDefaultHeaders(defaultHeaders); - return this; - } - - /** - * @param itcp - * @return This object (for method chaining). - * @see HttpClientBuilder#addInterceptorFirst(HttpResponseInterceptor) - */ - public RestClient addInterceptorFirst(HttpResponseInterceptor itcp) { - httpClientBuilder.addInterceptorFirst(itcp); - return this; - } - - /** - * @param itcp - * @return This object (for method chaining). - * @see HttpClientBuilder#addInterceptorLast(HttpResponseInterceptor) - */ - public RestClient addInterceptorLast(HttpResponseInterceptor itcp) { - httpClientBuilder.addInterceptorLast(itcp); - return this; - } - - /** - * @param itcp - * @return This object (for method chaining). - * @see HttpClientBuilder#addInterceptorFirst(HttpRequestInterceptor) - */ - public RestClient addInterceptorFirst(HttpRequestInterceptor itcp) { - httpClientBuilder.addInterceptorFirst(itcp); - return this; - } - - /** - * @param itcp - * @return This object (for method chaining). - * @see HttpClientBuilder#addInterceptorLast(HttpRequestInterceptor) - */ - public RestClient addInterceptorLast(HttpRequestInterceptor itcp) { - httpClientBuilder.addInterceptorLast(itcp); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#disableCookieManagement() - */ - public RestClient disableCookieManagement() { - httpClientBuilder.disableCookieManagement(); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#disableContentCompression() - */ - public RestClient disableContentCompression() { - httpClientBuilder.disableContentCompression(); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#disableAuthCaching() - */ - public RestClient disableAuthCaching() { - httpClientBuilder.disableAuthCaching(); - return this; - } - - /** - * @param httpprocessor - * @return This object (for method chaining). - * @see HttpClientBuilder#setHttpProcessor(HttpProcessor) - */ - public RestClient setHttpProcessor(HttpProcessor httpprocessor) { - httpClientBuilder.setHttpProcessor(httpprocessor); - return this; - } - - /** - * @param retryHandler - * @return This object (for method chaining). - * @see HttpClientBuilder#setRetryHandler(HttpRequestRetryHandler) - */ - public RestClient setRetryHandler(HttpRequestRetryHandler retryHandler) { - httpClientBuilder.setRetryHandler(retryHandler); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#disableAutomaticRetries() - */ - public RestClient disableAutomaticRetries() { - httpClientBuilder.disableAutomaticRetries(); - return this; - } - - /** - * @param proxy - * @return This object (for method chaining). - * @see HttpClientBuilder#setProxy(HttpHost) - */ - public RestClient setProxy(HttpHost proxy) { - httpClientBuilder.setProxy(proxy); - return this; - } - - /** - * @param routePlanner - * @return This object (for method chaining). - * @see HttpClientBuilder#setRoutePlanner(HttpRoutePlanner) - */ - public RestClient setRoutePlanner(HttpRoutePlanner routePlanner) { - httpClientBuilder.setRoutePlanner(routePlanner); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#disableRedirectHandling() - */ - public RestClient disableRedirectHandling() { - httpClientBuilder.disableRedirectHandling(); - return this; - } - - /** - * @param connectionBackoffStrategy - * @return This object (for method chaining). - * @see HttpClientBuilder#setConnectionBackoffStrategy(ConnectionBackoffStrategy) - */ - public RestClient setConnectionBackoffStrategy(ConnectionBackoffStrategy connectionBackoffStrategy) { - httpClientBuilder.setConnectionBackoffStrategy(connectionBackoffStrategy); - return this; - } - - /** - * @param backoffManager - * @return This object (for method chaining). - * @see HttpClientBuilder#setBackoffManager(BackoffManager) - */ - public RestClient setBackoffManager(BackoffManager backoffManager) { - httpClientBuilder.setBackoffManager(backoffManager); - return this; - } - - /** - * @param serviceUnavailStrategy - * @return This object (for method chaining). - * @see HttpClientBuilder#setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy) - */ - public RestClient setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy serviceUnavailStrategy) { - httpClientBuilder.setServiceUnavailableRetryStrategy(serviceUnavailStrategy); - return this; - } - - /** - * @param cookieStore - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultCookieStore(CookieStore) - */ - public RestClient setDefaultCookieStore(CookieStore cookieStore) { - httpClientBuilder.setDefaultCookieStore(cookieStore); - return this; - } - - /** - * @param credentialsProvider - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultCredentialsProvider(CredentialsProvider) - */ - public RestClient setDefaultCredentialsProvider(CredentialsProvider credentialsProvider) { - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - return this; - } - - /** - * @param authSchemeRegistry - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultAuthSchemeRegistry(Lookup) - */ - public RestClient setDefaultAuthSchemeRegistry(Lookup<AuthSchemeProvider> authSchemeRegistry) { - httpClientBuilder.setDefaultAuthSchemeRegistry(authSchemeRegistry); - return this; - } - - /** - * @param contentDecoderMap - * @return This object (for method chaining). - * @see HttpClientBuilder#setContentDecoderRegistry(Map) - */ - public RestClient setContentDecoderRegistry(Map<String,InputStreamFactory> contentDecoderMap) { - httpClientBuilder.setContentDecoderRegistry(contentDecoderMap); - return this; - } - - /** - * @param config - * @return This object (for method chaining). - * @see HttpClientBuilder#setDefaultRequestConfig(RequestConfig) - */ - public RestClient setDefaultRequestConfig(RequestConfig config) { - httpClientBuilder.setDefaultRequestConfig(config); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#useSystemProperties() - */ - public RestClient useSystemProperties() { - httpClientBuilder.useSystemProperties(); - return this; - } - - /** - * @return This object (for method chaining). - * @see HttpClientBuilder#evictExpiredConnections() - */ - public RestClient evictExpiredConnections() { - httpClientBuilder.evictExpiredConnections(); - return this; - } - - /** - * @param maxIdleTime - * @param maxIdleTimeUnit - * @return This object (for method chaining). - * @see HttpClientBuilder#evictIdleConnections(long,TimeUnit) - */ - public RestClient evictIdleConnections(long maxIdleTime, TimeUnit maxIdleTimeUnit) { - httpClientBuilder.evictIdleConnections(maxIdleTime, maxIdleTimeUnit); - return this; - } - @Override protected void finalize() throws Throwable { - if (! isClosed) { + if (! isClosed && ! keepHttpClientOpen) { System.err.println("WARNING: RestClient garbage collected before it was finalized."); if (creationStack != null) { System.err.println("Creation Stack:"); for (StackTraceElement e : creationStack) System.err.println(e); } else { - System.err.println("Creation stack traces can be displayed by setting the system property 'org.apache.juneau.rest.client.RestClient.trackCreation' to true."); + System.err.println("Creation stack traces can be displayed by setting the system property 'org.apache.juneau.rest.client.RestClient.trackLifecycle' to true."); } } }
