GUACAMOLE-641: Allow extensions to receive Environment via constructors.

This commit is contained in:
Michael Jumper
2020-08-25 01:31:26 -07:00
parent 6644955fff
commit 9d7b979195
4 changed files with 47 additions and 14 deletions

View File

@@ -23,6 +23,7 @@ import java.util.Set;
import java.util.UUID;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials;
@@ -71,6 +72,9 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
* facade will still succeed, but its use will result in errors being
* logged, and all authentication attempts will fail.
*
* @param environment
* The Guacamole server environment.
*
* @param authProviderClass
* The AuthenticationProvider subclass to instantiate.
*
@@ -83,12 +87,12 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
* attempt. By default, errors during authentication halt the
* authentication process entirely.
*/
public AuthenticationProviderFacade(
public AuthenticationProviderFacade(Environment environment,
Class<? extends AuthenticationProvider> authProviderClass,
Set<String> tolerateFailures) {
this.tolerateFailures = tolerateFailures;
this.authProvider = ProviderFactory.newInstance("authentication provider",
authProviderClass);
this.authProvider = ProviderFactory.newInstance(environment,
"authentication provider", authProviderClass);
}
@Override

View File

@@ -199,7 +199,7 @@ public class ExtensionModule extends ServletModule {
logger.debug("[{}] Binding AuthenticationProvider \"{}\".",
boundAuthenticationProviders.size(), authenticationProvider.getName());
boundAuthenticationProviders.add(new AuthenticationProviderFacade(
authenticationProvider, tolerateFailures));
environment, authenticationProvider, tolerateFailures));
}
@@ -255,7 +255,7 @@ public class ExtensionModule extends ServletModule {
logger.debug("[{}] Binding listener \"{}\".",
boundListeners.size(), providerClass.getName());
boundListeners.addAll(ListenerFactory.createListeners(providerClass));
boundListeners.addAll(ListenerFactory.createListeners(environment, providerClass));
}

View File

@@ -30,6 +30,7 @@ import org.apache.guacamole.net.event.listener.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.guacamole.environment.Environment;
/**
* A factory that reflectively instantiates Listener objects for a given
@@ -44,15 +45,20 @@ class ListenerFactory {
* only listener type that will be returned. Otherwise, a list of Listener
* objects that adapt the legacy listener interfaces will be returned.
*
* @param environment
* The Environment instance that should be passed to the constructor
* of the given class, if a constructor accepting an Environment
* instance is defined.
*
* @param providerClass
* A class that represents a listener.
*
* @return
* The list of listeners represented by the given provider class.
*/
static List<Listener> createListeners(Class<?> providerClass) {
static List<Listener> createListeners(Environment environment, Class<?> providerClass) {
Object provider = ProviderFactory.newInstance("listener", providerClass);
Object provider = ProviderFactory.newInstance(environment, "listener", providerClass);
if (provider instanceof Listener) {
return Collections.singletonList((Listener) provider);

View File

@@ -24,6 +24,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import org.apache.guacamole.environment.Environment;
/**
* A utility for creating provider instances and logging unexpected outcomes
@@ -37,10 +38,18 @@ class ProviderFactory {
private static final Logger logger = LoggerFactory.getLogger(ProviderFactory.class);
/**
* Creates an instance of the specified provider class using the no-arg constructor.
* Creates an instance of the specified provider class using either the
* constructor accepting an instance of the Environment interface or, if no
* such constructor is defined, the no-arg constructor.
*
* @param environment
* The Environment instance that should be passed to the constructor
* of the given class, if a constructor accepting an Environment
* instance is defined.
*
* @param typeName
* The provider type name used for log messages; e.g. "authentication provider".
* The provider type name used for log messages; e.g. "authentication
* provider".
*
* @param providerClass
* The provider class to instantiate.
@@ -51,19 +60,33 @@ class ProviderFactory {
* @return
* A provider instance or null if no instance was created due to error.
*/
static <T> T newInstance(String typeName, Class<? extends T> providerClass) {
static <T> T newInstance(Environment environment, String typeName,
Class<? extends T> providerClass) {
T instance = null;
try {
// Attempt to instantiate the provider
instance = providerClass.getConstructor().newInstance();
// Attempt to instantiate the provider while providing the
// Guacamole server's environment
try {
instance = providerClass.getConstructor(Environment.class).newInstance(environment);
}
// Fall back to no-arg constructor if no constructor accepts
// Environment
catch (NoSuchMethodException e) {
logger.debug("{} does not provide a constructor accepting "
+ "Environment. Falling back to no-arg constructor.",
providerClass.getName());
instance = providerClass.getConstructor().newInstance();
}
}
catch (NoSuchMethodException e) {
logger.error("The {} extension in use is not properly defined. "
+ "Please contact the developers of the extension or, if you "
+ "are the developer, turn on debug-level logging.", typeName);
logger.debug("{} is missing a default constructor.",
providerClass.getName(), e);
logger.debug("{} is missing a usable constructor.", providerClass.getName(), e);
}
catch (SecurityException e) {
logger.error("The Java security manager is preventing extensions "