GUACAMOLE-566: Replace the entire RESTExceptionWrapper with the ExceptionMapper 
implementation.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/eb91f4d8
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/eb91f4d8
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/eb91f4d8

Branch: refs/heads/master
Commit: eb91f4d87a408ff82a308fe9f45069771d5ba1aa
Parents: a603774
Author: Nick Couchman <[email protected]>
Authored: Tue May 29 17:24:54 2018 -0400
Committer: Nick Couchman <[email protected]>
Committed: Tue May 29 17:59:53 2018 -0400

----------------------------------------------------------------------
 .../guacamole/extension/ExtensionModule.java    |   6 +-
 .../rest/GuacamoleExceptionMapper.java          |  60 +++++-
 .../guacamole/rest/RESTExceptionWrapper.java    | 200 -------------------
 .../guacamole/rest/RESTServiceModule.java       |   5 -
 4 files changed, 60 insertions(+), 211 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/eb91f4d8/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java 
b/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java
index 665c028..822741c 100644
--- 
a/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java
+++ 
b/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java
@@ -39,7 +39,6 @@ import org.apache.guacamole.resource.Resource;
 import org.apache.guacamole.resource.ResourceServlet;
 import org.apache.guacamole.resource.SequenceResource;
 import org.apache.guacamole.resource.WebApplicationResource;
-import org.apache.guacamole.rest.GuacamoleExceptionMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -418,10 +417,7 @@ public class ExtensionModule extends ServletModule {
         // Bind resource services
         
bind(LanguageResourceService.class).toInstance(languageResourceService);
         bind(PatchResourceService.class).toInstance(patchResourceService);
-
-        // Get ExceptionMapper to rewrite exceptions in JSON.
-        bind(GuacamoleExceptionMapper.class);
-        
+ 
         // Load initial language resources from servlet context
         languageResourceService.addLanguageResources(getServletContext());
 

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/eb91f4d8/guacamole/src/main/java/org/apache/guacamole/rest/GuacamoleExceptionMapper.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/GuacamoleExceptionMapper.java
 
b/guacamole/src/main/java/org/apache/guacamole/rest/GuacamoleExceptionMapper.java
index 4af39b8..f27c59c 100644
--- 
a/guacamole/src/main/java/org/apache/guacamole/rest/GuacamoleExceptionMapper.java
+++ 
b/guacamole/src/main/java/org/apache/guacamole/rest/GuacamoleExceptionMapper.java
@@ -19,12 +19,23 @@
 
 package org.apache.guacamole.rest;
 
+import com.google.inject.Inject;
 import com.google.inject.Singleton;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
+import org.aopalliance.intercept.MethodInvocation;
 import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleUnauthorizedException;
+import org.apache.guacamole.rest.auth.AuthenticationService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -37,12 +48,59 @@ import org.slf4j.LoggerFactory;
 @Singleton
 public class GuacamoleExceptionMapper
         implements ExceptionMapper<GuacamoleException> {
-        
+    
+    /**
+     * The logger for this class.
+     */
     private final Logger logger = 
LoggerFactory.getLogger(GuacamoleExceptionMapper.class);
     
+    /**
+     * The request associated with this instance of this mapper.
+     */
+    @Context private HttpServletRequest request;
+    
+    /**
+     * The authentication service associated with the currently active session.
+     */
+    @Inject
+    private AuthenticationService authenticationService;
+    
+    /**
+     * Returns the authentication token that is in use in the current session,
+     * if present, or null if otherwise.
+     *
+     * @return
+     *     The authentication token for the current session, or null if no
+     *     token is present.
+     */
+    private String getAuthenticationToken() {
+
+        @SuppressWarnings("unchecked")
+        Map<String, String[]> parameters = request.getParameterMap();
+
+        for (String paramName : parameters.keySet()) {
+            if (paramName.equals("token")) {
+                String tokenParams[] = parameters.get(paramName);
+                if (tokenParams[0] != null && !tokenParams[0].isEmpty())
+                    return tokenParams[0];
+            }
+        }
+        
+        return null;
+
+    }
+    
     @Override
     public Response toResponse(GuacamoleException e) {
         logger.debug(">>>EXMAPPER<<< Mapping exception {}", e.getMessage());
+        
+        if (e instanceof GuacamoleUnauthorizedException) {
+            String token = getAuthenticationToken();
+            
+            if (authenticationService.destroyGuacamoleSession(token))
+                logger.debug("Implicitly invalidated session for token 
\"{}\"", token);
+        }
+        
         return Response
                 .status(e.getHttpStatusCode())
                 .entity(new APIError(e))

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/eb91f4d8/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java 
b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
deleted file mode 100644
index fb854b0..0000000
--- 
a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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.guacamole.rest;
-
-import com.google.inject.Inject;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
-import org.aopalliance.intercept.MethodInterceptor;
-import org.aopalliance.intercept.MethodInvocation;
-import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.GuacamoleUnauthorizedException;
-import org.apache.guacamole.rest.auth.AuthenticationService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A method interceptor which wraps custom exception handling around methods
- * which can throw GuacamoleExceptions and which are exposed through the REST
- * interface. The various types of GuacamoleExceptions are automatically
- * translated into appropriate HTTP responses, including JSON describing the
- * error that occurred.
- */
-public class RESTExceptionWrapper implements MethodInterceptor {
-
-    /**
-     * Logger for this class.
-     */
-    private final Logger logger = 
LoggerFactory.getLogger(RESTExceptionWrapper.class);
-
-    /**
-     * Service for authenticating users and managing their Guacamole sessions.
-     */
-    @Inject
-    private AuthenticationService authenticationService;
-
-    /**
-     * Determines whether the given set of annotations describes an HTTP
-     * request parameter of the given name. For a parameter to be associated
-     * with an HTTP request parameter, it must be annotated with either the
-     * <code>@QueryParam</code> or <code>@FormParam</code> annotations.
-     *
-     * @param annotations
-     *     The annotations associated with the Java parameter being checked.
-     *
-     * @param name
-     *     The name of the HTTP request parameter.
-     *
-     * @return
-     *     true if the given set of annotations describes an HTTP request
-     *     parameter having the given name, false otherwise.
-     */
-    private boolean isRequestParameter(Annotation[] annotations, String name) {
-
-        // Search annotations for associated HTTP parameters
-        for (Annotation annotation : annotations) {
-
-            // Check if parameter is associated with the HTTP query string
-            if (annotation instanceof QueryParam && name.equals(((QueryParam) 
annotation).value()))
-                return true;
-
-            // Failing that, check whether the parameter is associated with the
-            // HTTP request body
-            if (annotation instanceof FormParam && name.equals(((FormParam) 
annotation).value()))
-                return true;
-
-        }
-
-        // No parameter annotations are present
-        return false;
-
-    }
-
-    /**
-     * Returns the authentication token that was passed in the given method
-     * invocation. If the given method invocation is not associated with an
-     * HTTP request (it lacks the appropriate JAX-RS annotations) or there is
-     * no authentication token, null is returned.
-     *
-     * @param invocation
-     *     The method invocation whose corresponding authentication token
-     *     should be determined.
-     *
-     * @return
-     *     The authentication token passed in the given method invocation, or
-     *     null if there is no such token.
-     */
-    private String getAuthenticationToken(MethodInvocation invocation) {
-
-        Method method = invocation.getMethod();
-
-        // Get the types and annotations associated with each parameter
-        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-        Class<?>[] parameterTypes = method.getParameterTypes();
-
-        // The Java standards require these to be parallel arrays
-        assert(parameterAnnotations.length == parameterTypes.length);
-
-        // Iterate through all parameters, looking for the authentication token
-        for (int i = 0; i < parameterTypes.length; i++) {
-
-            // Only inspect String parameters
-            Class<?> parameterType = parameterTypes[i];
-            if (parameterType != String.class)
-                continue;
-
-            // Parameter must be declared as a REST service parameter
-            Annotation[] annotations = parameterAnnotations[i];
-            if (!isRequestParameter(annotations, "token"))
-                continue;
-
-            // The token parameter has been found - return its value
-            Object[] args = invocation.getArguments();
-            return (String) args[i];
-
-        }
-
-        // No token parameter is defined
-        return null;
-
-    }
-
-    @Override
-    public Object invoke(MethodInvocation invocation) throws 
WebApplicationException {
-
-        try {
-
-            // Invoke wrapped method
-            try {
-                return invocation.proceed();
-            }
-
-            // Ensure any associated session is invalidated if unauthorized
-            catch (GuacamoleUnauthorizedException e) {
-
-                // Pull authentication token from request
-                String token = getAuthenticationToken(invocation);
-
-                // If there is an associated auth token, invalidate it
-                if (authenticationService.destroyGuacamoleSession(token))
-                    logger.debug("Implicitly invalidated session for token 
\"{}\".", token);
-
-                // Continue with exception processing
-                throw e;
-
-            }
-
-        }
-
-        // Translate GuacamoleException subclasses to HTTP error codes
-        catch (GuacamoleException e) {
-            throw new APIException(
-                Response.Status.fromStatusCode(e.getHttpStatusCode()),
-                e
-            );
-        }
-
-        // Rethrow unchecked exceptions such that they are properly wrapped
-        catch (Throwable t) {
-
-            // Log all reasonable details of error
-            String message = t.getMessage();
-            if (message != null)
-                logger.error("Unexpected internal error: {}", message);
-            else
-                logger.error("An internal error occurred, but did not contain "
-                           + "an error message. Enable debug-level logging for 
"
-                           + "details.");
-
-            // Ensure internal errors are fully logged at the debug level
-            logger.debug("Unexpected error in REST endpoint.", t);
-
-            throw new APIException(Response.Status.INTERNAL_SERVER_ERROR,
-                    new GuacamoleException("Unexpected internal error.", t));
-
-        }
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/eb91f4d8/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java 
b/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
index cfa8b06..8075b1e 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
@@ -83,11 +83,6 @@ public class RESTServiceModule extends ServletModule {
         bind(AuthenticationService.class);
         
bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class);
         bind(DecorationService.class);
-
-        // Automatically translate GuacamoleExceptions for REST methods
-        MethodInterceptor interceptor = new RESTExceptionWrapper();
-        requestInjection(interceptor);
-        bindInterceptor(Matchers.any(), new RESTMethodMatcher(), interceptor);
         
         // Get the ExceptionMapper that will rewrite exceptions into JSON.
         bind(GuacamoleExceptionMapper.class);

Reply via email to