You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by jm...@apache.org on 2016/03/29 06:20:24 UTC
[15/51] [abbrv] incubator-guacamole-client git commit: GUACAMOLE-1:
Remove useless .net.basic subpackage, now that everything is being renamed.
GUACAMOLE-1: Remove useless .net.basic subpackage, now that everything is being renamed.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/648a6c96
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/648a6c96
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/648a6c96
Branch: refs/heads/master
Commit: 648a6c96f02973e8792af10328f771aeabd1a024
Parents: 4198c33
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Mar 22 14:35:36 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Mon Mar 28 20:49:56 2016 -0700
----------------------------------------------------------------------
.../guacamole/BasicGuacamoleTunnelServlet.java | 67 ++
.../guacamole/BasicServletContextListener.java | 103 +++
.../org/apache/guacamole/ClipboardState.java | 154 +++++
.../org/apache/guacamole/EnvironmentModule.java | 60 ++
.../apache/guacamole/GuacamoleClassLoader.java | 185 ++++++
.../org/apache/guacamole/GuacamoleSession.java | 222 +++++++
.../org/apache/guacamole/HTTPTunnelRequest.java | 90 +++
.../java/org/apache/guacamole/TunnelLoader.java | 44 ++
.../java/org/apache/guacamole/TunnelModule.java | 113 ++++
.../org/apache/guacamole/TunnelRequest.java | 372 +++++++++++
.../apache/guacamole/TunnelRequestService.java | 359 ++++++++++
.../apache/guacamole/auth/Authorization.java | 255 ++++++++
.../org/apache/guacamole/auth/UserMapping.java | 62 ++
.../auth/basic/AuthorizeTagHandler.java | 151 +++++
.../basic/BasicFileAuthenticationProvider.java | 218 +++++++
.../auth/basic/ConnectionTagHandler.java | 110 ++++
.../guacamole/auth/basic/ParamTagHandler.java | 74 +++
.../auth/basic/ProtocolTagHandler.java | 70 ++
.../auth/basic/UserMappingTagHandler.java | 78 +++
.../guacamole/auth/basic/package-info.java | 27 +
.../org/apache/guacamole/auth/package-info.java | 28 +
.../extension/AuthenticationProviderFacade.java | 203 ++++++
.../extension/DirectoryClassLoader.java | 154 +++++
.../apache/guacamole/extension/Extension.java | 515 +++++++++++++++
.../guacamole/extension/ExtensionManifest.java | 407 ++++++++++++
.../guacamole/extension/ExtensionModule.java | 450 +++++++++++++
.../extension/LanguageResourceService.java | 442 +++++++++++++
.../extension/PatchResourceService.java | 84 +++
.../guacamole/extension/package-info.java | 27 +
.../org/apache/guacamole/log/LogModule.java | 99 +++
.../basic/BasicFileAuthenticationProvider.java | 218 -------
.../net/basic/BasicGuacamoleTunnelServlet.java | 67 --
.../net/basic/BasicServletContextListener.java | 103 ---
.../guacamole/net/basic/ClipboardState.java | 154 -----
.../guacamole/net/basic/EnvironmentModule.java | 60 --
.../net/basic/GuacamoleClassLoader.java | 185 ------
.../guacamole/net/basic/GuacamoleSession.java | 222 -------
.../guacamole/net/basic/HTTPTunnelRequest.java | 90 ---
.../guacamole/net/basic/TunnelLoader.java | 44 --
.../guacamole/net/basic/TunnelModule.java | 113 ----
.../guacamole/net/basic/TunnelRequest.java | 372 -----------
.../net/basic/TunnelRequestService.java | 359 ----------
.../guacamole/net/basic/auth/Authorization.java | 255 --------
.../guacamole/net/basic/auth/UserMapping.java | 62 --
.../guacamole/net/basic/auth/package-info.java | 28 -
.../extension/AuthenticationProviderFacade.java | 203 ------
.../basic/extension/DirectoryClassLoader.java | 154 -----
.../net/basic/extension/Extension.java | 515 ---------------
.../net/basic/extension/ExtensionManifest.java | 407 ------------
.../net/basic/extension/ExtensionModule.java | 450 -------------
.../extension/LanguageResourceService.java | 442 -------------
.../basic/extension/PatchResourceService.java | 84 ---
.../net/basic/extension/package-info.java | 27 -
.../guacamole/net/basic/log/LogModule.java | 99 ---
.../guacamole/net/basic/package-info.java | 28 -
.../AuthenticationProviderProperty.java | 68 --
.../properties/BasicGuacamoleProperties.java | 90 ---
.../net/basic/properties/StringSetProperty.java | 66 --
.../net/basic/properties/package-info.java | 28 -
.../net/basic/resource/AbstractResource.java | 82 ---
.../net/basic/resource/ByteArrayResource.java | 62 --
.../net/basic/resource/ClassPathResource.java | 85 ---
.../guacamole/net/basic/resource/Resource.java | 67 --
.../net/basic/resource/ResourceServlet.java | 126 ----
.../net/basic/resource/SequenceResource.java | 153 -----
.../basic/resource/WebApplicationResource.java | 116 ----
.../net/basic/resource/package-info.java | 28 -
.../guacamole/net/basic/rest/APIError.java | 183 ------
.../guacamole/net/basic/rest/APIException.java | 85 ---
.../guacamole/net/basic/rest/APIPatch.java | 104 ---
.../guacamole/net/basic/rest/APIRequest.java | 107 ---
.../net/basic/rest/ObjectRetrievalService.java | 280 --------
.../apache/guacamole/net/basic/rest/PATCH.java | 40 --
.../net/basic/rest/RESTExceptionWrapper.java | 274 --------
.../net/basic/rest/RESTMethodMatcher.java | 109 ----
.../net/basic/rest/RESTServiceModule.java | 107 ---
.../activeconnection/APIActiveConnection.java | 130 ----
.../ActiveConnectionRESTService.java | 196 ------
.../rest/auth/APIAuthenticationResponse.java | 105 ---
.../rest/auth/APIAuthenticationResult.java | 133 ----
.../net/basic/rest/auth/AuthTokenGenerator.java | 39 --
.../basic/rest/auth/AuthenticationService.java | 475 --------------
.../basic/rest/auth/BasicTokenSessionMap.java | 189 ------
.../auth/SecureRandomAuthTokenGenerator.java | 48 --
.../net/basic/rest/auth/TokenRESTService.java | 230 -------
.../net/basic/rest/auth/TokenSessionMap.java | 69 --
.../net/basic/rest/auth/package-info.java | 27 -
.../basic/rest/connection/APIConnection.java | 233 -------
.../rest/connection/APIConnectionWrapper.java | 138 ----
.../rest/connection/ConnectionRESTService.java | 349 ----------
.../net/basic/rest/connection/package-info.java | 27 -
.../connectiongroup/APIConnectionGroup.java | 272 --------
.../APIConnectionGroupWrapper.java | 124 ----
.../ConnectionGroupRESTService.java | 287 --------
.../connectiongroup/ConnectionGroupTree.java | 259 --------
.../rest/connectiongroup/package-info.java | 28 -
.../basic/rest/history/APIConnectionRecord.java | 163 -----
.../APIConnectionRecordSortPredicate.java | 148 -----
.../basic/rest/history/HistoryRESTService.java | 147 -----
.../net/basic/rest/history/package-info.java | 28 -
.../rest/language/LanguageRESTService.java | 63 --
.../net/basic/rest/language/package-info.java | 27 -
.../guacamole/net/basic/rest/package-info.java | 27 -
.../net/basic/rest/patch/PatchRESTService.java | 133 ----
.../net/basic/rest/patch/package-info.java | 27 -
.../basic/rest/permission/APIPermissionSet.java | 300 ---------
.../net/basic/rest/permission/package-info.java | 27 -
.../basic/rest/schema/SchemaRESTService.java | 199 ------
.../net/basic/rest/schema/package-info.java | 27 -
.../guacamole/net/basic/rest/user/APIUser.java | 130 ----
.../basic/rest/user/APIUserPasswordUpdate.java | 82 ---
.../net/basic/rest/user/APIUserWrapper.java | 115 ----
.../net/basic/rest/user/PermissionSetPatch.java | 98 ---
.../net/basic/rest/user/UserRESTService.java | 647 -------------------
.../net/basic/rest/user/package-info.java | 27 -
.../BasicGuacamoleWebSocketTunnelEndpoint.java | 120 ----
.../basic/websocket/WebSocketTunnelModule.java | 104 ---
.../basic/websocket/WebSocketTunnelRequest.java | 70 --
.../BasicGuacamoleWebSocketTunnelServlet.java | 52 --
.../jetty8/GuacamoleWebSocketTunnelServlet.java | 232 -------
.../websocket/jetty8/WebSocketTunnelModule.java | 73 ---
.../basic/websocket/jetty8/package-info.java | 27 -
.../jetty9/BasicGuacamoleWebSocketCreator.java | 72 ---
.../BasicGuacamoleWebSocketTunnelListener.java | 59 --
.../BasicGuacamoleWebSocketTunnelServlet.java | 54 --
.../GuacamoleWebSocketTunnelListener.java | 243 -------
.../websocket/jetty9/WebSocketTunnelModule.java | 73 ---
.../jetty9/WebSocketTunnelRequest.java | 76 ---
.../basic/websocket/jetty9/package-info.java | 28 -
.../net/basic/websocket/package-info.java | 28 -
.../BasicGuacamoleWebSocketTunnelServlet.java | 52 --
.../tomcat/GuacamoleWebSocketTunnelServlet.java | 265 --------
.../websocket/tomcat/WebSocketTunnelModule.java | 73 ---
.../basic/websocket/tomcat/package-info.java | 29 -
.../xml/usermapping/AuthorizeTagHandler.java | 151 -----
.../xml/usermapping/ConnectionTagHandler.java | 110 ----
.../basic/xml/usermapping/ParamTagHandler.java | 74 ---
.../xml/usermapping/ProtocolTagHandler.java | 70 --
.../xml/usermapping/UserMappingTagHandler.java | 78 ---
.../net/basic/xml/usermapping/package-info.java | 27 -
.../java/org/apache/guacamole/package-info.java | 28 +
.../AuthenticationProviderProperty.java | 68 ++
.../properties/BasicGuacamoleProperties.java | 90 +++
.../guacamole/properties/StringSetProperty.java | 66 ++
.../guacamole/properties/package-info.java | 28 +
.../guacamole/resource/AbstractResource.java | 82 +++
.../guacamole/resource/ByteArrayResource.java | 62 ++
.../guacamole/resource/ClassPathResource.java | 85 +++
.../org/apache/guacamole/resource/Resource.java | 67 ++
.../guacamole/resource/ResourceServlet.java | 126 ++++
.../guacamole/resource/SequenceResource.java | 153 +++++
.../resource/WebApplicationResource.java | 116 ++++
.../apache/guacamole/resource/package-info.java | 28 +
.../org/apache/guacamole/rest/APIError.java | 183 ++++++
.../org/apache/guacamole/rest/APIException.java | 85 +++
.../org/apache/guacamole/rest/APIPatch.java | 104 +++
.../org/apache/guacamole/rest/APIRequest.java | 107 +++
.../guacamole/rest/ObjectRetrievalService.java | 280 ++++++++
.../java/org/apache/guacamole/rest/PATCH.java | 40 ++
.../guacamole/rest/RESTExceptionWrapper.java | 274 ++++++++
.../guacamole/rest/RESTMethodMatcher.java | 109 ++++
.../guacamole/rest/RESTServiceModule.java | 107 +++
.../activeconnection/APIActiveConnection.java | 130 ++++
.../ActiveConnectionRESTService.java | 196 ++++++
.../rest/auth/APIAuthenticationResponse.java | 105 +++
.../rest/auth/APIAuthenticationResult.java | 133 ++++
.../guacamole/rest/auth/AuthTokenGenerator.java | 39 ++
.../rest/auth/AuthenticationService.java | 475 ++++++++++++++
.../rest/auth/BasicTokenSessionMap.java | 189 ++++++
.../auth/SecureRandomAuthTokenGenerator.java | 48 ++
.../guacamole/rest/auth/TokenRESTService.java | 230 +++++++
.../guacamole/rest/auth/TokenSessionMap.java | 69 ++
.../guacamole/rest/auth/package-info.java | 27 +
.../rest/connection/APIConnection.java | 233 +++++++
.../rest/connection/APIConnectionWrapper.java | 138 ++++
.../rest/connection/ConnectionRESTService.java | 349 ++++++++++
.../guacamole/rest/connection/package-info.java | 27 +
.../connectiongroup/APIConnectionGroup.java | 272 ++++++++
.../APIConnectionGroupWrapper.java | 124 ++++
.../ConnectionGroupRESTService.java | 287 ++++++++
.../connectiongroup/ConnectionGroupTree.java | 259 ++++++++
.../rest/connectiongroup/package-info.java | 28 +
.../rest/history/APIConnectionRecord.java | 163 +++++
.../APIConnectionRecordSortPredicate.java | 148 +++++
.../rest/history/HistoryRESTService.java | 147 +++++
.../guacamole/rest/history/package-info.java | 28 +
.../rest/language/LanguageRESTService.java | 63 ++
.../guacamole/rest/language/package-info.java | 27 +
.../org/apache/guacamole/rest/package-info.java | 27 +
.../guacamole/rest/patch/PatchRESTService.java | 133 ++++
.../guacamole/rest/patch/package-info.java | 27 +
.../rest/permission/APIPermissionSet.java | 300 +++++++++
.../guacamole/rest/permission/package-info.java | 27 +
.../rest/schema/SchemaRESTService.java | 199 ++++++
.../guacamole/rest/schema/package-info.java | 27 +
.../org/apache/guacamole/rest/user/APIUser.java | 130 ++++
.../rest/user/APIUserPasswordUpdate.java | 82 +++
.../guacamole/rest/user/APIUserWrapper.java | 115 ++++
.../guacamole/rest/user/PermissionSetPatch.java | 98 +++
.../guacamole/rest/user/UserRESTService.java | 647 +++++++++++++++++++
.../guacamole/rest/user/package-info.java | 27 +
.../BasicGuacamoleWebSocketTunnelEndpoint.java | 120 ++++
.../websocket/WebSocketTunnelModule.java | 104 +++
.../websocket/WebSocketTunnelRequest.java | 70 ++
.../BasicGuacamoleWebSocketTunnelServlet.java | 52 ++
.../jetty8/GuacamoleWebSocketTunnelServlet.java | 232 +++++++
.../websocket/jetty8/WebSocketTunnelModule.java | 73 +++
.../websocket/jetty8/package-info.java | 27 +
.../jetty9/BasicGuacamoleWebSocketCreator.java | 72 +++
.../BasicGuacamoleWebSocketTunnelListener.java | 59 ++
.../BasicGuacamoleWebSocketTunnelServlet.java | 54 ++
.../GuacamoleWebSocketTunnelListener.java | 243 +++++++
.../websocket/jetty9/WebSocketTunnelModule.java | 73 +++
.../jetty9/WebSocketTunnelRequest.java | 76 +++
.../websocket/jetty9/package-info.java | 28 +
.../guacamole/websocket/package-info.java | 28 +
.../BasicGuacamoleWebSocketTunnelServlet.java | 52 ++
.../tomcat/GuacamoleWebSocketTunnelServlet.java | 265 ++++++++
.../websocket/tomcat/WebSocketTunnelModule.java | 73 +++
.../websocket/tomcat/package-info.java | 29 +
guacamole/src/main/webapp/WEB-INF/web.xml | 2 +-
221 files changed, 15015 insertions(+), 15015 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/BasicGuacamoleTunnelServlet.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/BasicGuacamoleTunnelServlet.java b/guacamole/src/main/java/org/apache/guacamole/BasicGuacamoleTunnelServlet.java
new file mode 100644
index 0000000..7ebbd7f
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/BasicGuacamoleTunnelServlet.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.net.GuacamoleTunnel;
+import org.apache.guacamole.servlet.GuacamoleHTTPTunnelServlet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Connects users to a tunnel associated with the authorized connection
+ * having the given ID.
+ *
+ * @author Michael Jumper
+ */
+@Singleton
+public class BasicGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet {
+
+ /**
+ * Service for handling tunnel requests.
+ */
+ @Inject
+ private TunnelRequestService tunnelRequestService;
+
+ /**
+ * Logger for this class.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(BasicGuacamoleTunnelServlet.class);
+
+ @Override
+ protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {
+
+ // Attempt to create HTTP tunnel
+ GuacamoleTunnel tunnel = tunnelRequestService.createTunnel(new HTTPTunnelRequest(request));
+
+ // If successful, warn of lack of WebSocket
+ logger.info("Using HTTP tunnel (not WebSocket). Performance may be sub-optimal.");
+
+ return tunnel;
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/BasicServletContextListener.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/BasicServletContextListener.java b/guacamole/src/main/java/org/apache/guacamole/BasicServletContextListener.java
new file mode 100644
index 0000000..96fab85
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/BasicServletContextListener.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.google.inject.servlet.GuiceServletContextListener;
+import javax.servlet.ServletContextEvent;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.environment.Environment;
+import org.apache.guacamole.environment.LocalEnvironment;
+import org.apache.guacamole.extension.ExtensionModule;
+import org.apache.guacamole.log.LogModule;
+import org.apache.guacamole.rest.RESTServiceModule;
+import org.apache.guacamole.rest.auth.BasicTokenSessionMap;
+import org.apache.guacamole.rest.auth.TokenSessionMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A ServletContextListener to listen for initialization of the servlet context
+ * in order to set up dependency injection.
+ *
+ * @author James Muehlner
+ */
+public class BasicServletContextListener extends GuiceServletContextListener {
+
+ /**
+ * Logger for this class.
+ */
+ private final Logger logger = LoggerFactory.getLogger(BasicServletContextListener.class);
+
+ /**
+ * The Guacamole server environment.
+ */
+ private Environment environment;
+
+ /**
+ * Singleton instance of a TokenSessionMap.
+ */
+ private TokenSessionMap sessionMap;
+
+ @Override
+ public void contextInitialized(ServletContextEvent servletContextEvent) {
+
+ try {
+ environment = new LocalEnvironment();
+ sessionMap = new BasicTokenSessionMap(environment);
+ }
+ catch (GuacamoleException e) {
+ logger.error("Unable to read guacamole.properties: {}", e.getMessage());
+ logger.debug("Error reading guacamole.properties.", e);
+ throw new RuntimeException(e);
+ }
+
+ super.contextInitialized(servletContextEvent);
+
+ }
+
+ @Override
+ protected Injector getInjector() {
+ return Guice.createInjector(Stage.PRODUCTION,
+ new EnvironmentModule(environment),
+ new LogModule(environment),
+ new ExtensionModule(environment),
+ new RESTServiceModule(sessionMap),
+ new TunnelModule()
+ );
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent servletContextEvent) {
+
+ super.contextDestroyed(servletContextEvent);
+
+ // Shutdown TokenSessionMap
+ if (sessionMap != null)
+ sessionMap.shutdown();
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/ClipboardState.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/ClipboardState.java b/guacamole/src/main/java/org/apache/guacamole/ClipboardState.java
new file mode 100644
index 0000000..bde6822
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/ClipboardState.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+/**
+ * Provides central storage for a cross-connection clipboard state. This
+ * clipboard state is shared only for a single HTTP session. Multiple HTTP
+ * sessions will all have their own state.
+ *
+ * @author Michael Jumper
+ */
+public class ClipboardState {
+
+ /**
+ * The maximum number of bytes to track.
+ */
+ private static final int MAXIMUM_LENGTH = 262144;
+
+ /**
+ * The mimetype of the current contents.
+ */
+ private String mimetype = "text/plain";
+
+ /**
+ * The mimetype of the pending contents.
+ */
+ private String pending_mimetype = "text/plain";
+
+ /**
+ * The current contents.
+ */
+ private byte[] contents = new byte[0];
+
+ /**
+ * The pending clipboard contents.
+ */
+ private final byte[] pending = new byte[MAXIMUM_LENGTH];
+
+ /**
+ * The length of the pending data, in bytes.
+ */
+ private int pending_length = 0;
+
+ /**
+ * The timestamp of the last contents update.
+ */
+ private long last_update = 0;
+
+ /**
+ * Returns the current clipboard contents.
+ * @return The current clipboard contents
+ */
+ public synchronized byte[] getContents() {
+ return contents;
+ }
+
+ /**
+ * Returns the mimetype of the current clipboard contents.
+ * @return The mimetype of the current clipboard contents.
+ */
+ public synchronized String getMimetype() {
+ return mimetype;
+ }
+
+ /**
+ * Begins a new update of the clipboard contents. The actual contents will
+ * not be saved until commit() is called.
+ *
+ * @param mimetype The mimetype of the contents being added.
+ */
+ public synchronized void begin(String mimetype) {
+ pending_length = 0;
+ this.pending_mimetype = mimetype;
+ }
+
+ /**
+ * Appends the given data to the clipboard contents.
+ *
+ * @param data The raw data to append.
+ */
+ public synchronized void append(byte[] data) {
+
+ // Calculate size of copy
+ int length = data.length;
+ int remaining = pending.length - pending_length;
+ if (remaining < length)
+ length = remaining;
+
+ // Append data
+ System.arraycopy(data, 0, pending, pending_length, length);
+ pending_length += length;
+
+ }
+
+ /**
+ * Commits the pending contents to the clipboard, notifying any threads
+ * waiting for clipboard updates.
+ */
+ public synchronized void commit() {
+
+ // Commit contents
+ mimetype = pending_mimetype;
+ contents = new byte[pending_length];
+ System.arraycopy(pending, 0, contents, 0, pending_length);
+
+ // Notify of update
+ last_update = System.currentTimeMillis();
+ this.notifyAll();
+
+ }
+
+ /**
+ * Wait up to the given timeout for new clipboard data.
+ *
+ * @param timeout The amount of time to wait, in milliseconds.
+ * @return true if the contents were updated within the timeframe given,
+ * false otherwise.
+ */
+ public synchronized boolean waitForContents(int timeout) {
+
+ // Wait for new contents if it's been a while
+ if (System.currentTimeMillis() - last_update > timeout) {
+ try {
+ this.wait(timeout);
+ return true;
+ }
+ catch (InterruptedException e) { /* ignore */ }
+ }
+
+ return false;
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/EnvironmentModule.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/EnvironmentModule.java b/guacamole/src/main/java/org/apache/guacamole/EnvironmentModule.java
new file mode 100644
index 0000000..c4a6115
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/EnvironmentModule.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import com.google.inject.AbstractModule;
+import org.apache.guacamole.environment.Environment;
+
+/**
+ * Guice module which binds the base Guacamole server environment.
+ *
+ * @author Michael Jumper
+ */
+public class EnvironmentModule extends AbstractModule {
+
+ /**
+ * The Guacamole server environment.
+ */
+ private final Environment environment;
+
+ /**
+ * Creates a new EnvironmentModule which will bind the given environment
+ * for future injection.
+ *
+ * @param environment
+ * The environment to bind.
+ */
+ public EnvironmentModule(Environment environment) {
+ this.environment = environment;
+ }
+
+ @Override
+ protected void configure() {
+
+ // Bind environment
+ bind(Environment.class).toInstance(environment);
+
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/GuacamoleClassLoader.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/GuacamoleClassLoader.java b/guacamole/src/main/java/org/apache/guacamole/GuacamoleClassLoader.java
new file mode 100644
index 0000000..f89b885
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/GuacamoleClassLoader.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.environment.Environment;
+import org.apache.guacamole.environment.LocalEnvironment;
+import org.apache.guacamole.properties.BasicGuacamoleProperties;
+
+/**
+ * A ClassLoader implementation which finds classes within a configurable
+ * directory. This directory is set within guacamole.properties. This class
+ * is deprecated in favor of DirectoryClassLoader, which is automatically
+ * configured based on the presence/absence of GUACAMOLE_HOME/lib.
+ *
+ * @author Michael Jumper
+ */
+@Deprecated
+public class GuacamoleClassLoader extends ClassLoader {
+
+ /**
+ * Class loader which will load classes from the classpath specified
+ * in guacamole.properties.
+ */
+ private URLClassLoader classLoader = null;
+
+ /**
+ * Any exception that occurs while the class loader is being instantiated.
+ */
+ private static GuacamoleException exception = null;
+
+ /**
+ * Singleton instance of the GuacamoleClassLoader.
+ */
+ private static GuacamoleClassLoader instance = null;
+
+ static {
+
+ try {
+ // Attempt to create singleton classloader which loads classes from
+ // all .jar's in the lib directory defined in guacamole.properties
+ instance = AccessController.doPrivileged(new PrivilegedExceptionAction<GuacamoleClassLoader>() {
+
+ @Override
+ public GuacamoleClassLoader run() throws GuacamoleException {
+
+ // TODONT: This should be injected, but GuacamoleClassLoader will be removed soon.
+ Environment environment = new LocalEnvironment();
+
+ return new GuacamoleClassLoader(
+ environment.getProperty(BasicGuacamoleProperties.LIB_DIRECTORY)
+ );
+
+ }
+
+ });
+ }
+
+ catch (PrivilegedActionException e) {
+ // On error, record exception
+ exception = (GuacamoleException) e.getException();
+ }
+
+ }
+
+ /**
+ * Creates a new GuacamoleClassLoader which reads classes from the given
+ * directory.
+ *
+ * @param libDirectory The directory to load classes from.
+ * @throws GuacamoleException If the file given is not a director, or if
+ * an error occurs while constructing the URL
+ * for the backing classloader.
+ */
+ private GuacamoleClassLoader(File libDirectory) throws GuacamoleException {
+
+ // If no directory provided, just direct requests to parent classloader
+ if (libDirectory == null)
+ return;
+
+ // Validate directory is indeed a directory
+ if (!libDirectory.isDirectory())
+ throw new GuacamoleException(libDirectory + " is not a directory.");
+
+ // Get list of URLs for all .jar's in the lib directory
+ Collection<URL> jarURLs = new ArrayList<URL>();
+ File[] files = libDirectory.listFiles(new FilenameFilter() {
+
+ @Override
+ public boolean accept(File dir, String name) {
+
+ // If it ends with .jar, accept the file
+ return name.endsWith(".jar");
+
+ }
+
+ });
+
+ // Verify directory was successfully read
+ if (files == null)
+ throw new GuacamoleException("Unable to read contents of directory " + libDirectory);
+
+ // Add the URL for each .jar to the jar URL list
+ for (File file : files) {
+
+ try {
+ jarURLs.add(file.toURI().toURL());
+ }
+ catch (MalformedURLException e) {
+ throw new GuacamoleException(e);
+ }
+
+ }
+
+ // Set delegate classloader to new URLClassLoader which loads from the
+ // .jars found above.
+
+ URL[] urls = new URL[jarURLs.size()];
+ classLoader = new URLClassLoader(
+ jarURLs.toArray(urls),
+ getClass().getClassLoader()
+ );
+
+ }
+
+ /**
+ * Returns an instance of a GuacamoleClassLoader which finds classes
+ * within the directory configured in guacamole.properties.
+ *
+ * @return An instance of a GuacamoleClassLoader.
+ * @throws GuacamoleException If no instance could be returned due to an
+ * error.
+ */
+ public static GuacamoleClassLoader getInstance() throws GuacamoleException {
+
+ // If instance could not be created, rethrow original exception
+ if (exception != null) throw exception;
+
+ return instance;
+
+ }
+
+ @Override
+ public Class<?> findClass(String name) throws ClassNotFoundException {
+
+ // If no classloader, use default loader
+ if (classLoader == null)
+ return Class.forName(name);
+
+ // Otherwise, delegate
+ return classLoader.loadClass(name);
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java b/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java
new file mode 100644
index 0000000..5345528
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.environment.Environment;
+import org.apache.guacamole.net.GuacamoleTunnel;
+import org.apache.guacamole.net.auth.AuthenticatedUser;
+import org.apache.guacamole.net.auth.UserContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Contains Guacamole-specific user information which is tied to the current
+ * session, such as the UserContext and current clipboard state.
+ *
+ * @author Michael Jumper
+ */
+public class GuacamoleSession {
+
+ /**
+ * Logger for this class.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(GuacamoleSession.class);
+
+ /**
+ * The user associated with this session.
+ */
+ private AuthenticatedUser authenticatedUser;
+
+ /**
+ * All UserContexts associated with this session. Each
+ * AuthenticationProvider may provide its own UserContext.
+ */
+ private List<UserContext> userContexts;
+
+ /**
+ * All currently-active tunnels, indexed by tunnel UUID.
+ */
+ private final Map<String, GuacamoleTunnel> tunnels = new ConcurrentHashMap<String, GuacamoleTunnel>();
+
+ /**
+ * The last time this session was accessed.
+ */
+ private long lastAccessedTime;
+
+ /**
+ * Creates a new Guacamole session associated with the given
+ * AuthenticatedUser and UserContexts.
+ *
+ * @param environment
+ * The environment of the Guacamole server associated with this new
+ * session.
+ *
+ * @param authenticatedUser
+ * The authenticated user to associate this session with.
+ *
+ * @param userContexts
+ * The List of UserContexts to associate with this session.
+ *
+ * @throws GuacamoleException
+ * If an error prevents the session from being created.
+ */
+ public GuacamoleSession(Environment environment,
+ AuthenticatedUser authenticatedUser,
+ List<UserContext> userContexts)
+ throws GuacamoleException {
+ this.lastAccessedTime = System.currentTimeMillis();
+ this.authenticatedUser = authenticatedUser;
+ this.userContexts = userContexts;
+ }
+
+ /**
+ * Returns the authenticated user associated with this session.
+ *
+ * @return
+ * The authenticated user associated with this session.
+ */
+ public AuthenticatedUser getAuthenticatedUser() {
+ return authenticatedUser;
+ }
+
+ /**
+ * Replaces the authenticated user associated with this session with the
+ * given authenticated user.
+ *
+ * @param authenticatedUser
+ * The authenticated user to associated with this session.
+ */
+ public void setAuthenticatedUser(AuthenticatedUser authenticatedUser) {
+ this.authenticatedUser = authenticatedUser;
+ }
+
+ /**
+ * Returns a list of all UserContexts associated with this session. Each
+ * AuthenticationProvider currently loaded by Guacamole may provide its own
+ * UserContext for any successfully-authenticated user.
+ *
+ * @return
+ * An unmodifiable list of all UserContexts associated with this
+ * session.
+ */
+ public List<UserContext> getUserContexts() {
+ return Collections.unmodifiableList(userContexts);
+ }
+
+ /**
+ * Replaces all UserContexts associated with this session with the given
+ * List of UserContexts.
+ *
+ * @param userContexts
+ * The List of UserContexts to associate with this session.
+ */
+ public void setUserContexts(List<UserContext> userContexts) {
+ this.userContexts = userContexts;
+ }
+
+ /**
+ * Returns whether this session has any associated active tunnels.
+ *
+ * @return true if this session has any associated active tunnels,
+ * false otherwise.
+ */
+ public boolean hasTunnels() {
+ return !tunnels.isEmpty();
+ }
+
+ /**
+ * Returns a map of all active tunnels associated with this session, where
+ * each key is the String representation of the tunnel's UUID. Changes to
+ * this map immediately affect the set of tunnels associated with this
+ * session. A tunnel need not be present here to be used by the user
+ * associated with this session, but tunnels not in this set will not
+ * be taken into account when determining whether a session is in use.
+ *
+ * @return A map of all active tunnels associated with this session.
+ */
+ public Map<String, GuacamoleTunnel> getTunnels() {
+ return tunnels;
+ }
+
+ /**
+ * Associates the given tunnel with this session, such that it is taken
+ * into account when determining session activity.
+ *
+ * @param tunnel The tunnel to associate with this session.
+ */
+ public void addTunnel(GuacamoleTunnel tunnel) {
+ tunnels.put(tunnel.getUUID().toString(), tunnel);
+ }
+
+ /**
+ * Disassociates the tunnel having the given UUID from this session.
+ *
+ * @param uuid The UUID of the tunnel to disassociate from this session.
+ * @return true if the tunnel existed and was removed, false otherwise.
+ */
+ public boolean removeTunnel(String uuid) {
+ return tunnels.remove(uuid) != null;
+ }
+
+ /**
+ * Updates this session, marking it as accessed.
+ */
+ public void access() {
+ lastAccessedTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Returns the time this session was last accessed, as the number of
+ * milliseconds since midnight January 1, 1970 GMT. Session access must
+ * be explicitly marked through calls to the access() function.
+ *
+ * @return The time this session was last accessed.
+ */
+ public long getLastAccessedTime() {
+ return lastAccessedTime;
+ }
+
+ /**
+ * Closes all associated tunnels and prevents any further use of this
+ * session.
+ */
+ public void invalidate() {
+
+ // Close all associated tunnels, if possible
+ for (GuacamoleTunnel tunnel : tunnels.values()) {
+ try {
+ tunnel.close();
+ }
+ catch (GuacamoleException e) {
+ logger.debug("Unable to close tunnel.", e);
+ }
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/HTTPTunnelRequest.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/HTTPTunnelRequest.java b/guacamole/src/main/java/org/apache/guacamole/HTTPTunnelRequest.java
new file mode 100644
index 0000000..9edc45a
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/HTTPTunnelRequest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * HTTP-specific implementation of TunnelRequest.
+ *
+ * @author Michael Jumper
+ */
+public class HTTPTunnelRequest extends TunnelRequest {
+
+ /**
+ * A copy of the parameters obtained from the HttpServletRequest used to
+ * construct the HTTPTunnelRequest.
+ */
+ private final Map<String, List<String>> parameterMap =
+ new HashMap<String, List<String>>();
+
+ /**
+ * Creates a HTTPTunnelRequest which copies and exposes the parameters
+ * from the given HttpServletRequest.
+ *
+ * @param request
+ * The HttpServletRequest to copy parameter values from.
+ */
+ @SuppressWarnings("unchecked") // getParameterMap() is defined as returning Map<String, String[]>
+ public HTTPTunnelRequest(HttpServletRequest request) {
+
+ // For each parameter
+ for (Map.Entry<String, String[]> mapEntry : ((Map<String, String[]>)
+ request.getParameterMap()).entrySet()) {
+
+ // Get parameter name and corresponding values
+ String parameterName = mapEntry.getKey();
+ List<String> parameterValues = Arrays.asList(mapEntry.getValue());
+
+ // Store copy of all values in our own map
+ parameterMap.put(
+ parameterName,
+ new ArrayList<String>(parameterValues)
+ );
+
+ }
+
+ }
+
+ @Override
+ public String getParameter(String name) {
+ List<String> values = getParameterValues(name);
+
+ // Return the first value from the list if available
+ if (values != null && !values.isEmpty())
+ return values.get(0);
+
+ return null;
+ }
+
+ @Override
+ public List<String> getParameterValues(String name) {
+ return parameterMap.get(name);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/TunnelLoader.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/TunnelLoader.java b/guacamole/src/main/java/org/apache/guacamole/TunnelLoader.java
new file mode 100644
index 0000000..756c6dd
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/TunnelLoader.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import com.google.inject.Module;
+
+/**
+ * Generic means of loading a tunnel without adding explicit dependencies within
+ * the main ServletModule, as not all servlet containers may have the classes
+ * required by all tunnel implementations.
+ *
+ * @author Michael Jumper
+ */
+public interface TunnelLoader extends Module {
+
+ /**
+ * Checks whether this type of tunnel is supported by the servlet container.
+ *
+ * @return true if this type of tunnel is supported and can be loaded
+ * without errors, false otherwise.
+ */
+ public boolean isSupported();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/TunnelModule.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/TunnelModule.java b/guacamole/src/main/java/org/apache/guacamole/TunnelModule.java
new file mode 100644
index 0000000..e7c105c
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/TunnelModule.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import com.google.inject.servlet.ServletModule;
+import java.lang.reflect.InvocationTargetException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Module which loads tunnel implementations.
+ *
+ * @author Michael Jumper
+ */
+public class TunnelModule extends ServletModule {
+
+ /**
+ * Logger for this class.
+ */
+ private final Logger logger = LoggerFactory.getLogger(TunnelModule.class);
+
+ /**
+ * Classnames of all implementation-specific WebSocket tunnel modules.
+ */
+ private static final String[] WEBSOCKET_MODULES = {
+ "org.apache.guacamole.websocket.WebSocketTunnelModule",
+ "org.apache.guacamole.websocket.jetty8.WebSocketTunnelModule",
+ "org.apache.guacamole.websocket.jetty9.WebSocketTunnelModule",
+ "org.apache.guacamole.websocket.tomcat.WebSocketTunnelModule"
+ };
+
+ private boolean loadWebSocketModule(String classname) {
+
+ try {
+
+ // Attempt to find WebSocket module
+ Class<?> module = Class.forName(classname);
+
+ // Create loader
+ TunnelLoader loader = (TunnelLoader) module.getConstructor().newInstance();
+
+ // Install module, if supported
+ if (loader.isSupported()) {
+ install(loader);
+ return true;
+ }
+
+ }
+
+ // If no such class or constructor, etc., then this particular
+ // WebSocket support is not present
+ catch (ClassNotFoundException e) {}
+ catch (NoClassDefFoundError e) {}
+ catch (NoSuchMethodException e) {}
+
+ // Log errors which indicate bugs
+ catch (InstantiationException e) {
+ logger.debug("Error instantiating WebSocket module.", e);
+ }
+ catch (IllegalAccessException e) {
+ logger.debug("Error instantiating WebSocket module.", e);
+ }
+ catch (InvocationTargetException e) {
+ logger.debug("Error instantiating WebSocket module.", e);
+ }
+
+ // Load attempt failed
+ return false;
+
+ }
+
+ @Override
+ protected void configureServlets() {
+
+ bind(TunnelRequestService.class);
+
+ // Set up HTTP tunnel
+ serve("/tunnel").with(BasicGuacamoleTunnelServlet.class);
+
+ // Try to load each WebSocket tunnel in sequence
+ for (String classname : WEBSOCKET_MODULES) {
+ if (loadWebSocketModule(classname)) {
+ logger.debug("WebSocket module loaded: {}", classname);
+ return;
+ }
+ }
+
+ // Warn of lack of WebSocket
+ logger.info("WebSocket support NOT present. Only HTTP will be used.");
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/TunnelRequest.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/TunnelRequest.java b/guacamole/src/main/java/org/apache/guacamole/TunnelRequest.java
new file mode 100644
index 0000000..622e2f0
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/TunnelRequest.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2015 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import java.util.List;
+import org.apache.guacamole.GuacamoleClientException;
+import org.apache.guacamole.GuacamoleException;
+
+/**
+ * A request object which provides only the functions absolutely required to
+ * retrieve and connect to a tunnel.
+ *
+ * @author Michael Jumper
+ */
+public abstract class TunnelRequest {
+
+ /**
+ * The name of the request parameter containing the user's authentication
+ * token.
+ */
+ public static final String AUTH_TOKEN_PARAMETER = "token";
+
+ /**
+ * The name of the parameter containing the identifier of the
+ * AuthenticationProvider associated with the UserContext containing the
+ * object to which a tunnel is being requested.
+ */
+ public static final String AUTH_PROVIDER_IDENTIFIER_PARAMETER = "GUAC_DATA_SOURCE";
+
+ /**
+ * The name of the parameter specifying the type of object to which a
+ * tunnel is being requested. Currently, this may be "c" for a Guacamole
+ * connection, or "g" for a Guacamole connection group.
+ */
+ public static final String TYPE_PARAMETER = "GUAC_TYPE";
+
+ /**
+ * The name of the parameter containing the unique identifier of the object
+ * to which a tunnel is being requested.
+ */
+ public static final String IDENTIFIER_PARAMETER = "GUAC_ID";
+
+ /**
+ * The name of the parameter containing the desired display width, in
+ * pixels.
+ */
+ public static final String WIDTH_PARAMETER = "GUAC_WIDTH";
+
+ /**
+ * The name of the parameter containing the desired display height, in
+ * pixels.
+ */
+ public static final String HEIGHT_PARAMETER = "GUAC_HEIGHT";
+
+ /**
+ * The name of the parameter containing the desired display resolution, in
+ * DPI.
+ */
+ public static final String DPI_PARAMETER = "GUAC_DPI";
+
+ /**
+ * The name of the parameter specifying one supported audio mimetype. This
+ * will normally appear multiple times within a single tunnel request -
+ * once for each mimetype.
+ */
+ public static final String AUDIO_PARAMETER = "GUAC_AUDIO";
+
+ /**
+ * The name of the parameter specifying one supported video mimetype. This
+ * will normally appear multiple times within a single tunnel request -
+ * once for each mimetype.
+ */
+ public static final String VIDEO_PARAMETER = "GUAC_VIDEO";
+
+ /**
+ * The name of the parameter specifying one supported image mimetype. This
+ * will normally appear multiple times within a single tunnel request -
+ * once for each mimetype.
+ */
+ public static final String IMAGE_PARAMETER = "GUAC_IMAGE";
+
+ /**
+ * All supported object types that can be used as the destination of a
+ * tunnel.
+ */
+ public static enum Type {
+
+ /**
+ * A Guacamole connection.
+ */
+ CONNECTION("c"),
+
+ /**
+ * A Guacamole connection group.
+ */
+ CONNECTION_GROUP("g");
+
+ /**
+ * The parameter value which denotes a destination object of this type.
+ */
+ final String PARAMETER_VALUE;
+
+ /**
+ * Defines a Type having the given corresponding parameter value.
+ *
+ * @param value
+ * The parameter value which denotes a destination object of this
+ * type.
+ */
+ Type(String value) {
+ PARAMETER_VALUE = value;
+ }
+
+ };
+
+ /**
+ * Returns the value of the parameter having the given name.
+ *
+ * @param name
+ * The name of the parameter to return.
+ *
+ * @return
+ * The value of the parameter having the given name, or null if no such
+ * parameter was specified.
+ */
+ public abstract String getParameter(String name);
+
+ /**
+ * Returns a list of all values specified for the given parameter.
+ *
+ * @param name
+ * The name of the parameter to return.
+ *
+ * @return
+ * All values of the parameter having the given name , or null if no
+ * such parameter was specified.
+ */
+ public abstract List<String> getParameterValues(String name);
+
+ /**
+ * Returns the value of the parameter having the given name, throwing an
+ * exception if the parameter is missing.
+ *
+ * @param name
+ * The name of the parameter to return.
+ *
+ * @return
+ * The value of the parameter having the given name.
+ *
+ * @throws GuacamoleException
+ * If the parameter is not present in the request.
+ */
+ public String getRequiredParameter(String name) throws GuacamoleException {
+
+ // Pull requested parameter, aborting if absent
+ String value = getParameter(name);
+ if (value == null)
+ throw new GuacamoleClientException("Parameter \"" + name + "\" is required.");
+
+ return value;
+
+ }
+
+ /**
+ * Returns the integer value of the parameter having the given name,
+ * throwing an exception if the parameter cannot be parsed.
+ *
+ * @param name
+ * The name of the parameter to return.
+ *
+ * @return
+ * The integer value of the parameter having the given name, or null if
+ * the parameter is missing.
+ *
+ * @throws GuacamoleException
+ * If the parameter is not a valid integer.
+ */
+ public Integer getIntegerParameter(String name) throws GuacamoleException {
+
+ // Pull requested parameter
+ String value = getParameter(name);
+ if (value == null)
+ return null;
+
+ // Attempt to parse as an integer
+ try {
+ return Integer.parseInt(value);
+ }
+
+ // Rethrow any parsing error as a GuacamoleClientException
+ catch (NumberFormatException e) {
+ throw new GuacamoleClientException("Parameter \"" + name + "\" must be a valid integer.", e);
+ }
+
+ }
+
+ /**
+ * Returns the authentication token associated with this tunnel request.
+ *
+ * @return
+ * The authentication token associated with this tunnel request, or
+ * null if no authentication token is present.
+ */
+ public String getAuthenticationToken() {
+ return getParameter(AUTH_TOKEN_PARAMETER);
+ }
+
+ /**
+ * Returns the identifier of the AuthenticationProvider associated with the
+ * UserContext from which the connection or connection group is to be
+ * retrieved when the tunnel is created. In the context of the REST API and
+ * the JavaScript side of the web application, this is referred to as the
+ * data source identifier.
+ *
+ * @return
+ * The identifier of the AuthenticationProvider associated with the
+ * UserContext from which the connection or connection group is to be
+ * retrieved when the tunnel is created.
+ *
+ * @throws GuacamoleException
+ * If the identifier was not present in the request.
+ */
+ public String getAuthenticationProviderIdentifier()
+ throws GuacamoleException {
+ return getRequiredParameter(AUTH_PROVIDER_IDENTIFIER_PARAMETER);
+ }
+
+ /**
+ * Returns the type of object for which the tunnel is being requested.
+ *
+ * @return
+ * The type of object for which the tunnel is being requested.
+ *
+ * @throws GuacamoleException
+ * If the type was not present in the request, or if the type requested
+ * is in the wrong format.
+ */
+ public Type getType() throws GuacamoleException {
+
+ String type = getRequiredParameter(TYPE_PARAMETER);
+
+ // For each possible object type
+ for (Type possibleType : Type.values()) {
+
+ // Match against defined parameter value
+ if (type.equals(possibleType.PARAMETER_VALUE))
+ return possibleType;
+
+ }
+
+ throw new GuacamoleClientException("Illegal identifier - unknown type.");
+
+ }
+
+ /**
+ * Returns the identifier of the destination of the tunnel being requested.
+ * As there are multiple types of destination objects available, and within
+ * multiple data sources, the associated object type and data source are
+ * also necessary to determine what this identifier refers to.
+ *
+ * @return
+ * The identifier of the destination of the tunnel being requested.
+ *
+ * @throws GuacamoleException
+ * If the identifier was not present in the request.
+ */
+ public String getIdentifier() throws GuacamoleException {
+ return getRequiredParameter(IDENTIFIER_PARAMETER);
+ }
+
+ /**
+ * Returns the display width desired for the Guacamole session over the
+ * tunnel being requested.
+ *
+ * @return
+ * The display width desired for the Guacamole session over the tunnel
+ * being requested, or null if no width was given.
+ *
+ * @throws GuacamoleException
+ * If the width specified was not a valid integer.
+ */
+ public Integer getWidth() throws GuacamoleException {
+ return getIntegerParameter(WIDTH_PARAMETER);
+ }
+
+ /**
+ * Returns the display height desired for the Guacamole session over the
+ * tunnel being requested.
+ *
+ * @return
+ * The display height desired for the Guacamole session over the tunnel
+ * being requested, or null if no width was given.
+ *
+ * @throws GuacamoleException
+ * If the height specified was not a valid integer.
+ */
+ public Integer getHeight() throws GuacamoleException {
+ return getIntegerParameter(HEIGHT_PARAMETER);
+ }
+
+ /**
+ * Returns the display resolution desired for the Guacamole session over
+ * the tunnel being requested, in DPI.
+ *
+ * @return
+ * The display resolution desired for the Guacamole session over the
+ * tunnel being requested, or null if no resolution was given.
+ *
+ * @throws GuacamoleException
+ * If the resolution specified was not a valid integer.
+ */
+ public Integer getDPI() throws GuacamoleException {
+ return getIntegerParameter(DPI_PARAMETER);
+ }
+
+ /**
+ * Returns a list of all audio mimetypes declared as supported within the
+ * tunnel request.
+ *
+ * @return
+ * A list of all audio mimetypes declared as supported within the
+ * tunnel request, or null if no mimetypes were specified.
+ */
+ public List<String> getAudioMimetypes() {
+ return getParameterValues(AUDIO_PARAMETER);
+ }
+
+ /**
+ * Returns a list of all video mimetypes declared as supported within the
+ * tunnel request.
+ *
+ * @return
+ * A list of all video mimetypes declared as supported within the
+ * tunnel request, or null if no mimetypes were specified.
+ */
+ public List<String> getVideoMimetypes() {
+ return getParameterValues(VIDEO_PARAMETER);
+ }
+
+ /**
+ * Returns a list of all image mimetypes declared as supported within the
+ * tunnel request.
+ *
+ * @return
+ * A list of all image mimetypes declared as supported within the
+ * tunnel request, or null if no mimetypes were specified.
+ */
+ public List<String> getImageMimetypes() {
+ return getParameterValues(IMAGE_PARAMETER);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/648a6c96/guacamole/src/main/java/org/apache/guacamole/TunnelRequestService.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/TunnelRequestService.java b/guacamole/src/main/java/org/apache/guacamole/TunnelRequestService.java
new file mode 100644
index 0000000..d78fdde
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/TunnelRequestService.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2013 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.guacamole;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.util.List;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.GuacamoleUnauthorizedException;
+import org.apache.guacamole.net.DelegatingGuacamoleTunnel;
+import org.apache.guacamole.net.GuacamoleTunnel;
+import org.apache.guacamole.net.auth.Connection;
+import org.apache.guacamole.net.auth.ConnectionGroup;
+import org.apache.guacamole.net.auth.Directory;
+import org.apache.guacamole.net.auth.UserContext;
+import org.apache.guacamole.rest.ObjectRetrievalService;
+import org.apache.guacamole.rest.auth.AuthenticationService;
+import org.apache.guacamole.protocol.GuacamoleClientInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class that takes a standard request from the Guacamole JavaScript
+ * client and produces the corresponding GuacamoleTunnel. The implementation
+ * of this utility is specific to the form of request used by the upstream
+ * Guacamole web application, and is not necessarily useful to applications
+ * that use purely the Guacamole API.
+ *
+ * @author Michael Jumper
+ * @author Vasily Loginov
+ */
+@Singleton
+public class TunnelRequestService {
+
+ /**
+ * Logger for this class.
+ */
+ private final Logger logger = LoggerFactory.getLogger(TunnelRequestService.class);
+
+ /**
+ * A service for authenticating users from auth tokens.
+ */
+ @Inject
+ private AuthenticationService authenticationService;
+
+ /**
+ * Service for convenient retrieval of objects.
+ */
+ @Inject
+ private ObjectRetrievalService retrievalService;
+
+ /**
+ * Reads and returns the client information provided within the given
+ * request.
+ *
+ * @param request
+ * The request describing tunnel to create.
+ *
+ * @return GuacamoleClientInformation
+ * An object containing information about the client sending the tunnel
+ * request.
+ *
+ * @throws GuacamoleException
+ * If the parameters of the tunnel request are invalid.
+ */
+ protected GuacamoleClientInformation getClientInformation(TunnelRequest request)
+ throws GuacamoleException {
+
+ // Get client information
+ GuacamoleClientInformation info = new GuacamoleClientInformation();
+
+ // Set width if provided
+ Integer width = request.getWidth();
+ if (width != null)
+ info.setOptimalScreenWidth(width);
+
+ // Set height if provided
+ Integer height = request.getHeight();
+ if (height != null)
+ info.setOptimalScreenHeight(height);
+
+ // Set resolution if provided
+ Integer dpi = request.getDPI();
+ if (dpi != null)
+ info.setOptimalResolution(dpi);
+
+ // Add audio mimetypes
+ List<String> audioMimetypes = request.getAudioMimetypes();
+ if (audioMimetypes != null)
+ info.getAudioMimetypes().addAll(audioMimetypes);
+
+ // Add video mimetypes
+ List<String> videoMimetypes = request.getVideoMimetypes();
+ if (videoMimetypes != null)
+ info.getVideoMimetypes().addAll(videoMimetypes);
+
+ // Add image mimetypes
+ List<String> imageMimetypes = request.getImageMimetypes();
+ if (imageMimetypes != null)
+ info.getImageMimetypes().addAll(imageMimetypes);
+
+ return info;
+ }
+
+ /**
+ * Creates a new tunnel using which is connected to the connection or
+ * connection group identifier by the given ID. Client information
+ * is specified in the {@code info} parameter.
+ *
+ * @param context
+ * The UserContext associated with the user for whom the tunnel is
+ * being created.
+ *
+ * @param type
+ * The type of object being connected to (connection or group).
+ *
+ * @param id
+ * The id of the connection or group being connected to.
+ *
+ * @param info
+ * Information describing the connected Guacamole client.
+ *
+ * @return
+ * A new tunnel, connected as required by the request.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while creating the tunnel.
+ */
+ protected GuacamoleTunnel createConnectedTunnel(UserContext context,
+ final TunnelRequest.Type type, String id,
+ GuacamoleClientInformation info)
+ throws GuacamoleException {
+
+ // Create connected tunnel from identifier
+ GuacamoleTunnel tunnel = null;
+ switch (type) {
+
+ // Connection identifiers
+ case CONNECTION: {
+
+ // Get connection directory
+ Directory<Connection> directory = context.getConnectionDirectory();
+
+ // Get authorized connection
+ Connection connection = directory.get(id);
+ if (connection == null) {
+ logger.info("Connection \"{}\" does not exist for user \"{}\".", id, context.self().getIdentifier());
+ throw new GuacamoleSecurityException("Requested connection is not authorized.");
+ }
+
+ // Connect tunnel
+ tunnel = connection.connect(info);
+ logger.info("User \"{}\" connected to connection \"{}\".", context.self().getIdentifier(), id);
+ break;
+ }
+
+ // Connection group identifiers
+ case CONNECTION_GROUP: {
+
+ // Get connection group directory
+ Directory<ConnectionGroup> directory = context.getConnectionGroupDirectory();
+
+ // Get authorized connection group
+ ConnectionGroup group = directory.get(id);
+ if (group == null) {
+ logger.info("Connection group \"{}\" does not exist for user \"{}\".", id, context.self().getIdentifier());
+ throw new GuacamoleSecurityException("Requested connection group is not authorized.");
+ }
+
+ // Connect tunnel
+ tunnel = group.connect(info);
+ logger.info("User \"{}\" connected to group \"{}\".", context.self().getIdentifier(), id);
+ break;
+ }
+
+ // Type is guaranteed to be one of the above
+ default:
+ assert(false);
+
+ }
+
+ return tunnel;
+
+ }
+
+ /**
+ * Associates the given tunnel with the given session, returning a wrapped
+ * version of the same tunnel which automatically handles closure and
+ * removal from the session.
+ *
+ * @param tunnel
+ * The connected tunnel to wrap and monitor.
+ *
+ * @param authToken
+ * The authentication token associated with the given session. If
+ * provided, this token will be automatically invalidated (and the
+ * corresponding session destroyed) if tunnel errors imply that the
+ * user is no longer authorized.
+ *
+ * @param session
+ * The Guacamole session to associate the tunnel with.
+ *
+ * @param type
+ * The type of object being connected to (connection or group).
+ *
+ * @param id
+ * The id of the connection or group being connected to.
+ *
+ * @return
+ * A new tunnel, associated with the given session, which delegates all
+ * functionality to the given tunnel while monitoring and automatically
+ * handling closure.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while obtaining the tunnel.
+ */
+ protected GuacamoleTunnel createAssociatedTunnel(GuacamoleTunnel tunnel,
+ final String authToken, final GuacamoleSession session,
+ final TunnelRequest.Type type, final String id)
+ throws GuacamoleException {
+
+ // Monitor tunnel closure and data
+ GuacamoleTunnel monitoredTunnel = new DelegatingGuacamoleTunnel(tunnel) {
+
+ /**
+ * The time the connection began, measured in milliseconds since
+ * midnight, January 1, 1970 UTC.
+ */
+ private final long connectionStartTime = System.currentTimeMillis();
+
+ @Override
+ public void close() throws GuacamoleException {
+
+ long connectionEndTime = System.currentTimeMillis();
+ long duration = connectionEndTime - connectionStartTime;
+
+ // Log closure
+ switch (type) {
+
+ // Connection identifiers
+ case CONNECTION:
+ logger.info("User \"{}\" disconnected from connection \"{}\". Duration: {} milliseconds",
+ session.getAuthenticatedUser().getIdentifier(), id, duration);
+ break;
+
+ // Connection group identifiers
+ case CONNECTION_GROUP:
+ logger.info("User \"{}\" disconnected from connection group \"{}\". Duration: {} milliseconds",
+ session.getAuthenticatedUser().getIdentifier(), id, duration);
+ break;
+
+ // Type is guaranteed to be one of the above
+ default:
+ assert(false);
+
+ }
+
+ try {
+
+ // Close and clean up tunnel
+ session.removeTunnel(getUUID().toString());
+ super.close();
+
+ }
+
+ // Ensure any associated session is invalidated if unauthorized
+ catch (GuacamoleUnauthorizedException e) {
+
+ // If there is an associated auth token, invalidate it
+ if (authenticationService.destroyGuacamoleSession(authToken))
+ logger.debug("Implicitly invalidated session for token \"{}\".", authToken);
+
+ // Continue with exception processing
+ throw e;
+
+ }
+
+ }
+
+ };
+
+ // Associate tunnel with session
+ session.addTunnel(monitoredTunnel);
+ return monitoredTunnel;
+
+ }
+
+ /**
+ * Creates a new tunnel using the parameters and credentials present in
+ * the given request.
+ *
+ * @param request
+ * The request describing the tunnel to create.
+ *
+ * @return
+ * The created tunnel, or null if the tunnel could not be created.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while creating the tunnel.
+ */
+ public GuacamoleTunnel createTunnel(TunnelRequest request)
+ throws GuacamoleException {
+
+ // Parse request parameters
+ String authToken = request.getAuthenticationToken();
+ String id = request.getIdentifier();
+ TunnelRequest.Type type = request.getType();
+ String authProviderIdentifier = request.getAuthenticationProviderIdentifier();
+ GuacamoleClientInformation info = getClientInformation(request);
+
+ GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
+ UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
+
+ try {
+
+ // Create connected tunnel using provided connection ID and client information
+ GuacamoleTunnel tunnel = createConnectedTunnel(userContext, type, id, info);
+
+ // Associate tunnel with session
+ return createAssociatedTunnel(tunnel, authToken, session, type, id);
+
+ }
+
+ // Ensure any associated session is invalidated if unauthorized
+ catch (GuacamoleUnauthorizedException e) {
+
+ // If there is an associated auth token, invalidate it
+ if (authenticationService.destroyGuacamoleSession(authToken))
+ logger.debug("Implicitly invalidated session for token \"{}\".", authToken);
+
+ // Continue with exception processing
+ throw e;
+
+ }
+
+ }
+
+}