GUACAMOLE-504: Merge changes adding support for overriding HTTP/WebSocket status codes via custom exceptions.
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/GuacamoleException.java b/guacamole-common/src/main/java/org/apache/guacamole/GuacamoleException.java
index 1b2226d..d984226 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/GuacamoleException.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/GuacamoleException.java
@@ -68,5 +68,29 @@
public GuacamoleStatus getStatus() {
return GuacamoleStatus.SERVER_ERROR;
}
+
+ /**
+ * Returns the most applicable HTTP status code that can be associated
+ * with this exception.
+ *
+ * @return
+ * An integer representing the most applicable HTTP status code
+ * associated with this exception.
+ */
+ public int getHttpStatusCode() {
+ return getStatus().getHttpStatusCode();
+ }
+
+ /**
+ * Returns the most applicable WebSocket status code that can be
+ * associated with this exception.
+ *
+ * @return
+ * An integer representing the most applicable WebSocket status
+ * code associated with this exception.
+ */
+ public int getWebSocketCode() {
+ return getStatus().getWebSocketCode();
+ }
}
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/servlet/GuacamoleHTTPTunnelServlet.java b/guacamole-common/src/main/java/org/apache/guacamole/servlet/GuacamoleHTTPTunnelServlet.java
index fdbfb8e..be2da13 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/servlet/GuacamoleHTTPTunnelServlet.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/servlet/GuacamoleHTTPTunnelServlet.java
@@ -149,26 +149,29 @@
* @param response
* The HTTP response to use to send the error.
*
- * @param guacStatus
- * The status to send
+ * @param guacamoleStatusCode
+ * The GuacamoleStatus code to send.
+ *
+ * @param guacamoleHttpCode
+ * The numeric HTTP code to send.
*
* @param message
- * A human-readable message that can be presented to the user.
+ * The human-readable error message to send.
*
* @throws ServletException
* If an error prevents sending of the error code.
*/
- protected void sendError(HttpServletResponse response,
- GuacamoleStatus guacStatus, String message)
+ protected void sendError(HttpServletResponse response, int guacamoleStatusCode,
+ int guacamoleHttpCode, String message)
throws ServletException {
try {
// If response not committed, send error code and message
if (!response.isCommitted()) {
- response.addHeader("Guacamole-Status-Code", Integer.toString(guacStatus.getGuacamoleStatusCode()));
+ response.addHeader("Guacamole-Status-Code", Integer.toString(guacamoleStatusCode));
response.addHeader("Guacamole-Error-Message", message);
- response.sendError(guacStatus.getHttpStatusCode());
+ response.sendError(guacamoleHttpCode);
}
}
@@ -237,14 +240,14 @@
// If read operation, call doRead() with tunnel UUID, ignoring any
// characters following the tunnel UUID.
- else if(query.startsWith(READ_PREFIX))
+ else if (query.startsWith(READ_PREFIX))
doRead(request, response, query.substring(
READ_PREFIX_LENGTH,
READ_PREFIX_LENGTH + UUID_LENGTH));
// If write operation, call doWrite() with tunnel UUID, ignoring any
// characters following the tunnel UUID.
- else if(query.startsWith(WRITE_PREFIX))
+ else if (query.startsWith(WRITE_PREFIX))
doWrite(request, response, query.substring(
WRITE_PREFIX_LENGTH,
WRITE_PREFIX_LENGTH + UUID_LENGTH));
@@ -258,12 +261,14 @@
// HTTP response, logging each error appropriately.
catch (GuacamoleClientException e) {
logger.warn("HTTP tunnel request rejected: {}", e.getMessage());
- sendError(response, e.getStatus(), e.getMessage());
+ sendError(response, e.getStatus().getGuacamoleStatusCode(),
+ e.getStatus().getHttpStatusCode(), e.getMessage());
}
catch (GuacamoleException e) {
logger.error("HTTP tunnel request failed: {}", e.getMessage());
logger.debug("Internal error in HTTP tunnel.", e);
- sendError(response, e.getStatus(), "Internal server error.");
+ sendError(response, e.getStatus().getGuacamoleStatusCode(),
+ e.getStatus().getHttpStatusCode(), "Internal server error.");
}
}
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/websocket/GuacamoleWebSocketTunnelEndpoint.java b/guacamole-common/src/main/java/org/apache/guacamole/websocket/GuacamoleWebSocketTunnelEndpoint.java
index 0cae732..0e02622 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/websocket/GuacamoleWebSocketTunnelEndpoint.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/websocket/GuacamoleWebSocketTunnelEndpoint.java
@@ -66,17 +66,24 @@
private GuacamoleTunnel tunnel;
/**
- * Sends the given status on the given WebSocket connection and closes the
- * connection.
+ * Sends the numeric Guacaomle Status Code and Web Socket
+ * code and closes the connection.
*
- * @param session The outbound WebSocket connection to close.
- * @param guac_status The status to send.
+ * @param session
+ * The outbound WebSocket connection to close.
+ *
+ * @param guacamoleStatusCode
+ * The numeric Guacamole status to send.
+ *
+ * @param webSocketCode
+ * The numeric WebSocket status to send.
*/
- private void closeConnection(Session session, GuacamoleStatus guac_status) {
+ private void closeConnection(Session session, int guacamoleStatusCode,
+ int webSocketCode) {
try {
- CloseCode code = CloseReason.CloseCodes.getCloseCode(guac_status.getWebSocketCode());
- String message = Integer.toString(guac_status.getGuacamoleStatusCode());
+ CloseCode code = CloseReason.CloseCodes.getCloseCode(webSocketCode);
+ String message = Integer.toString(guacamoleStatusCode);
session.close(new CloseReason(code, message));
}
catch (IOException e) {
@@ -86,6 +93,21 @@
}
/**
+ * Sends the given Guacaomle Status and closes the given
+ * connection.
+ *
+ * @param session
+ * The outbound WebSocket connection to close.
+ *
+ * @param guacStatus
+ * The status to use for the connection.
+ */
+ private void closeConnection(Session session, GuacamoleStatus guacStatus) {
+ closeConnection(session, guacStatus.getGuacamoleStatusCode(),
+ guacStatus.getWebSocketCode());
+ }
+
+ /**
* Returns a new tunnel for the given session. How this tunnel is created
* or retrieved is implementation-dependent.
*
@@ -117,7 +139,8 @@
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
- closeConnection(session, e.getStatus());
+ closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
return;
}
@@ -181,7 +204,8 @@
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
- closeConnection(session, e.getStatus());
+ closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
@@ -190,7 +214,8 @@
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
- closeConnection(session, e.getStatus());
+ closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
}
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
index 28736e8..a0c756e 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionWrapper.java
@@ -173,7 +173,7 @@
// Translate GuacamoleException subclasses to HTTP error codes
catch (GuacamoleException e) {
throw new APIException(
- Response.Status.fromStatusCode(e.getStatus().getHttpStatusCode()),
+ Response.Status.fromStatusCode(e.getHttpStatusCode()),
e
);
}
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java
index 9769646..e5c5db9 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/GuacamoleWebSocketTunnelServlet.java
@@ -53,17 +53,42 @@
private static final int BUFFER_SIZE = 8192;
/**
- * Sends the given status on the given WebSocket connection and closes the
+ * Sends the given numeric Guacamole and WebSocket status
+ * on the given WebSocket connection and closes the
* connection.
*
- * @param connection The WebSocket connection to close.
- * @param guac_status The status to send.
+ * @param connection
+ * The WebSocket connection to close.
+ *
+ * @param guacamoleStatusCode
+ * The numeric Guacamole Status code to send.
+ *
+ * @param webSocketCode
+ * The numeric WebSocket status code to send.
*/
- public static void closeConnection(Connection connection,
- GuacamoleStatus guac_status) {
+ private static void closeConnection(Connection connection,
+ int guacamoleStatusCode, int webSocketCode) {
- connection.close(guac_status.getWebSocketCode(),
- Integer.toString(guac_status.getGuacamoleStatusCode()));
+ connection.close(webSocketCode,
+ Integer.toString(guacamoleStatusCode));
+
+ }
+
+ /**
+ * Sends the given status on the given WebSocket connection
+ * and closes the connection.
+ *
+ * @param connection
+ * The WebSocket connection to close.
+ *
+ * @param guacStatus
+ * The status to send.
+ */
+ private static void closeConnection(Connection connection,
+ GuacamoleStatus guacStatus) {
+
+ closeConnection(connection, guacStatus.getGuacamoleStatusCode(),
+ guacStatus.getWebSocketCode());
}
@@ -114,7 +139,8 @@
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
- closeConnection(connection, e.getStatus());
+ closeConnection(connection, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
return;
}
@@ -168,7 +194,8 @@
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
- closeConnection(connection, e.getStatus());
+ closeConnection(connection, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
@@ -177,7 +204,8 @@
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
- closeConnection(connection, e.getStatus());
+ closeConnection(connection, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
}
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/GuacamoleWebSocketTunnelListener.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/GuacamoleWebSocketTunnelListener.java
index 5375d75..0594d06 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/GuacamoleWebSocketTunnelListener.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/GuacamoleWebSocketTunnelListener.java
@@ -57,18 +57,25 @@
private GuacamoleTunnel tunnel;
/**
- * Sends the given status on the given WebSocket connection and closes the
+ * Sends the given numeric Guacamole and WebSocket status
+ * codes on the given WebSocket connection and closes the
* connection.
*
- * @param session The outbound WebSocket connection to close.
- * @param guac_status The status to send.
+ * @param session
+ * The outbound WebSocket connection to close.
+ *
+ * @param guacamoleStatusCode
+ * The numeric Guacamole status code to send.
+ *
+ * @param webSocketCode
+ * The numeric WebSocket status code to send.
*/
- private void closeConnection(Session session, GuacamoleStatus guac_status) {
+ private void closeConnection(Session session, int guacamoleStatusCode,
+ int webSocketCode) {
try {
- int code = guac_status.getWebSocketCode();
- String message = Integer.toString(guac_status.getGuacamoleStatusCode());
- session.close(new CloseStatus(code, message));
+ String message = Integer.toString(guacamoleStatusCode);
+ session.close(new CloseStatus(webSocketCode, message));
}
catch (IOException e) {
logger.debug("Unable to close WebSocket connection.", e);
@@ -77,6 +84,24 @@
}
/**
+ * Sends the given status on the given WebSocket connection
+ * and closes the connection.
+ *
+ * @param session
+ * The outbound WebSocket connection to close.
+ *
+ * @param guacStatus
+ * The status to send.
+ */
+ private void closeConnection(Session session,
+ GuacamoleStatus guacStatus) {
+
+ closeConnection(session, guacStatus.getGuacamoleStatusCode(),
+ guacStatus.getWebSocketCode());
+
+ }
+
+ /**
* Returns a new tunnel for the given session. How this tunnel is created
* or retrieved is implementation-dependent.
*
@@ -105,7 +130,7 @@
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
- closeConnection(session, e.getStatus());
+ closeConnection(session, e.getStatus().getGuacamoleStatusCode(), e.getWebSocketCode());
return;
}
@@ -159,7 +184,8 @@
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
- closeConnection(session, e.getStatus());
+ closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
@@ -168,7 +194,8 @@
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
- closeConnection(session, e.getStatus());
+ closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
}
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java
index 986650e..a2e8b39 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/GuacamoleWebSocketTunnelServlet.java
@@ -58,17 +58,25 @@
private final Logger logger = LoggerFactory.getLogger(GuacamoleWebSocketTunnelServlet.class);
/**
- * Sends the given status on the given WebSocket connection and closes the
+ * Sends the given Guacamole and WebSocket numeric status
+ * on the given WebSocket connection and closes the
* connection.
*
- * @param outbound The outbound WebSocket connection to close.
- * @param guac_status The status to send.
+ * @param outbound
+ * The outbound WebSocket connection to close.
+ *
+ * @param guacamoleStatusCode
+ * The status to send.
+ *
+ * @param webSocketCode
+ * The numeric WebSocket status code to send.
*/
- public void closeConnection(WsOutbound outbound, GuacamoleStatus guac_status) {
+ private void closeConnection(WsOutbound outbound, int guacamoleStatusCode,
+ int webSocketCode) {
try {
- byte[] message = Integer.toString(guac_status.getGuacamoleStatusCode()).getBytes("UTF-8");
- outbound.close(guac_status.getWebSocketCode(), ByteBuffer.wrap(message));
+ byte[] message = Integer.toString(guacamoleStatusCode).getBytes("UTF-8");
+ outbound.close(webSocketCode, ByteBuffer.wrap(message));
}
catch (IOException e) {
logger.debug("Unable to close WebSocket tunnel.", e);
@@ -76,6 +84,24 @@
}
+ /**
+ * Sends the given status on the given WebSocket connection
+ * and closes the connection.
+ *
+ * @param outbound
+ * The outbound WebSocket connection to close.
+ *
+ * @param guacStatus
+ * The status to send.
+ */
+ private void closeConnection(WsOutbound outbound,
+ GuacamoleStatus guacStatus) {
+
+ closeConnection(outbound, guacStatus.getGuacamoleStatusCode(),
+ guacStatus.getWebSocketCode());
+
+ }
+
@Override
protected String selectSubProtocol(List<String> subProtocols) {
@@ -142,7 +168,8 @@
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
- closeConnection(outbound, e.getStatus());
+ closeConnection(outbound, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
return;
}
@@ -196,7 +223,8 @@
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
- closeConnection(outbound, e.getStatus());
+ closeConnection(outbound, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
@@ -205,7 +233,8 @@
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
- closeConnection(outbound, e.getStatus());
+ closeConnection(outbound, e.getStatus().getGuacamoleStatusCode(),
+ e.getWebSocketCode());
}
}