diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java new file mode 100644 index 000000000..550463716 --- /dev/null +++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java @@ -0,0 +1,111 @@ +package net.sourceforge.guacamole.net.basic; + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import net.sourceforge.guacamole.GuacamoleException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Simple ServletContextListener which loads a WebSocket tunnel implementation + * if available, using the Servlet 3.0 API to dynamically load and install + * the tunnel servlet. + * + * Note that because Guacamole depends on the Servlet 2.5 API, and 3.0 may + * not be available or needed if WebSocket is not desired, the 3.0 API is + * detected and invoked dynamically via reflection. + * + * @author Michael Jumper + */ +public class WebSocketSupportLoader implements ServletContextListener { + + private Logger logger = LoggerFactory.getLogger(WebSocketSupportLoader.class); + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + + try { + + // Attempt to find WebSocket servlet + Class servlet = (Class) GuacamoleClassLoader.getInstance().findClass( + "net.sourceforge.guacamole.net.basic.BasicGuacamoleWebSocketTunnelServlet" + ); + + // Dynamically add servlet IF SERVLET 3.0 API AVAILABLE! + try { + + // Get servlet registration class + Class regClass = Class.forName("javax.servlet.ServletRegistration"); + + // Get and invoke addServlet() + Method addServlet = ServletContext.class.getMethod("addServlet", String.class, Class.class); + Object reg = addServlet.invoke(sce.getServletContext(), "WebSocketTunnel", servlet); + + // Get and invoke addMapping() + Method addMapping = regClass.getMethod("addMapping", String[].class); + addMapping.invoke(reg, (Object) new String[]{"/websocket-tunnel"}); + + // If we succesfully load and register the WebSocket tunnel servlet, + // WebSocket is supported. + logger.info("WebSocket support found and loaded."); + + } + + // Servlet API 3.0 unsupported + catch (ClassNotFoundException e) { + logger.error("Servlet API 3.0 not found.", e); + } + catch (NoSuchMethodException e) { + logger.error("Servlet API 3.0 found, but incomplete.", e); + } + + // Servlet API 3.0 found, but errors during use + catch (IllegalAccessException e) { + logger.error("Unable to load WebSocket tunnel servlet.", e); + } + catch (InvocationTargetException e) { + logger.error("Internal error loading WebSocket tunnel servlet.", e); + } + + } + + // If no such servlet class, WebSocket support not present + catch (ClassNotFoundException e) { + logger.info("WebSocket support not found."); + } + + // Log all GuacamoleExceptions + catch (GuacamoleException e) { + logger.error("Unable to load/detect WebSocket support.", e); + } + + } + +} + diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml index 041e82ce0..61ae0b21b 100644 --- a/guacamole/src/main/webapp/WEB-INF/web.xml +++ b/guacamole/src/main/webapp/WEB-INF/web.xml @@ -28,6 +28,11 @@ + + + net.sourceforge.guacamole.net.basic.WebSocketSupportLoader + + Login servlet. diff --git a/guacamole/src/main/webapp/client.xhtml b/guacamole/src/main/webapp/client.xhtml index fb8c20c65..1a319ea11 100644 --- a/guacamole/src/main/webapp/client.xhtml +++ b/guacamole/src/main/webapp/client.xhtml @@ -101,10 +101,14 @@ window.onload = function() { window.setTimeout(function() { + var tunnel; + + // TODO: Detect WebSocket and websocket-tunnel + tunnel = new Guacamole.WebSocketTunnel("websocket-tunnel") + //tunnel = new Guacamole.HTTPTunnel("tunnel") + // Instantiate client - var guac = new Guacamole.Client( - new Guacamole.HTTPTunnel("tunnel") - ); + var guac = new Guacamole.Client(tunnel); // Add client to UI guac.getDisplay().className = "software-cursor";