You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/10/16 13:22:51 UTC

[isis] branch v2 updated (53ddb25 -> 0d4c71b)

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a change to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from 53ddb25  ISIS-2006: fixes java-doc
     new 6edfca4  ISIS-2006: more fixes for java-doc, also showing simplified usage
     new 0d4c71b  ISIS-2006: adding a jax-rs request/response debug logging filter

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/isis/applib/client/RestfulClient.java   |  81 ++++++++-----
 .../isis/applib/client/RestfulClientConfig.java    |  42 ++++---
 .../isis/applib/client/auth/BasicAuthFilter.java   |   2 +
 .../applib/client/log/RestfulLoggingFilter.java    | 128 +++++++++++++++++++++
 .../isis/commons/internal/base/_Strings.java       |  10 ++
 .../internal/base/_Strings_KeyValuePair.java       |  26 +++++
 6 files changed, 246 insertions(+), 43 deletions(-)
 create mode 100644 core/applib/src/main/java/org/apache/isis/applib/client/log/RestfulLoggingFilter.java


[isis] 01/02: ISIS-2006: more fixes for java-doc, also showing simplified usage

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 6edfca43561f036876ef8ae8cdcc8c67db5523b3
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Oct 16 12:11:53 2018 +0200

    ISIS-2006: more fixes for java-doc, also showing simplified usage
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-2006
---
 .../apache/isis/applib/client/RestfulClient.java   | 25 +++++++++++-----------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java
index e155711..8009e25 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java
@@ -37,7 +37,7 @@ import org.apache.isis.commons.internal.context._Context;
 
 /**
  * Setup the Restful Client with Basic-Auth:
- * <pre>
+ * <blockquote><pre>
 RestfulClientConfig clientConfig = new RestfulClientConfig();
 clientConfig.setRestfulBase("http://localhost:8080/helloworld/restful/");
 // setup basic-auth
@@ -46,14 +46,14 @@ clientConfig.setRestfulAuthUser("sven");
 clientConfig.setRestfulAuthPassword("pass");
 
 RestfulClient client = RestfulClient.ofConfig(clientConfig);
- * </pre>
+ * </pre></blockquote>
  * 
  * Synchronous example:
- * <pre>
+ * <blockquote><pre>{@code
 
 Builder request = client.request(
                 "services/myService/actions/lookupMyObjectById/invoke", 
-                SuppressionType.setOf(SuppressionType.RO));
+                SuppressionType.RO);
 
 Entity<String> args = client.arguments()
         .addActionParameter("id", "12345")
@@ -62,19 +62,19 @@ Entity<String> args = client.arguments()
 Response response = request.post(args);
 
 ResponseDigest<MyObject> digest = client.digest(response, MyObject.class);
+}
 
 if(digest.isSuccess()) {
     System.out.println("result: "+ digest.get().get$$instanceId());
 } else {
     digest.getFailureCause().printStackTrace();
 }
- * </pre>
+ * </pre></blockquote>
  * Asynchronous example:
- * <pre>
- 
+ * <blockquote><pre>{@code 
 Builder request = client.request(
                 "services/myService/actions/lookupMyObjectById/invoke", 
-                SuppressionType.setOf(SuppressionType.RO));
+                SuppressionType.RO);
 
 Entity<String> args = client.arguments()
         .addActionParameter("id", "12345")
@@ -88,16 +88,17 @@ CompletableFuture<ResponseDigest<MyObject>> digestFuture =
                 client.digest(asyncResponse, MyObject.class);
         
 ResponseDigest<MyObject> digest = digestFuture.get(); // blocking
+}
 
 if(digest.isSuccess()) {
     System.out.println("result: "+ digest.get().get$$instanceId());
 } else {
     digest.getFailureCause().printStackTrace();
 }
- * </pre>
+ * </pre></blockquote>
  * 
  * Maven Setup:
- * <pre>{@code
+ * <blockquote><pre>{@code
 <dependency>
     <groupId>org.apache.isis.core</groupId>
     <artifactId>isis-core-applib</artifactId>
@@ -117,8 +118,8 @@ if(digest.isSuccess()) {
     <groupId>org.eclipse.persistence</groupId>
     <artifactId>org.eclipse.persistence.moxy</artifactId>
     <version>2.6.0</version>
-</dependency>} 
- * </pre>
+</dependency>
+ * }</pre></blockquote>
  * 
  * @since 2.0.0-M2
  */


[isis] 02/02: ISIS-2006: adding a jax-rs request/response debug logging filter

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 0d4c71b9841c661ca34dc4e2959fbc51835c543c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Oct 16 12:51:36 2018 +0200

    ISIS-2006: adding a jax-rs request/response debug logging filter
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-2006
---
 .../apache/isis/applib/client/RestfulClient.java   |  56 ++++++---
 .../isis/applib/client/RestfulClientConfig.java    |  42 ++++---
 .../isis/applib/client/auth/BasicAuthFilter.java   |   2 +
 .../applib/client/log/RestfulLoggingFilter.java    | 128 +++++++++++++++++++++
 .../isis/commons/internal/base/_Strings.java       |  10 ++
 .../internal/base/_Strings_KeyValuePair.java       |  26 +++++
 6 files changed, 233 insertions(+), 31 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java
index 8009e25..6496db1 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClient.java
@@ -23,6 +23,7 @@ import static org.apache.isis.commons.internal.base._NullSafe.stream;
 import java.util.EnumSet;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
+import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
 import javax.ws.rs.client.Client;
@@ -32,6 +33,7 @@ import javax.ws.rs.core.Response;
 
 import org.apache.isis.applib.client.auth.BasicAuthFilter;
 import org.apache.isis.applib.client.auth.BasicAuthFilter.Credentials;
+import org.apache.isis.applib.client.log.RestfulLoggingFilter;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.context._Context;
 
@@ -41,9 +43,11 @@ import org.apache.isis.commons.internal.context._Context;
 RestfulClientConfig clientConfig = new RestfulClientConfig();
 clientConfig.setRestfulBase("http://localhost:8080/helloworld/restful/");
 // setup basic-auth
-clientConfig.setUseBasicAuth(true);
+clientConfig.setUseBasicAuth(true); // default = false
 clientConfig.setRestfulAuthUser("sven");
 clientConfig.setRestfulAuthPassword("pass");
+// setup request/response debug logging
+clientConfig.setUseRequestDebugLogging(true); // default = false
 
 RestfulClient client = RestfulClient.ofConfig(clientConfig);
  * </pre></blockquote>
@@ -125,7 +129,9 @@ if(digest.isSuccess()) {
  */
 public class RestfulClient {
     
-    public static String DEFAULT_RESPONSE_CONTENT_TYPE = "application/json;profile=urn:org.apache.isis/v1";
+    private static final Logger LOG = Logger.getLogger(RestfulClient.class.getName());
+    
+    public static String DEFAULT_RESPONSE_CONTENT_TYPE = "application/json;profile=\"urn:org.apache.isis/v1\"";
 
     private RestfulClientConfig clientConfig;
     private Client client;
@@ -140,22 +146,11 @@ public class RestfulClient {
         this.clientConfig = clientConfig;
         client = ClientBuilder.newClient();
         
-        if(clientConfig.isUseBasicAuth()){
-            final Credentials credentials = Credentials.of(
-                    clientConfig.getRestfulAuthUser(), 
-                    clientConfig.getRestfulAuthPassword());
-            client.register(BasicAuthFilter.of(credentials));
-        }
-        
-        try {
-            Class<?> MOXyJsonProvider = _Context.loadClass("org.eclipse.persistence.jaxb.rs.MOXyJsonProvider");
-            client.register(MOXyJsonProvider);
-        } catch (Exception e) {
-            // this is just provided for convenience
-        }
-        
+        registerDefaultJsonProvider();
+        registerBasicAuthFilter();
+        registerRequestDebugLoggingFilter();
     }
-    
+
     public RestfulClientConfig getConfig() {
         return clientConfig;
     }
@@ -210,6 +205,33 @@ public class RestfulClient {
         return completableFuture;
     }
     
+    // -- FILTER
+    
+    private void registerDefaultJsonProvider() {
+        try {
+            Class<?> MOXyJsonProvider = _Context.loadClass("org.eclipse.persistence.jaxb.rs.MOXyJsonProvider");
+            client.register(MOXyJsonProvider);
+        } catch (Exception e) {
+            LOG.warning("This implementaion of RestfulClient does require the class 'MOXyJsonProvider' on the class-path."
+                    + " Are you missing a maven dependency?");
+        }
+    }
+    
+    private void registerBasicAuthFilter() {
+        if(clientConfig.isUseBasicAuth()){
+            final Credentials credentials = Credentials.of(
+                    clientConfig.getRestfulAuthUser(), 
+                    clientConfig.getRestfulAuthPassword());
+            client.register(BasicAuthFilter.of(credentials));
+        }
+    }
+    
+    private void registerRequestDebugLoggingFilter() {
+        if(clientConfig.isUseRequestDebugLogging()){
+            client.register(new RestfulLoggingFilter());
+        }
+    }
+    
     // -- HELPER
     
     private String relativePathToUri(String path) {
diff --git a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java
index c0578b1..cdd9b84 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java
@@ -32,23 +32,23 @@ import javax.xml.bind.annotation.XmlRootElement;
 public class RestfulClientConfig {
 
     // --
-    
+
     @XmlElement(name="restfulBase") 
     private String restfulBase;
-    
+
     public String getRestfulBase() {
         return restfulBase;
     }
-    
+
     public void setRestfulBase(String restfulBase) {
         this.restfulBase = restfulBase;
     }
-    
+
     // --
-    
+
     @XmlElement(name="useBasicAuth") 
     private boolean useBasicAuth;
-    
+
     public boolean isUseBasicAuth() {
         return useBasicAuth;
     }
@@ -56,32 +56,46 @@ public class RestfulClientConfig {
     public void setUseBasicAuth(boolean useBasicAuth) {
         this.useBasicAuth = useBasicAuth;
     }
-    
+
     // --
 
     @XmlElement(name="restfulAuthUser")
     private String restfulAuthUser;
-    
+
     public String getRestfulAuthUser() {
         return restfulAuthUser;
     }
-    
+
     public void setRestfulAuthUser(String restfulAuthUser) {
         this.restfulAuthUser = restfulAuthUser;
     }
-    
+
     // --
 
     @XmlElement(name="restfulAuthPassword")
     private String restfulAuthPassword;
-    
+
     public String getRestfulAuthPassword() {
         return restfulAuthPassword;
     }
-    
+
     public void setRestfulAuthPassword(String restfulAuthPassword) {
         this.restfulAuthPassword = restfulAuthPassword;
     }
-    
-    
+
+    // --
+
+    @XmlElement(name="useRequestDebugLogging") 
+    private boolean useRequestDebugLogging;
+
+    public boolean isUseRequestDebugLogging() {
+        return useRequestDebugLogging;
+    }
+
+    public void setUseRequestDebugLogging(boolean useRequestDebugLogging) {
+        this.useRequestDebugLogging = useRequestDebugLogging;
+    }
+
+    // --
+
 }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/client/auth/BasicAuthFilter.java b/core/applib/src/main/java/org/apache/isis/applib/client/auth/BasicAuthFilter.java
index 3f4f39e..201e35b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/client/auth/BasicAuthFilter.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/client/auth/BasicAuthFilter.java
@@ -23,6 +23,7 @@ import static org.apache.isis.commons.internal.base._With.requires;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 
+import javax.annotation.Priority;
 import javax.ws.rs.client.ClientRequestContext;
 import javax.ws.rs.client.ClientRequestFilter;
 import javax.xml.bind.DatatypeConverter;
@@ -33,6 +34,7 @@ import org.apache.isis.commons.internal.base._Strings;
  * 
  * @since 2.0.0-M2
  */
+@Priority(100)
 public class BasicAuthFilter implements ClientRequestFilter {
 
     /**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/client/log/RestfulLoggingFilter.java b/core/applib/src/main/java/org/apache/isis/applib/client/log/RestfulLoggingFilter.java
new file mode 100644
index 0000000..8ea45f1
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/client/log/RestfulLoggingFilter.java
@@ -0,0 +1,128 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.client.log;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import javax.annotation.Priority;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+
+import org.apache.isis.commons.internal.base._Strings;
+
+/**
+ * 
+ * @since 2.0.0-M2
+ */
+@Priority(999)
+public class RestfulLoggingFilter implements ClientRequestFilter, ClientResponseFilter{
+    private static final Logger LOG = Logger.getLogger(RestfulLoggingFilter.class.getName());
+
+    @Override
+    public void filter(ClientRequestContext requestContext) throws IOException {
+        final String endpoint = requestContext.getUri().toString();
+        final String method = requestContext.getMethod();
+        
+        Exception acceptableMediaTypeParsingFailure;
+        try {
+            @SuppressWarnings("unused")
+            final String acceptableMediaTypes = requestContext.getAcceptableMediaTypes().toString();
+            acceptableMediaTypeParsingFailure = null;
+        } catch (Exception e) {
+            acceptableMediaTypeParsingFailure = e;
+        }
+        final String acceptHeaderParsing = acceptableMediaTypeParsingFailure != null
+                ? "Failed to parse accept header, cause: " + acceptableMediaTypeParsingFailure.getMessage()
+                    : "OK";
+        
+        final String headers = requestContext.getStringHeaders().entrySet().stream()
+                .map(entry->entry.toString())
+                .map(this::obscureAuthHeader)
+                .collect(Collectors.joining(",\n\t"));
+        
+        final String requestBody = requestContext.getEntity().toString();
+        
+        final StringBuilder sb = new StringBuilder();
+        sb.append("\n")
+        .append("---------- JAX-RS REQUEST -------------\n")
+        .append("uri: ").append(endpoint).append("\n")
+        .append("method: ").append(method).append("\n")
+        .append("accept-header-parsing: ").append(acceptHeaderParsing).append("\n")
+        .append("headers: \n\t").append(headers).append("\n")
+        .append("request-body: ").append(requestBody).append("\n")
+        .append("----------------------------------------\n")
+        ;
+        
+        LOG.log(Level.INFO, sb.toString());
+    }
+    
+    @Override
+    public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+        
+        final InputStream inputStream = responseContext.getEntityStream();
+        final String responseBody;
+        if(inputStream!=null) {
+            responseBody = _Strings.read(responseContext.getEntityStream(), StandardCharsets.UTF_8);
+            responseContext.setEntityStream(new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)));    
+        } else {
+            responseBody = "null";
+        }
+        
+        final StringBuilder sb = new StringBuilder();
+        sb.append("\n")
+        .append("---------- JAX-RS RESPONSE -------------\n")
+        .append("response-body: ").append(responseBody).append("\n")
+        .append("----------------------------------------\n")
+        ;
+        
+        LOG.log(Level.INFO, sb.toString());
+        
+    }
+       
+    // -- HELPER
+    
+    private final String basicAuthMagic = "Authorization=[Basic "; 
+    
+    String obscureAuthHeader(String keyValueLiteral) {
+        if(_Strings.isEmpty(keyValueLiteral)) {
+            return keyValueLiteral;
+        }
+        if(keyValueLiteral.startsWith(basicAuthMagic)) {
+            
+            final String obscured = _Strings.padEnd(basicAuthMagic, keyValueLiteral.length() - 1, '*') + "]";
+            return obscured;
+            
+        }
+        return keyValueLiteral;
+    }
+
+
+    
+    
+    
+    
+}
\ No newline at end of file
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java
index 38fd902..8596840 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java
@@ -28,6 +28,7 @@ import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Scanner;
 import java.util.Spliterator;
 import java.util.Spliterators;
@@ -76,6 +77,15 @@ public final class _Strings {
         return _Strings_KeyValuePair.of(key, value);
     }
     
+    /**
+     * Parses a string assumed to be of the form <kbd>key=value</kbd> into its parts.
+     *
+     * @return a non-empty Optional, if (and only if) the {@code keyValueLiteral} does contain at least one '='
+     */
+    public static Optional<KeyValuePair> parseKeyValuePair(@Nullable String keyValueLiteral) {
+        return _Strings_KeyValuePair.parse(keyValueLiteral);
+    }
+    
     // -- FILLING
     
     public static String of(int length, char c) {
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings_KeyValuePair.java b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings_KeyValuePair.java
index 7696a48..3fa619a 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings_KeyValuePair.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings_KeyValuePair.java
@@ -21,6 +21,8 @@ package org.apache.isis.commons.internal.base;
 
 import static org.apache.isis.commons.internal.exceptions._Exceptions.notImplemented;
 
+import java.util.Optional;
+
 import org.apache.isis.commons.internal.base._Strings.KeyValuePair;
 
 /**
@@ -56,5 +58,29 @@ final class _Strings_KeyValuePair implements _Strings.KeyValuePair {
     public String setValue(String value) {
         throw notImplemented();
     }
+    
+    /**
+     * Parses a string assumed to be of the form <kbd>key=value</kbd> into its parts.
+     *
+     * @return a non-empty Optional, if (and only if) the {@code keyValueLiteral} does contain at least one '='
+     */
+    public static Optional<KeyValuePair> parse(String keyValueLiteral) {
+        
+        if(_Strings.isNullOrEmpty(keyValueLiteral)) {
+            return Optional.empty();
+        }
+        
+        final int equalsIndex = keyValueLiteral.indexOf('=');
+        if (equalsIndex == -1) {
+            return Optional.empty();
+        }
+
+        String aKey = keyValueLiteral.substring(0, equalsIndex);
+        String aValue = equalsIndex == keyValueLiteral.length() - 1 
+                ? "" 
+                        : keyValueLiteral.substring(equalsIndex + 1);
+
+        return Optional.of(of(aKey, aValue));
+    }
 
 }