GUACAMOLE-566: Handle all exceptions, not just GuacamoleException instances.

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

Branch: refs/heads/master
Commit: a3faf6a2eeb0955fede6db74156d51df22da4a39
Parents: 75c8fc8
Author: Nick Couchman <[email protected]>
Authored: Tue May 29 22:13:04 2018 -0400
Committer: Nick Couchman <[email protected]>
Committed: Tue May 29 22:13:04 2018 -0400

----------------------------------------------------------------------
 .../rest/GuacamoleExceptionMapper.java          | 111 -----------------
 .../guacamole/rest/RESTExceptionMapper.java     | 118 +++++++++++++++++++
 .../guacamole/rest/RESTServiceModule.java       |   4 +-
 3 files changed, 120 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3faf6a2/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
deleted file mode 100644
index dd8c76e..0000000
--- 
a/guacamole/src/main/java/org/apache/guacamole/rest/GuacamoleExceptionMapper.java
+++ /dev/null
@@ -1,111 +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 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;
-
-/**
- * A class that maps GuacamoleExceptions in a way that returns a
- * custom response to the user via JSON rather than allowing the default
- * web application error handling to take place.
- */
-@Provider
-@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) {
-        
-        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))
-                .type(MediaType.APPLICATION_JSON)
-                .build();
-      
-    }
-    
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3faf6a2/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java 
b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java
new file mode 100644
index 0000000..ae35274
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.google.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
+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.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleUnauthorizedException;
+import org.apache.guacamole.rest.auth.AuthenticationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A class that maps GuacamoleExceptions in a way that returns a
+ * custom response to the user via JSON rather than allowing the default
+ * web application error handling to take place.
+ */
+@Provider
+@Singleton
+public class RESTExceptionMapper implements ExceptionMapper<Throwable> {
+    
+    /**
+     * The logger for this class.
+     */
+    private final Logger logger = 
LoggerFactory.getLogger(RESTExceptionMapper.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() {
+
+        String token = request.getParameter("token");
+        if (token != null && !token.isEmpty())
+            return token;
+        
+        return null;
+
+    }
+    
+    @Override
+    public Response toResponse(Throwable t) {
+        
+        // Ensure any associated session is invalidated if unauthorized 
+        if (t instanceof GuacamoleUnauthorizedException) {
+            String token = getAuthenticationToken();
+            
+            if (authenticationService.destroyGuacamoleSession(token))
+                logger.debug("Implicitly invalidated session for token 
\"{}\"", token);
+        }
+        
+        // Translate GuacamoleException subclasses to HTTP error codes 
+        if (t instanceof GuacamoleException)
+            return Response
+                    .status(((GuacamoleException) t).getHttpStatusCode())
+                    .entity(new APIError((GuacamoleException)t))
+                    .type(MediaType.APPLICATION_JSON)
+                    .build();
+        
+        // Rethrow unchecked exceptions such that they are properly wrapped    
        
+        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.");
+            
+        logger.debug("Unexpected error in REST endpoint.", t);
+            
+        return Response
+                .status(Response.Status.INTERNAL_SERVER_ERROR)
+                .entity("Unexpected Internal Error.")
+                .type(MediaType.APPLICATION_JSON)
+                .build();
+        
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3faf6a2/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 8075b1e..b23eec6 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
@@ -84,8 +84,8 @@ public class RESTServiceModule extends ServletModule {
         
bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class);
         bind(DecorationService.class);
         
-        // Get the ExceptionMapper that will rewrite exceptions into JSON.
-        bind(GuacamoleExceptionMapper.class);
+        // Automatically translate GuacamoleExceptions for REST methods
+        bind(RESTExceptionMapper.class);
 
         // Set up the API endpoints
         bind(ExtensionRESTService.class);

Reply via email to