http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallException.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallException.java
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallException.java
new file mode 100755
index 0000000..b0129f4
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallException.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import static java.lang.String.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.regex.*;
+
+import org.apache.http.*;
+import org.apache.http.client.*;
+import org.apache.http.util.*;
+
+import com.ibm.juno.core.utils.*;
+
+/**
+ * Exception representing a <code>400+</code> HTTP response code against a 
remote resource.
+ *
+ * @author James Bognar ([email protected])
+ */
+public final class RestCallException extends IOException {
+
+       private static final long serialVersionUID = 1L;
+
+       private int responseCode;
+       private String response, responseStatusMessage;
+       HttpResponseException e;
+       private HttpResponse httpResponse;
+
+
+       /**
+        * Constructor.
+        *
+        * @param msg The exception message.
+        */
+       public RestCallException(String msg) {
+               super(msg);
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param e The inner cause of the exception.
+        */
+       public RestCallException(Exception e) {
+               super(e.getLocalizedMessage(), e);
+               if (e instanceof FileNotFoundException) {
+                       responseCode = 404;
+               } else if (e.getMessage() != null) {
+                       Pattern p = Pattern.compile("[^\\d](\\d{3})[^\\d]");
+                       Matcher m = p.matcher(e.getMessage());
+                       if (m.find())
+                               responseCode = Integer.parseInt(m.group(1));
+               }
+               setStackTrace(e.getStackTrace());
+       }
+
+       /**
+        * Create an exception with a simple message and the status code and 
body of the specified response.
+        *
+        * @param msg The exception message.
+        * @param response The HTTP response object.
+        * @throws ParseException
+        * @throws IOException
+        */
+       public RestCallException(String msg, HttpResponse response) throws 
ParseException, IOException {
+               super(format("%s%nstatus='%s'%nResponse: %n%s%n", msg, 
response.getStatusLine().getStatusCode(), 
EntityUtils.toString(response.getEntity(), IOUtils.UTF8)));
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param responseCode The response code.
+        * @param responseMsg The response message.
+        * @param method The HTTP method (for message purposes).
+        * @param url The HTTP URL (for message purposes).
+        * @param response The reponse from the server.
+        */
+       public RestCallException(int responseCode, String responseMsg, String 
method, URI url, String response) {
+               super(format("HTTP method '%s' call to '%s' caused response 
code '%s,%s'.%nResponse: %n%s%n", method, url, responseCode, responseMsg, 
response));
+               this.responseCode = responseCode;
+               this.responseStatusMessage = responseMsg;
+               this.response = response;
+       }
+
+       /**
+        * Sets the HTTP response object that caused this exception.
+        *
+        * @param httpResponse The HTTP respose object.
+        * @return This object (for method chaining).
+        */
+       protected RestCallException setHttpResponse(HttpResponse httpResponse) {
+               this.httpResponse = httpResponse;
+               return this;
+       }
+
+       /**
+        * Returns the HTTP response object that caused this exception.
+        *
+        * @return The HTTP response object that caused this exception, or 
<jk>null</jk> if no response was created yet when the exception was thrown.
+        */
+       public HttpResponse getHttpResponse() {
+               return this.httpResponse;
+       }
+
+       /**
+        * Returns the HTTP response status code.
+        *
+        * @return The response status code.  If a connection could not be made 
at all, returns <code>0<code>.
+        */
+       public int getResponseCode() {
+               return responseCode;
+       }
+
+       /**
+        * Returns the HTTP response message body text.
+        *
+        * @return The response message body text.
+        */
+       public String getResponseMessage() {
+               return response;
+       }
+
+       /**
+        * Returns the response status message as a plain string.
+        *
+        * @return The response status message.
+        */
+       public String getResponseStatusMessage() {
+               return responseStatusMessage;
+       }
+
+       /**
+        * Sets the inner cause for this exception.
+        * @param cause The inner cause.
+        * @return This object (for method chaining).
+        */
+       @Override /* Throwable */
+       public synchronized RestCallException initCause(Throwable cause) {
+               super.initCause(cause);
+               return this;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.class
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.class
new file mode 100755
index 0000000..e4e4096
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.class
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.java
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.java
new file mode 100755
index 0000000..52c278b
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallInterceptor.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import org.apache.http.*;
+
+/**
+ * Used to intercept http connection responses to allow modification of that 
response before processing
+ * and for listening for call lifecycle events.
+ * <p>
+ * Useful if you want to prevent {@link RestCallException RestCallExceptions} 
from being thrown on error conditions.
+ */
+public abstract class RestCallInterceptor {
+
+       /**
+        * Called when {@link RestCall} object is created.
+        *
+        * @param restCall The restCall object invoking this method.
+        */
+       public void onInit(RestCall restCall) {}
+
+       /**
+        * Called immediately after an HTTP response has been received.
+        *
+        * @param statusCode The HTTP status code received.
+        * @param restCall The restCall object invoking this method.
+        * @param req The HTTP request object.
+        * @param res The HTTP response object.
+        */
+       public void onConnect(RestCall restCall, int statusCode, HttpRequest 
req, HttpResponse res) {}
+
+       /**
+        * Called if retry is going to be attempted.
+        *
+        * @param statusCode The HTTP status code received.
+        * @param restCall The restCall object invoking this method.
+        * @param req The HTTP request object.
+        * @param res The HTTP response object.
+        * @param ex The exception thrown from the client.
+        */
+       public void onRetry(RestCall restCall, int statusCode, HttpRequest req, 
HttpResponse res, Exception ex) {}
+
+       /**
+        * Called when {@link RestCall#close()} is called.
+        *
+        * @param restCall The restCall object invoking this method.
+        * @throws RestCallException
+        */
+       public void onClose(RestCall restCall) throws RestCallException {}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.class
new file mode 100755
index 0000000..27cbe0c
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.class 
differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.java 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.java
new file mode 100755
index 0000000..a0dc722
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestCallLogger.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import java.io.*;
+import java.text.*;
+import java.util.logging.*;
+
+import org.apache.http.*;
+import org.apache.http.client.methods.*;
+import org.apache.http.util.*;
+
+/**
+ * Specialized interceptor for logging calls to a log file.
+ * <p>
+ * 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)}
+ * <p>
+ * methods to create instances of this class.
+ */
+public class RestCallLogger extends RestCallInterceptor {
+
+       private Level level;
+       private Logger log;
+
+       /**
+        * Constructor.
+        *
+        * @param level The log level to log messages at.
+        * @param log The logger to log to.
+        */
+       protected RestCallLogger(Level level, Logger log) {
+               this.level = level;
+               this.log = log;
+       }
+
+       @Override /* RestCallInterceptor */
+       public void onInit(RestCall restCall) {
+               if (log.isLoggable(level))
+                       restCall.captureResponse();
+       }
+
+       @Override /* RestCallInterceptor */
+       public void onConnect(RestCall restCall, int statusCode, HttpRequest 
req, HttpResponse res) {
+               // Do nothing.
+       }
+
+       @Override /* RestCallInterceptor */
+       public void onRetry(RestCall restCall, int statusCode, HttpRequest req, 
HttpResponse res, Exception ex) {
+               if (log.isLoggable(level)) {
+                       if (ex == null)
+                       log.log(level, MessageFormat.format("Call to {0} 
returned {1}.  Will retry.", req.getRequestLine().getUri(), statusCode)); 
//$NON-NLS-1$
+                       else
+                               log.log(level, MessageFormat.format("Call to 
{0} caused exception {1}.  Will retry.", req.getRequestLine().getUri(), 
ex.getLocalizedMessage()), ex); //$NON-NLS-1$
+               }
+       }
+
+       @Override /* RestCallInterceptor */
+       public void onClose(RestCall restCall) throws RestCallException {
+               try {
+                       if (log.isLoggable(level)) {
+                               String output = restCall.getCapturedResponse();
+                               StringBuilder sb = new StringBuilder();
+                               HttpUriRequest req = restCall.getRequest();
+                               HttpResponse res = restCall.getResponse();
+                               if (req != null) {
+                                       sb.append("\n=== HTTP Call 
==================================================================");
+
+                                       sb.append("\n=== REQUEST 
===\n").append(req);
+                                       sb.append("\n---request headers---");
+                                       for (Header h : req.getAllHeaders())
+                                               sb.append("\n").append(h);
+                                       if (req instanceof 
HttpEntityEnclosingRequestBase) {
+                                               sb.append("\n---request 
entity---");
+                                               HttpEntityEnclosingRequestBase 
req2 = (HttpEntityEnclosingRequestBase)req;
+                                               HttpEntity e = req2.getEntity();
+                                               if (e == null)
+                                                       sb.append("\nEntity is 
null");
+                                               else {
+                                                       if (e.getContentType() 
!= null)
+                                                               
sb.append("\n").append(e.getContentType());
+                                                       if 
(e.getContentEncoding() != null)
+                                                               
sb.append("\n").append(e.getContentEncoding());
+                                                       if (e.isRepeatable()) {
+                                                               try {
+                                                                       
sb.append("\n---request content---\n").append(EntityUtils.toString(e));
+                                                               } catch 
(Exception ex) {
+                                                                       throw 
new RuntimeException(ex);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (res != null) {
+                                       sb.append("\n=== RESPONSE 
===\n").append(res.getStatusLine());
+                                       sb.append("\n---response headers---");
+                                       for (Header h : res.getAllHeaders())
+                                               sb.append("\n").append(h);
+                                       sb.append("\n---response 
content---\n").append(output);
+                                       sb.append("\n=== END 
========================================================================");
+                               }
+                               log.log(level, sb.toString());
+                       }
+               } catch (IOException e) {
+                       log.log(Level.SEVERE, e.getLocalizedMessage(), e);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$1.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$1.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$1.class
new file mode 100755
index 0000000..59a5b7c
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$1.class 
differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$2.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$2.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$2.class
new file mode 100755
index 0000000..dbb30de
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$2.class 
differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$3.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$3.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$3.class
new file mode 100755
index 0000000..bf86a9a
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$3.class 
differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$4.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$4.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$4.class
new file mode 100755
index 0000000..0d56649
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient$4.class 
differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.class
new file mode 100755
index 0000000..f169511
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.class 
differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.java 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.java
new file mode 100755
index 0000000..a63018e
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestClient.java
@@ -0,0 +1,1378 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import static com.ibm.juno.core.utils.ThrowableUtils.*;
+
+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 com.ibm.juno.core.*;
+import com.ibm.juno.core.json.*;
+import com.ibm.juno.core.parser.*;
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.urlencoding.*;
+import com.ibm.juno.core.utils.*;
+
+/**
+ * Utility class for interfacing with remote REST interfaces.
+ *
+ *
+ * <h6 class='topic'>Features</h6>
+ * <ul>
+ *     <li>Convert POJOs directly to HTTP request message bodies using {@link 
Serializer} class.
+ *     <li>Convert HTTP response message bodies directly to POJOs using {@link 
Parser} class.
+ *     <li>Fluent interface.
+ *     <li>Thread safe.
+ *     <li>API for interacting with remoteable services.
+ * </ul>
+ *
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <ul>
+ *     <li><a class='doclink' 
href='package-summary.html#RestClient'>com.ibm.juno.client &gt; REST client 
API</a> for more information and code examples.
+ * </ul>
+ *
+ * @author James Bognar ([email protected])
+ */
+public class RestClient extends CoreApi {
+
+       Map<String,Object> headers = new 
TreeMap<String,Object>(String.CASE_INSENSITIVE_ORDER);
+       CloseableHttpClient httpClient;
+       HttpClientBuilder httpClientBuilder;
+       HttpClientConnectionManager connectionManager;
+       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;
+
+       /**
+        * 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() {
+       }
+
+       /**
+        * 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) {
+               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) {
+               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) {
+               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 {
+               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 {
+               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 #getHttpClientBuilder()}.
+        *
+        * @return The HTTP client to use.
+        * @throws Exception
+        */
+       protected CloseableHttpClient createHttpClient() throws Exception {
+               return getHttpClientBuilder().build();
+       }
+
+       /**
+        * Returns the {@link HttpClientBuilder} used to create {@link 
HttpClient httpClient} in {@link #createHttpClient()}.
+        *
+        * @return The HTTP client builder to use to create the HTTP client.
+        */
+       protected HttpClientBuilder getHttpClientBuilder() {
+               if (httpClientBuilder == null)
+                       httpClientBuilder = createHttpClientBuilder();
+               return httpClientBuilder;
+       }
+
+       /**
+        * Creates an instance of an {@link HttpClientBuilder} to be used to 
create
+        *      the {@link HttpClient} the first time {@link 
#getHttpClientBuilder()} is called.
+        * <p>
+        *      Subclasses can override this method to provide their own client 
builder.
+        * </p>
+        * <p>
+        *      The predefined method returns an {@link HttpClientBuilder} with 
the following settings:
+        * </p>
+        * <ul>
+        *      <li>Lax redirect strategy.
+        *      <li>The connection manager returned by {@link 
#getConnectionManager()}.
+        * </ul>
+        *
+        * @return The HTTP client builder to use to create the HTTP client.
+        */
+       protected HttpClientBuilder createHttpClientBuilder() {
+               HttpClientBuilder b = HttpClientBuilder.create();
+               b.setRedirectStrategy(new LaxRedirectStrategy());
+               b.setConnectionManager(getConnectionManager());
+               return b;
+       }
+
+       /**
+        * Returns the {@link HttpClientConnectionManager} passed to the {@link 
HttpClientBuilder} created in {@link #createHttpClientBuilder()}.
+        *
+        * @return The HTTP client builder to use to create the HTTP client.
+        */
+       protected HttpClientConnectionManager getConnectionManager() {
+               if (connectionManager == null)
+                       connectionManager = createConnectionManager();
+               return connectionManager;
+       }
+
+       /**
+        * Creates the {@link HttpClientConnectionManager} returned by {@link 
#getConnectionManager()}.
+        * <p>
+        *      Subclasses can override this method to provide their own 
connection manager.
+        * </p>
+        * <p>
+        *      The default implementation returns an instance of a {@link 
PoolingHttpClientConnectionManager}.
+        * </p>
+        *
+        * @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 new 
PoolingHttpClientConnectionManager(r);
+                               } catch (Throwable t) {}
+                       }
+               }
+
+                       // Using pooling connection so that this client is 
threadsafe.
+               return new PoolingHttpClientConnectionManager();
+       }
+
+       /**
+        * 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;
+       }
+
+       /**
+        * Calls {@link CloseableHttpClient#close()} on the underlying {@link 
CloseableHttpClient}.
+        * It's good practice to call this method after the client is no longer 
used.
+        *
+        * @throws IOException
+        */
+       public void close() throws IOException {
+               if (httpClient != null)
+                       httpClient.close();
+       }
+
+       /**
+        * 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 = parser.getMediaTypes()[0];
+               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;
+       }
+
+       /**
+        * 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;
+       }
+
+       /**
+        * Returns the serializer currently associated with this client.
+        *
+        * @return The serializer currently associated with this client, or 
<jk>null</jk> if no serializer is currently associated.
+        */
+       public Serializer<?> getSerializer() {
+               return serializer;
+       }
+
+       /**
+        * Returns the parser currently associated with this client.
+        *
+        * @return The parser currently associated with this client, or 
<jk>null</jk> if no parser is currently associated.
+        */
+       public Parser<?> getParser() {
+               return parser;
+       }
+
+       /**
+        * Returns the {@link HttpClient} currently associated with this client.
+        *
+        * @return The HTTP client currently associated with this client.
+        * @throws Exception
+        */
+       public HttpClient getHttpClient() throws Exception {
+               if (httpClient == null)
+                       httpClient = createHttpClient();
+               return httpClient;
+       }
+
+       /**
+        * Execute the specified request.
+        * Subclasses can override this method to provide specialized handling.
+        *
+        * @param req The HTTP request.
+        * @return The HTTP response.
+        * @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.
+        * @return This object (for method chaining).
+        */
+       public RestClient setRootUrl(String rootUrl) {
+               if (rootUrl.endsWith("/"))
+                       rootUrl = rootUrl.replaceAll("\\/$", "");
+               this.rootUrl = rootUrl;
+               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);
+       }
+
+       /**
+        * Perform a <code>GET</code> request against the specified URL.
+        *
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       public RestCall doGet(Object url) throws RestCallException {
+               return doCall("GET", url, false);
+       }
+
+       /**
+        * Perform a <code>PUT</code> request against the specified URL.
+        *
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @param o The object to serialize and transmit to the URL as the body 
of the request.
+        *      Can be of the following types:
+        *      <ul>
+        *              <li>{@link Reader} - Raw contents of {@code Reader} 
will be serialized to remote resource.
+        *              <li>{@link InputStream} - Raw contents of {@code 
InputStream} will be serialized to remote resource.
+        *              <li>{@link Object} - POJO to be converted to text using 
the {@link Serializer} registered with the {@link RestClient}.
+        *              <li>{@link HttpEntity} - Bypass Juno serialization and 
pass HttpEntity directly to HttpClient.
+        *      </ul>
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       public RestCall doPut(Object url, Object o) throws RestCallException {
+               return doCall("PUT", url, true).setInput(o);
+       }
+
+       /**
+        * Perform a <code>POST</code> request against the specified URL.
+        *
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @param o The object to serialize and transmit to the URL as the body 
of the request.
+        *      Can be of the following types:
+        *      <ul>
+        *              <li>{@link Reader} - Raw contents of {@code Reader} 
will be serialized to remote resource.
+        *              <li>{@link InputStream} - Raw contents of {@code 
InputStream} will be serialized to remote resource.
+        *              <li>{@link Object} - POJO to be converted to text using 
the {@link Serializer} registered with the {@link RestClient}.
+        *              <li>{@link HttpEntity} - Bypass Juno serialization and 
pass HttpEntity directly to HttpClient.
+        *      </ul>
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       public RestCall doPost(Object url, Object o) throws RestCallException {
+               return doCall("POST", url, true).setInput(o);
+       }
+
+       /**
+        * Perform a <code>DELETE</code> request against the specified URL.
+        *
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       public RestCall doDelete(Object url) throws RestCallException {
+               return doCall("DELETE", url, false);
+       }
+
+       /**
+        * Perform an <code>OPTIONS</code> request against the specified URL.
+        *
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       public RestCall doOptions(Object url) throws RestCallException {
+               return doCall("OPTIONS", url, true);
+       }
+
+       /**
+        * Perform a <code>POST</code> request with a content type of 
<code>application/x-www-form-urlencoded</code> against the specified URL.
+        *
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @param o The object to serialize and transmit to the URL as the body 
of the request, serialized as a form post
+        *      using the {@link UrlEncodingSerializer#DEFAULT} serializer.
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       public RestCall doFormPost(Object url, Object o) throws 
RestCallException {
+               return doCall("POST", url, true)
+                       .setInput(new RestRequestEntity(o, 
urlEncodingSerializer));
+       }
+
+       /**
+        * Performs a REST call where the entire call is specified in a simple 
string.
+        * <p>
+        * This method is useful for performing callbacks when the target of a 
callback is passed in
+        * on an initial request, for example to signal when a long-running 
process has completed.
+        * <p>
+        * The call string can be any of the following formats:
+        * <ul>
+        *      <li><js>"[method] [url]"</js> - e.g. <js>"GET 
http://localhost/callback";</js>
+        *      <li><js>"[method] [url] [payload]"</js> - e.g. <js>"POST 
http://localhost/callback some text payload"</js>
+        *      <li><js>"[method] [headers] [url] [payload]"</js> - e.g. 
<js>"POST {'Content-Type':'text/json'} http://localhost/callback 
{'some':'json'}"</js>
+        * </ul>
+        * <p>
+        * The payload will always be sent using a simple {@link StringEntity}.
+        *
+        * @param callString The call string.
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException
+        */
+       public RestCall doCallback(String callString) throws RestCallException {
+               String s = callString;
+               try {
+                       RestCall rc = null;
+                       String method = null, uri = null, content = null;
+                       ObjectMap h = null;
+                       int i = s.indexOf(' ');
+                       if (i != -1) {
+                               method = s.substring(0, i).trim();
+                               s = s.substring(i).trim();
+                               if (s.length() > 0) {
+                                       if (s.charAt(0) == '{') {
+                                               i = s.indexOf('}');
+                                               if (i != -1) {
+                                                       String json = 
s.substring(0, i+1);
+                                                       h = 
JsonParser.DEFAULT.parse(json, ObjectMap.class);
+                                                       s = 
s.substring(i+1).trim();
+                                               }
+                                       }
+                                       if (s.length() > 0) {
+                                               i = s.indexOf(' ');
+                                               if (i == -1)
+                                                       uri = s;
+                                               else {
+                                                       uri = s.substring(0, 
i).trim();
+                                                       s = 
s.substring(i).trim();
+                                                       if (s.length() > 0)
+                                                               content = s;
+                                               }
+                                       }
+                               }
+                       }
+                       if (method != null && uri != null) {
+                               rc = doCall(method, uri, content != null);
+                               if (content != null)
+                                       rc.setInput(new StringEntity(content));
+                               if (h != null)
+                                       for (Map.Entry<String,Object> e : 
h.entrySet())
+                                               rc.setHeader(e.getKey(), 
e.getValue());
+                               return rc;
+                       }
+               } catch (Exception e) {
+                       throw new RestCallException(e);
+               }
+               throw new RestCallException("Invalid format for call string.");
+       }
+
+       /**
+        * Perform a generic REST call.
+        *
+        * @param method The HTTP method.
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @param content The HTTP body content.
+        *      Can be of the following types:
+        *      <ul>
+        *              <li>{@link Reader} - Raw contents of {@code Reader} 
will be serialized to remote resource.
+        *              <li>{@link InputStream} - Raw contents of {@code 
InputStream} will be serialized to remote resource.
+        *              <li>{@link Object} - POJO to be converted to text using 
the {@link Serializer} registered with the {@link RestClient}.
+        *              <li>{@link HttpEntity} - Bypass Juno serialization and 
pass HttpEntity directly to HttpClient.
+        *      </ul>
+        *      This parameter is IGNORED if {@link HttpMethod#hasContent()} is 
<jk>false</jk>.
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       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);
+               return rc;
+       }
+
+       /**
+        * Perform a generic REST call.
+        *
+        * @param method The method name (e.g. <js>"GET"</js>, 
<js>"OPTIONS"</js>).
+        * @param url The URL of the remote REST resource.  Can be any of the 
following:  {@link String}, {@link URI}, {@link URL}.
+        * @param hasContent Boolean flag indicating if the specified request 
has content associated with it.
+        * @return A {@link RestCall} object that can be further tailored 
before executing the request
+        *      and getting the response as a parsed object.
+        * @throws RestCallException If any authentication errors occurred.
+        */
+       public RestCall doCall(String method, Object url, boolean hasContent) 
throws RestCallException {
+               HttpRequestBase req = null;
+               RestCall restCall = null;
+               final String methodUC = method.toUpperCase(Locale.ENGLISH);
+               if (hasContent) {
+                       req = new HttpEntityEnclosingRequestBase() {
+                               @Override /* HttpRequest */
+                               public String getMethod() {
+                                       return methodUC;
+                               }
+                       };
+                       restCall = new RestCall(this, req);
+                       if (contentType != null)
+                               restCall.setHeader("Content-Type", contentType);
+               } else {
+                       req = new HttpRequestBase() {
+                               @Override /* HttpRequest */
+                               public String getMethod() {
+                                       return methodUC;
+                               }
+                       };
+                       restCall = new RestCall(this, req);
+               }
+               try {
+                       req.setURI(toURI(url));
+               } 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());
+               return restCall;
+       }
+
+       /**
+        * Create a new proxy interface for the specified remoteable service 
interface.
+        *
+        * @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)}.
+        */
+       @SuppressWarnings("unchecked")
+       public <T> T getRemoteableProxy(final Class<T> interfaceClass) {
+               if (remoteableServletUri == null)
+                       throw new RuntimeException("Remoteable service URI has 
not been specified.");
+               return (T)Proxy.newProxyInstance(
+                       interfaceClass.getClassLoader(),
+                       new Class[] { interfaceClass },
+                       new InvocationHandler() {
+                               @Override /* InvocationHandler */
+                               public Object invoke(Object proxy, Method 
method, Object[] args) {
+                                       try {
+                                               String uri = 
remoteableServiceUriMap.get(method);
+                                               if (uri == null) {
+                                                       // Constructing this 
string each time can be time consuming, so cache it.
+                                                       uri = 
remoteableServletUri + '/' + interfaceClass.getName() + '/' + 
ClassUtils.getMethodSignature(method);
+                                                       
remoteableServiceUriMap.put(method, uri);
+                                               }
+                                               return doPost(uri, 
args).getResponse(method.getReturnType());
+                                       } catch (Exception e) {
+                                               throw new RuntimeException(e);
+                                       }
+                               }
+               });
+       }
+
+       private Pattern absUrlPattern = Pattern.compile("^\\w+\\:\\/\\/.*");
+
+       private URI toURI(Object url) throws URISyntaxException {
+               assertFieldNotNull(url, "url");
+               if (url instanceof URI)
+                       return (URI)url;
+               if (url instanceof URL)
+                       ((URL)url).toURI();
+               String s = url.toString();
+               if (rootUrl != null && ! absUrlPattern.matcher(s).matches()) {
+                       if (s.isEmpty())
+                               s = rootUrl;
+                       else {
+                               StringBuilder sb = new StringBuilder(rootUrl);
+                               if (! s.startsWith("/"))
+                                       sb.append('/');
+                               sb.append(s);
+                               s = sb.toString();
+                       }
+               }
+               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 addFilters(Class<?>...classes) throws LockedException 
{
+               super.addFilters(classes);
+               if (serializer != null)
+                       serializer.addFilters(classes);
+               if (parser != null)
+                       parser.addFilters(classes);
+               if (urlEncodingSerializer != null)
+                       urlEncodingSerializer.addFilters(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) {
+               getHttpClientBuilder().setRedirectStrategy(redirectStrategy);
+               return this;
+       }
+
+       /**
+        * @param cookieSpecRegistry
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setDefaultCookieSpecRegistry(Lookup)
+        */
+       public RestClient 
setDefaultCookieSpecRegistry(Lookup<CookieSpecProvider> cookieSpecRegistry) {
+               
getHttpClientBuilder().setDefaultCookieSpecRegistry(cookieSpecRegistry);
+               return this;
+       }
+
+       /**
+        * @param requestExec
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setRequestExecutor(HttpRequestExecutor)
+        */
+       public RestClient setRequestExecutor(HttpRequestExecutor requestExec) {
+               getHttpClientBuilder().setRequestExecutor(requestExec);
+               return this;
+       }
+
+       /**
+        * @param hostnameVerifier
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setSSLHostnameVerifier(HostnameVerifier)
+        */
+       public RestClient setSSLHostnameVerifier(HostnameVerifier 
hostnameVerifier) {
+               getHttpClientBuilder().setSSLHostnameVerifier(hostnameVerifier);
+               return this;
+       }
+
+       /**
+        * @param publicSuffixMatcher
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setPublicSuffixMatcher(PublicSuffixMatcher)
+        */
+       public RestClient setPublicSuffixMatcher(PublicSuffixMatcher 
publicSuffixMatcher) {
+               
getHttpClientBuilder().setPublicSuffixMatcher(publicSuffixMatcher);
+               return this;
+       }
+
+       /**
+        * @param sslContext
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setSSLContext(SSLContext)
+        */
+       public RestClient setSSLContext(SSLContext sslContext) {
+               getHttpClientBuilder().setSSLContext(sslContext);
+               return this;
+       }
+
+       /**
+        * @param sslSocketFactory
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory)
+        */
+       public RestClient setSSLSocketFactory(LayeredConnectionSocketFactory 
sslSocketFactory) {
+               getHttpClientBuilder().setSSLSocketFactory(sslSocketFactory);
+               return this;
+       }
+
+       /**
+        * @param maxConnTotal
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setMaxConnTotal(int)
+        */
+       public RestClient setMaxConnTotal(int maxConnTotal) {
+               getHttpClientBuilder().setMaxConnTotal(maxConnTotal);
+               return this;
+       }
+
+       /**
+        * @param maxConnPerRoute
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setMaxConnPerRoute(int)
+        */
+       public RestClient setMaxConnPerRoute(int maxConnPerRoute) {
+               getHttpClientBuilder().setMaxConnPerRoute(maxConnPerRoute);
+               return this;
+       }
+
+       /**
+        * @param config
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setDefaultSocketConfig(SocketConfig)
+        */
+       public RestClient setDefaultSocketConfig(SocketConfig config) {
+               getHttpClientBuilder().setDefaultSocketConfig(config);
+               return this;
+       }
+
+       /**
+        * @param config
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setDefaultConnectionConfig(ConnectionConfig)
+        */
+       public RestClient setDefaultConnectionConfig(ConnectionConfig config) {
+               getHttpClientBuilder().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) {
+               getHttpClientBuilder().setConnectionTimeToLive(connTimeToLive, 
connTimeToLiveTimeUnit);
+               return this;
+       }
+
+       /**
+        * @param connManager
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setConnectionManager(HttpClientConnectionManager)
+        */
+       public RestClient setConnectionManager(HttpClientConnectionManager 
connManager) {
+               this.connectionManager = connManager;
+               getHttpClientBuilder().setConnectionManager(connManager);
+               return this;
+       }
+
+       /**
+        * @param shared
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setConnectionManagerShared(boolean)
+        */
+       public RestClient setConnectionManagerShared(boolean shared) {
+               getHttpClientBuilder().setConnectionManagerShared(shared);
+               return this;
+       }
+
+       /**
+        * @param reuseStrategy
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setConnectionReuseStrategy(ConnectionReuseStrategy)
+        */
+       public RestClient setConnectionReuseStrategy(ConnectionReuseStrategy 
reuseStrategy) {
+               
getHttpClientBuilder().setConnectionReuseStrategy(reuseStrategy);
+               return this;
+       }
+
+       /**
+        * @param keepAliveStrategy
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setKeepAliveStrategy(ConnectionKeepAliveStrategy)
+        */
+       public RestClient setKeepAliveStrategy(ConnectionKeepAliveStrategy 
keepAliveStrategy) {
+               getHttpClientBuilder().setKeepAliveStrategy(keepAliveStrategy);
+               return this;
+       }
+
+       /**
+        * @param targetAuthStrategy
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setTargetAuthenticationStrategy(AuthenticationStrategy)
+        */
+       public RestClient 
setTargetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy) {
+               
getHttpClientBuilder().setTargetAuthenticationStrategy(targetAuthStrategy);
+               return this;
+       }
+
+       /**
+        * @param proxyAuthStrategy
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setProxyAuthenticationStrategy(AuthenticationStrategy)
+        */
+       public RestClient setProxyAuthenticationStrategy(AuthenticationStrategy 
proxyAuthStrategy) {
+               
getHttpClientBuilder().setProxyAuthenticationStrategy(proxyAuthStrategy);
+               return this;
+       }
+
+       /**
+        * @param userTokenHandler
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setUserTokenHandler(UserTokenHandler)
+        */
+       public RestClient setUserTokenHandler(UserTokenHandler 
userTokenHandler) {
+               getHttpClientBuilder().setUserTokenHandler(userTokenHandler);
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#disableConnectionState()
+        */
+       public RestClient disableConnectionState() {
+               getHttpClientBuilder().disableConnectionState();
+               return this;
+       }
+
+       /**
+        * @param schemePortResolver
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setSchemePortResolver(SchemePortResolver)
+        */
+       public RestClient setSchemePortResolver(SchemePortResolver 
schemePortResolver) {
+               
getHttpClientBuilder().setSchemePortResolver(schemePortResolver);
+               return this;
+       }
+
+       /**
+        * @param userAgent
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setUserAgent(String)
+        */
+       public RestClient setUserAgent(String userAgent) {
+               getHttpClientBuilder().setUserAgent(userAgent);
+               return this;
+       }
+
+       /**
+        * @param defaultHeaders
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setDefaultHeaders(Collection)
+        */
+       public RestClient setDefaultHeaders(Collection<? extends Header> 
defaultHeaders) {
+               getHttpClientBuilder().setDefaultHeaders(defaultHeaders);
+               return this;
+       }
+
+       /**
+        * @param itcp
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#addInterceptorFirst(HttpResponseInterceptor)
+        */
+       public RestClient addInterceptorFirst(HttpResponseInterceptor itcp) {
+               getHttpClientBuilder().addInterceptorFirst(itcp);
+               return this;
+       }
+
+       /**
+        * @param itcp
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#addInterceptorLast(HttpResponseInterceptor)
+        */
+       public RestClient addInterceptorLast(HttpResponseInterceptor itcp) {
+               getHttpClientBuilder().addInterceptorLast(itcp);
+               return this;
+       }
+
+       /**
+        * @param itcp
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#addInterceptorFirst(HttpRequestInterceptor)
+        */
+       public RestClient addInterceptorFirst(HttpRequestInterceptor itcp) {
+               getHttpClientBuilder().addInterceptorFirst(itcp);
+               return this;
+       }
+
+       /**
+        * @param itcp
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#addInterceptorLast(HttpRequestInterceptor)
+        */
+       public RestClient addInterceptorLast(HttpRequestInterceptor itcp) {
+               getHttpClientBuilder().addInterceptorLast(itcp);
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#disableCookieManagement()
+        */
+       public RestClient disableCookieManagement() {
+               getHttpClientBuilder().disableCookieManagement();
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#disableContentCompression()
+        */
+       public RestClient disableContentCompression() {
+               getHttpClientBuilder().disableContentCompression();
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#disableAuthCaching()
+        */
+       public RestClient disableAuthCaching() {
+               getHttpClientBuilder().disableAuthCaching();
+               return this;
+       }
+
+       /**
+        * @param httpprocessor
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setHttpProcessor(HttpProcessor)
+        */
+       public RestClient setHttpProcessor(HttpProcessor httpprocessor) {
+               getHttpClientBuilder().setHttpProcessor(httpprocessor);
+               return this;
+       }
+
+       /**
+        * @param retryHandler
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setRetryHandler(HttpRequestRetryHandler)
+        */
+       public RestClient setRetryHandler(HttpRequestRetryHandler retryHandler) 
{
+               getHttpClientBuilder().setRetryHandler(retryHandler);
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#disableAutomaticRetries()
+        */
+       public RestClient disableAutomaticRetries() {
+               getHttpClientBuilder().disableAutomaticRetries();
+               return this;
+       }
+
+       /**
+        * @param proxy
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setProxy(HttpHost)
+        */
+       public RestClient setProxy(HttpHost proxy) {
+               getHttpClientBuilder().setProxy(proxy);
+               return this;
+       }
+
+       /**
+        * @param routePlanner
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setRoutePlanner(HttpRoutePlanner)
+        */
+       public RestClient setRoutePlanner(HttpRoutePlanner routePlanner) {
+               getHttpClientBuilder().setRoutePlanner(routePlanner);
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#disableRedirectHandling()
+        */
+       public RestClient disableRedirectHandling() {
+               getHttpClientBuilder().disableRedirectHandling();
+               return this;
+       }
+
+       /**
+        * @param connectionBackoffStrategy
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setConnectionBackoffStrategy(ConnectionBackoffStrategy)
+        */
+       public RestClient 
setConnectionBackoffStrategy(ConnectionBackoffStrategy 
connectionBackoffStrategy) {
+               
getHttpClientBuilder().setConnectionBackoffStrategy(connectionBackoffStrategy);
+               return this;
+       }
+
+       /**
+        * @param backoffManager
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setBackoffManager(BackoffManager)
+        */
+       public RestClient setBackoffManager(BackoffManager backoffManager) {
+               getHttpClientBuilder().setBackoffManager(backoffManager);
+               return this;
+       }
+
+       /**
+        * @param serviceUnavailStrategy
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)
+        */
+       public RestClient 
setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy 
serviceUnavailStrategy) {
+               
getHttpClientBuilder().setServiceUnavailableRetryStrategy(serviceUnavailStrategy);
+               return this;
+       }
+
+       /**
+        * @param cookieStore
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setDefaultCookieStore(CookieStore)
+        */
+       public RestClient setDefaultCookieStore(CookieStore cookieStore) {
+               getHttpClientBuilder().setDefaultCookieStore(cookieStore);
+               return this;
+       }
+
+       /**
+        * @param credentialsProvider
+        * @return This object (for method chaining).
+        * @see 
HttpClientBuilder#setDefaultCredentialsProvider(CredentialsProvider)
+        */
+       public RestClient setDefaultCredentialsProvider(CredentialsProvider 
credentialsProvider) {
+               
getHttpClientBuilder().setDefaultCredentialsProvider(credentialsProvider);
+               return this;
+       }
+
+       /**
+        * @param authSchemeRegistry
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setDefaultAuthSchemeRegistry(Lookup)
+        */
+       public RestClient 
setDefaultAuthSchemeRegistry(Lookup<AuthSchemeProvider> authSchemeRegistry) {
+               
getHttpClientBuilder().setDefaultAuthSchemeRegistry(authSchemeRegistry);
+               return this;
+       }
+
+       /**
+        * @param contentDecoderMap
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setContentDecoderRegistry(Map)
+        */
+       public RestClient 
setContentDecoderRegistry(Map<String,InputStreamFactory> contentDecoderMap) {
+               
getHttpClientBuilder().setContentDecoderRegistry(contentDecoderMap);
+               return this;
+       }
+
+       /**
+        * @param config
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#setDefaultRequestConfig(RequestConfig)
+        */
+       public RestClient setDefaultRequestConfig(RequestConfig config) {
+               getHttpClientBuilder().setDefaultRequestConfig(config);
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#useSystemProperties()
+        */
+       public RestClient useSystemProperties() {
+               getHttpClientBuilder().useSystemProperties();
+               return this;
+       }
+
+       /**
+        * @return This object (for method chaining).
+        * @see HttpClientBuilder#evictExpiredConnections()
+        */
+       public RestClient evictExpiredConnections() {
+               getHttpClientBuilder().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) {
+               getHttpClientBuilder().evictIdleConnections(maxIdleTime, 
maxIdleTimeUnit);
+               return this;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.class
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.class
new file mode 100755
index 0000000..10ee13e
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.class
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.java
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.java
new file mode 100755
index 0000000..9336c23
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RestRequestEntity.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import java.io.*;
+
+import org.apache.http.entity.*;
+import org.apache.http.message.*;
+
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.utils.*;
+
+/**
+ * HttpEntity for serializing POJOs as the body of HTTP requests.
+ *
+ * @author James Bognar ([email protected])
+ */
+public final class RestRequestEntity extends BasicHttpEntity {
+       final Object output;
+       final Serializer<?> serializer;
+       byte[] outputBytes;
+
+       /**
+        * Constructor.
+        * @param input The POJO to serialize.  Can also be a {@link Reader} or 
{@link InputStream}.
+        * @param serializer The serializer to use to serialize this response.
+        */
+       public RestRequestEntity(Object input, Serializer<?> serializer) {
+               this.output = input;
+               this.serializer = serializer;
+               if (serializer != null)
+                       setContentType(new BasicHeader("Content-Type", 
serializer.getResponseContentType()));
+       }
+
+       @Override /* BasicHttpEntity */
+       public void writeTo(OutputStream os) throws IOException {
+               if (output instanceof InputStream) {
+                       IOPipe.create(output, os).closeOut().run();
+               } else if (output instanceof Reader) {
+                       IOPipe.create(output, new OutputStreamWriter(os, 
IOUtils.UTF8)).closeOut().run();
+               } else {
+                       try {
+                               if (serializer == null) {
+                                       // If no serializer specified, just 
close the stream.
+                                       os.close();
+                               } else if (! serializer.isWriterSerializer()) {
+                                       OutputStreamSerializer s2 = 
(OutputStreamSerializer)serializer;
+                                       s2.serialize(output, os);
+                                       os.close();
+                               } else {
+                                       Writer w = new OutputStreamWriter(os, 
IOUtils.UTF8);
+                                       WriterSerializer s2 = 
(WriterSerializer)serializer;
+                                       s2.serialize(output, w);
+                                       w.close();
+                               }
+                       } catch (SerializeException e) {
+                               throw new 
com.ibm.juno.client.RestCallException(e);
+                       }
+               }
+       }
+
+       @Override /* BasicHttpEntity */
+       public boolean isRepeatable() {
+               return true;
+       }
+
+       @Override /* BasicHttpEntity */
+       public InputStream getContent() {
+               if (outputBytes == null) {
+                       ByteArrayOutputStream baos = new 
ByteArrayOutputStream();
+                       try {
+                               writeTo(baos);
+                               outputBytes = baos.toByteArray();
+                       } catch (IOException e) {
+                               throw new RuntimeException(e);
+                       }
+               }
+               return new ByteArrayInputStream(outputBytes);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn$1.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn$1.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn$1.class
new file mode 100755
index 0000000..243a150
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn$1.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.class
new file mode 100755
index 0000000..5b38ebc
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.java 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.java
new file mode 100755
index 0000000..6b9bf75
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/RetryOn.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+/**
+ * Used to determine whether a request should be retried based on the HTTP 
response code.
+ *
+ * @author James Bognar ([email protected])
+ */
+public interface RetryOn {
+
+       /**
+        * Default RetryOn that returns <jk>true</jk> of any HTTP response 
&gt;= 400 is received.
+        */
+       public static final RetryOn DEFAULT = new RetryOn() {
+               @Override /* RetryOn */
+               public boolean onCode(int httpResponseCode) {
+                       return httpResponseCode <= 0 || httpResponseCode >= 400;
+               }
+       };
+
+       /**
+        * Subclasses should override this method to determine whether the HTTP 
response is retryable.
+        *
+        * @param httpResponseCode The HTTP response code.
+        * @return <jk>true</jk> if the specified response code is retryable.
+        */
+       boolean onCode(int httpResponseCode);
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$CertValidate.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$CertValidate.class
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$CertValidate.class
new file mode 100755
index 0000000..9d5c1ac
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$CertValidate.class
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$HostVerify.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$HostVerify.class
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$HostVerify.class
new file mode 100755
index 0000000..5e5fc3c
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts$HostVerify.class
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.class 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.class
new file mode 100755
index 0000000..0f1923d
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.java 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.java
new file mode 100755
index 0000000..2a7ed82
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SSLOpts.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2015. All Rights Reserved.
+ *
+ * The source code for this program is not published or otherwise
+ * divested of its trade secrets, irrespective of what has been
+ * deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import com.ibm.juno.core.utils.*;
+
+/**
+ * SSL configuration options that get passed to {@link 
RestClient#enableSSL(SSLOpts)}.
+ *
+ * @author James Bognar ([email protected])
+ */
+public class SSLOpts {
+
+       private String protocols = getDefaultProtocols();
+       private CertValidate certValidate = CertValidate.DEFAULT;
+       private HostVerify hostVerify = HostVerify.DEFAULT;
+
+       /**
+        * Reusable SSL options for lenient SSL (no cert validation or hostname 
verification).
+        */
+       public static final SSLOpts LAX = new SSLOpts(null, CertValidate.LAX, 
HostVerify.LAX);
+
+       /**
+        * Reusable SSL options for normal SSL (default cert validation and 
hostname verification).
+        */
+       public static final SSLOpts DEFAULT = new SSLOpts(null, 
CertValidate.DEFAULT, HostVerify.DEFAULT);
+
+       /**
+        * Constructor.
+        */
+       public SSLOpts() {}
+
+       /**
+        * Constructor.
+        *
+        * @param protocols A comma-delimited list of supported SSL protocols.
+        *      If <jk>null</jk>, uses the value returned by {@link 
#getDefaultProtocols()}.
+        * @param certValidate Certificate validation setting.
+        * @param hostVerify Host verification setting.
+        */
+       public SSLOpts(String protocols, CertValidate certValidate, HostVerify 
hostVerify) {
+               if (protocols != null)
+                       this.protocols = protocols;
+               this.certValidate = certValidate;
+               this.hostVerify = hostVerify;
+       }
+
+       /**
+        * Returns the default list of SSL protocols to support when the 
<code>protocols</code>
+        *      parameter on the constructor is <jk>null</jk>.
+        * <p>
+        * The default value is <jk>"SSL_TLS,TLS,SSL"</js> unless overridden by 
one of the following
+        *      system properties:
+        * <ul>
+        *      <li><js>"com.ibm.team.repository.transport.client.protocol"</js>
+        *      <li><js>"transport.client.protocol"</js>
+        * </ul>
+        * <p>
+        * Subclasses can override this method to provide their own logic for 
determining default supported protocols.
+        *
+        * @return The comma-delimited list of supported protocols.
+        */
+       protected String getDefaultProtocols() {
+               String sp = 
System.getProperty("com.ibm.team.repository.transport.client.protocol");
+               if (StringUtils.isEmpty(sp))
+                       sp = System.getProperty("transport.client.protocol");
+               if (StringUtils.isEmpty(sp))
+                       sp = "SSL_TLS,TLS,SSL";
+               return sp;
+       }
+
+
+       
//--------------------------------------------------------------------------------
+       // Bean properties
+       
//--------------------------------------------------------------------------------
+
+       /**
+        * Bean property getter:  <property>protocols</property>.
+        *
+        * @return The value of the <property>protocols</property> property on 
this bean, or <jk>null</jk> if it is not set.
+        */
+       public String getProtocols() {
+               return protocols;
+       }
+
+       /**
+        * Bean property setter:  <property>protocols</property>.
+        *
+        * @param protocols The new value for the 
<property>properties</property> property on this bean.
+        * @return This object (for method chaining).
+        */
+       public SSLOpts setProtocols(String protocols) {
+               this.protocols = protocols;
+               return this;
+       }
+
+       /**
+        * Bean property getter:  <property>certValidate</property>.
+        *
+        * @return The value of the <property>certValidate</property> property 
on this bean, or <jk>null</jk> if it is not set.
+        */
+       public CertValidate getCertValidate() {
+               return certValidate;
+       }
+
+       /**
+        * Bean property setter:  <property>certValidate</property>.
+        *
+        * @param certValidate The new value for the 
<property>properties</property> property on this bean.
+        * @return This object (for method chaining).
+        */
+       public SSLOpts setCertValidate(CertValidate certValidate) {
+               this.certValidate = certValidate;
+               return this;
+       }
+
+       /**
+        * Bean property getter:  <property>hostVerify</property>.
+        *
+        * @return The value of the <property>hostVerify</property> property on 
this bean, or <jk>null</jk> if it is not set.
+        */
+       public HostVerify getHostVerify() {
+               return hostVerify;
+       }
+
+       /**
+        * Bean property setter:  <property>hostVerify</property>.
+        *
+        * @param hostVerify The new value for the 
<property>properties</property> property on this bean.
+        * @return This object (for method chaining).
+        */
+       public SSLOpts setHostVerify(HostVerify hostVerify) {
+               this.hostVerify = hostVerify;
+               return this;
+       }
+
+
+       
//--------------------------------------------------------------------------------
+       // Enums
+       
//--------------------------------------------------------------------------------
+
+       /**
+        * Certificate validation options.
+        * <p>
+        * Used as enum for {@link SSLOpts#getCertValidate()} property.
+        */
+       @SuppressWarnings("hiding")
+       public static enum CertValidate {
+
+               /**
+                * Verify that the certificate is valid, but allow for 
self-signed certificates.
+                */
+               LAX,
+
+               /**
+                * Do normal certificate chain validation.
+                */
+               DEFAULT
+       }
+
+       /**
+        * Certificate host verification options.
+        * <p>
+        * Used as enum for {@link SSLOpts#getHostVerify()} property.
+        */
+       @SuppressWarnings("hiding")
+       public enum HostVerify {
+
+               /**
+                * Don't verify the hostname in the certificate.
+                */
+               LAX,
+
+               /**
+                * Do normal hostname verification.
+                */
+               DEFAULT
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.class
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.class
new file mode 100755
index 0000000..1dd1178
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.class
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.java
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.java
new file mode 100755
index 0000000..cdb3b2e
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SerializedNameValuePair.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import static com.ibm.juno.core.urlencoding.UonSerializerProperties.*;
+
+import org.apache.http.*;
+
+import com.ibm.juno.core.*;
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.urlencoding.*;
+
+/**
+ * Subclass of {@link NameValuePair} for serializing POJOs as URL-encoded form 
post entries
+ *     using the {@link UrlEncodingSerializer class}.
+ * <p>
+ * Example:
+ * <p class='bcode'>
+ *     NameValuePairs params = <jk>new</jk> NameValuePairs()
+ *             .append(<jk>new</jk> SerializedNameValuePair(<js>"myPojo"</js>, 
pojo, UrlEncodingSerializer.<jsf>DEFAULT_SIMPLE</jsf>))
+ *             .append(<jk>new</jk> 
BasicNameValuePair(<js>"someOtherParam"</js>, <js>"foobar"</js>));
+ *     request.setEntity(<jk>new</jk> UrlEncodedFormEntity(params));
+ * </p>
+ *
+ * @author James Bognar ([email protected])
+ */
+public final class SerializedNameValuePair implements NameValuePair {
+       private String name;
+       private Object value;
+       private UrlEncodingSerializer serializer;
+
+       // We must be sure to disable character encoding since it's done in the 
http client layer.
+       private static final ObjectMap op = new 
ObjectMap().append(UON_encodeChars, false);
+
+       /**
+        * Constructor.
+        *
+        * @param name The parameter name.
+        * @param value The POJO to serialize to the parameter value.
+        * @param serializer The serializer to use to convert the value to a 
string.
+        */
+       public SerializedNameValuePair(String name, Object value, 
UrlEncodingSerializer serializer) {
+               this.name = name;
+               this.value = value;
+               this.serializer = serializer;
+       }
+
+       @Override /* NameValuePair */
+       public String getName() {
+               if (name != null && name.length() > 0) {
+                       char c = name.charAt(0);
+                       if (c == '$' || c == '(') {
+                               try {
+                                       UonSerializerContext ctx = 
serializer.createContext(op, null);
+                                       return serializer.serialize(name, ctx);
+                               } catch (SerializeException e) {
+                                       throw new RuntimeException(e);
+                               }
+                       }
+               }
+               return name;
+       }
+
+       @Override /* NameValuePair */
+       public String getValue() {
+               try {
+                       UonSerializerContext ctx = serializer.createContext(op, 
null);
+                       return serializer.serialize(value, ctx);
+               } catch (SerializeException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.class
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.class
new file mode 100755
index 0000000..72c6dc0
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.class
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.java
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.java
new file mode 100755
index 0000000..72975cb
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/SimpleX509TrustManager.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2010, 2015. All Rights Reserved.
+ *
+ * The source code for this program is not published or otherwise
+ * divested of its trade secrets, irrespective of what has been
+ * deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.client;
+
+import java.security.*;
+import java.security.cert.*;
+
+import javax.net.ssl.*;
+
+/**
+ * A trust manager that optionally allows for self-signed certificates.
+ */
+public final class SimpleX509TrustManager implements X509TrustManager {
+
+       private X509TrustManager baseTrustManager;  // The JRE-provided trust 
manager used to validate certificates presented by a server.
+
+       /**
+        * Constructor.
+        *
+        * @param lax If <jk>true</jk>, allow self-signed and expired 
certificates.
+        * @throws KeyStoreException
+        * @throws NoSuchAlgorithmException
+        */
+       public SimpleX509TrustManager(boolean lax) throws KeyStoreException, 
NoSuchAlgorithmException {
+               if (! lax) {
+                       // Find the JRE-provided X509 trust manager.
+                       KeyStore ks = KeyStore.getInstance("jks");
+                       TrustManagerFactory factory = 
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+                       factory.init(ks);
+                       for (TrustManager tm : factory.getTrustManagers()) {
+                               if (tm instanceof X509TrustManager) {
+                                       baseTrustManager = 
(X509TrustManager)tm; // Take the first X509TrustManager we find
+                                       return;
+                               }
+                       }
+                       throw new IllegalStateException("Couldn't find JRE's 
X509TrustManager"); //$NON-NLS-1$
+               }
+       }
+
+       @Override /* X509TrustManager */
+       public X509Certificate[] getAcceptedIssuers() {
+               return baseTrustManager == null ? new X509Certificate[0] : 
baseTrustManager.getAcceptedIssuers();
+       }
+
+       @Override /* X509TrustManager */
+       public void checkClientTrusted(X509Certificate[] chain, String 
authType) throws CertificateException {
+               if (baseTrustManager != null)
+                       baseTrustManager.checkClientTrusted(chain, authType);
+       }
+
+       @Override /* X509TrustManager */
+       public void checkServerTrusted(X509Certificate[] chain, String 
authType) throws CertificateException {
+               if (baseTrustManager != null)
+                       baseTrustManager.checkServerTrusted(chain, authType);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/deprecated/CertificateStore.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/deprecated/CertificateStore.class
 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/deprecated/CertificateStore.class
new file mode 100755
index 0000000..aad4ecd
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/client/com/ibm/juno/client/deprecated/CertificateStore.class
 differ

Reply via email to