diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/AuthenticationModule.java similarity index 65% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/AuthenticationModule.java index 1ade6e968..be8970e9e 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/AuthenticationModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Glyptodon LLC + * 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 @@ -20,13 +20,12 @@ * THE SOFTWARE. */ -package org.glyptodon.guacamole.net.basic.rest; +package org.glyptodon.guacamole.net.basic.inject; import com.google.inject.AbstractModule; -import com.google.inject.matcher.Matchers; +import com.google.inject.Inject; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.environment.Environment; -import org.glyptodon.guacamole.environment.LocalEnvironment; import org.glyptodon.guacamole.net.auth.AuthenticationProvider; import org.glyptodon.guacamole.net.basic.properties.BasicGuacamoleProperties; import org.glyptodon.guacamole.net.basic.rest.auth.AuthTokenGenerator; @@ -38,56 +37,58 @@ import org.slf4j.LoggerFactory; /** * A Guice Module for setting up authentication-specific dependency injection. - * + * * @author James Muehlner * @author Michael Jumper */ -public class RESTAuthModule extends AbstractModule { +public class AuthenticationModule extends AbstractModule { /** * Logger for this class. */ - private static final Logger logger = LoggerFactory.getLogger(RESTAuthModule.class); + private final Logger logger = LoggerFactory.getLogger(AuthenticationModule.class); /** * The Guacamole server environment. */ - private Environment environment; - - /** - * The AuthenticationProvider to use to authenticate all requests. - */ - private AuthenticationProvider authProvider; + private final Environment environment; /** - * Singleton instance of a TokenSessionMap. + * Singleton instance of TokenSessionMap. */ - private final TokenSessionMap sessionMap; + private final TokenSessionMap tokenSessionMap; /** * Creates a module which handles binding of authentication-related * objects, including the singleton TokenSessionMap. - * - * @param sessionMap An instance of TokenSessionMap to inject as a singleton - * wherever needed. + * + * @param environment + * The environment to use when configuring authentication. + * + * @param tokenSessionMap + * An instance of TokenSessionMap to inject as a singleton wherever + * needed. */ - public RESTAuthModule(TokenSessionMap sessionMap) { - this.sessionMap = sessionMap; + public AuthenticationModule(Environment environment, + TokenSessionMap tokenSessionMap) { + this.environment = environment; + this.tokenSessionMap = tokenSessionMap; } - + @Override protected void configure() { + // Bind session map + bind(TokenSessionMap.class).toInstance(tokenSessionMap); + + // Bind low-level services + bind(AuthenticationService.class); + bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); + + // Get and bind auth provider instance try { - - // Bind environment - environment = new LocalEnvironment(); - bind(Environment.class).toInstance(environment); - - // Get and bind auth provider instance - authProvider = environment.getRequiredProperty(BasicGuacamoleProperties.AUTH_PROVIDER); + AuthenticationProvider authProvider = environment.getRequiredProperty(BasicGuacamoleProperties.AUTH_PROVIDER); bind(AuthenticationProvider.class).toInstance(authProvider); - } catch (GuacamoleException e) { logger.error("Unable to read authentication provider from guacamole.properties: {}", e.getMessage()); @@ -95,15 +96,6 @@ public class RESTAuthModule extends AbstractModule { throw new RuntimeException(e); } - // Bind singleton TokenSessionMap - bind(TokenSessionMap.class).toInstance(sessionMap); - - bind(AuthenticationService.class); - bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); - - // Bind @AuthProviderRESTExposure annotation - bindInterceptor(Matchers.any(), Matchers.annotatedWith(AuthProviderRESTExposure.class), new AuthProviderRESTExceptionWrapper()); - } - + } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/BasicServletContextListener.java similarity index 59% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/BasicServletContextListener.java index ab028157e..4df326612 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/BasicServletContextListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Glyptodon LLC + * 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 @@ -20,38 +20,68 @@ * THE SOFTWARE. */ -package org.glyptodon.guacamole.net.basic; +package org.glyptodon.guacamole.net.basic.inject; 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.glyptodon.guacamole.net.basic.log.LogModule; -import org.glyptodon.guacamole.net.basic.rest.RESTAuthModule; -import org.glyptodon.guacamole.net.basic.rest.RESTModule; -import org.glyptodon.guacamole.net.basic.rest.RESTServletModule; +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.environment.Environment; +import org.glyptodon.guacamole.environment.LocalEnvironment; import org.glyptodon.guacamole.net.basic.rest.auth.BasicTokenSessionMap; import org.glyptodon.guacamole.net.basic.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 final TokenSessionMap sessionMap = new BasicTokenSessionMap(); - + 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( - new LogModule(), - new RESTServletModule(), - new RESTAuthModule(sessionMap), + Stage.PRODUCTION, + new EnvironmentModule(environment), + new LogModule(environment), + new AuthenticationModule(environment, sessionMap), new RESTModule(), new TunnelModule() ); @@ -60,11 +90,12 @@ public class BasicServletContextListener extends GuiceServletContextListener { @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { - // Shutdown TokenSessionMap - sessionMap.shutdown(); - super.contextDestroyed(servletContextEvent); - + + // Shutdown TokenSessionMap + if (sessionMap != null) + sessionMap.shutdown(); + } - + } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/EnvironmentModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/EnvironmentModule.java new file mode 100644 index 000000000..2cc3fd228 --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/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.glyptodon.guacamole.net.basic.inject; + +import com.google.inject.AbstractModule; +import org.glyptodon.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); + + } + +} + diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/log/LogModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/LogModule.java similarity index 81% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/log/LogModule.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/LogModule.java index a5ba1a039..5502821a7 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/log/LogModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/LogModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Glyptodon LLC + * 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 @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -package org.glyptodon.guacamole.net.basic.log; +package org.glyptodon.guacamole.net.basic.inject; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; @@ -28,7 +28,7 @@ import ch.qos.logback.core.joran.spi.JoranException; import ch.qos.logback.core.util.StatusPrinter; import com.google.inject.AbstractModule; import java.io.File; -import org.glyptodon.guacamole.properties.GuacamoleHome; +import org.glyptodon.guacamole.environment.Environment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,11 +44,27 @@ public class LogModule extends AbstractModule { */ private final Logger logger = LoggerFactory.getLogger(LogModule.class); + /** + * The Guacamole server environment. + */ + private final Environment environment; + + /** + * Creates a new LogModule which uses the given environment to determine + * the logging configuration. + * + * @param environment + * The environment to use when configuring logging. + */ + public LogModule(Environment environment) { + this.environment = environment; + } + @Override protected void configure() { // Only load logback configuration if GUACAMOLE_HOME exists - File guacamoleHome = GuacamoleHome.getDirectory(); + File guacamoleHome = environment.getGuacamoleHome(); if (!guacamoleHome.isDirectory()) return; @@ -58,7 +74,7 @@ public class LogModule extends AbstractModule { return; logger.info("Loading logback configuration from \"{}\".", logbackConfiguration); - + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); context.reset(); @@ -77,8 +93,7 @@ public class LogModule extends AbstractModule { logger.error("Initialization of logback failed: {}", e.getMessage()); logger.debug("Unable to load logback configuration..", e); } - + } } - diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/RESTModule.java similarity index 78% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/RESTModule.java index e87ac7e54..09a99c8ec 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/RESTModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Glyptodon LLC + * 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 @@ -20,12 +20,16 @@ * THE SOFTWARE. */ -package org.glyptodon.guacamole.net.basic.rest; +package org.glyptodon.guacamole.net.basic.inject; import com.google.inject.Scopes; +import com.google.inject.matcher.Matchers; import com.google.inject.servlet.ServletModule; import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import org.codehaus.jackson.jaxrs.JacksonJsonProvider; +import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExceptionWrapper; +import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure; +import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService; import org.glyptodon.guacamole.net.basic.rest.auth.TokenRESTService; import org.glyptodon.guacamole.net.basic.rest.clipboard.ClipboardRESTService; import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionRESTService; @@ -37,14 +41,24 @@ import org.glyptodon.guacamole.net.basic.rest.user.UserRESTService; /** * A Guice Module to set up the servlet mappings for the Guacamole REST API. - * + * * @author James Muehlner */ -public class RESTServletModule extends ServletModule { - +public class RESTModule extends ServletModule { + @Override protected void configureServlets() { - + + // Bind @AuthProviderRESTExposure annotation + bindInterceptor( + Matchers.any(), + Matchers.annotatedWith(AuthProviderRESTExposure.class), + new AuthProviderRESTExceptionWrapper() + ); + + // Bind convenience services used by the REST API + bind(ObjectRetrievalService.class); + // Set up the API endpoints bind(ActiveConnectionRESTService.class); bind(ClipboardRESTService.class); @@ -54,12 +68,12 @@ public class RESTServletModule extends ServletModule { bind(ProtocolRESTService.class); bind(TokenRESTService.class); bind(UserRESTService.class); - + // Set up the servlet and JSON mappings bind(GuiceContainer.class); bind(JacksonJsonProvider.class).in(Scopes.SINGLETON); serve("/api/*").with(GuiceContainer.class); } - + } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/TunnelModule.java similarity index 91% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelModule.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/TunnelModule.java index baabf99a7..023656d4d 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/TunnelModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Glyptodon LLC + * 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 @@ -20,17 +20,21 @@ * THE SOFTWARE. */ -package org.glyptodon.guacamole.net.basic; +package org.glyptodon.guacamole.net.basic.inject; import com.google.inject.servlet.ServletModule; import java.lang.reflect.InvocationTargetException; import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.net.basic.BasicGuacamoleTunnelServlet; +import org.glyptodon.guacamole.net.basic.GuacamoleClassLoader; +import org.glyptodon.guacamole.net.basic.TunnelLoader; +import org.glyptodon.guacamole.net.basic.TunnelRequestService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Module which loads tunnel implementations. - * + * * @author Michael Jumper */ public class TunnelModule extends ServletModule { @@ -54,7 +58,7 @@ public class TunnelModule extends ServletModule { try { - // Attempt to find WebSocket module + // Attempt to find WebSocket module Class module = (Class) GuacamoleClassLoader.getInstance().findClass(classname); // Create loader @@ -118,4 +122,3 @@ public class TunnelModule extends ServletModule { } } - diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/package-info.java similarity index 71% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/package-info.java index 5a72669c2..6e090e05e 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/inject/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Glyptodon LLC + * 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 @@ -20,24 +20,8 @@ * THE SOFTWARE. */ -package org.glyptodon.guacamole.net.basic.rest; - -import com.google.inject.AbstractModule; - /** - * A Guice Module for setting up dependency injection for the - * Guacamole REST API. - * - * @author James Muehlner + * Dependency injection classes specific to the Guacamole web application. */ -public class RESTModule extends AbstractModule { +package org.glyptodon.guacamole.net.basic.inject; - @Override - protected void configure() { - - // Bind generic low-level services - bind(ObjectRetrievalService.class); - - } - -} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java index 53d3f0652..bbeaa43db 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/BasicTokenSessionMap.java @@ -22,8 +22,6 @@ package org.glyptodon.guacamole.net.basic.rest.auth; -import com.google.inject.Inject; -import com.google.inject.Singleton; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; @@ -44,15 +42,8 @@ import org.slf4j.LoggerFactory; * * @author James Muehlner */ -@Singleton public class BasicTokenSessionMap implements TokenSessionMap { - /** - * The Guacamole server environment. - */ - @Inject - private Environment environment; - /** * Logger for this class. */ @@ -70,9 +61,13 @@ public class BasicTokenSessionMap implements TokenSessionMap { Collections.synchronizedMap(new LinkedHashMap(16, 0.75f, true)); /** - * Create a new BasicTokenGuacamoleSessionMap and initialize the session timeout value. + * Create a new BasicTokenGuacamoleSessionMap configured using the given + * environment. + * + * @param environment + * The environment to use when configuring the token session map. */ - public BasicTokenSessionMap() { + public BasicTokenSessionMap(Environment environment) { int sessionTimeoutValue; diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml index 490bdb335..a1baf566b 100644 --- a/guacamole/src/main/webapp/WEB-INF/web.xml +++ b/guacamole/src/main/webapp/WEB-INF/web.xml @@ -42,7 +42,7 @@ - org.glyptodon.guacamole.net.basic.BasicServletContextListener + org.glyptodon.guacamole.net.basic.inject.BasicServletContextListener