mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-364: declare and implement new listener API
This commit also deprecates the existing listener API and includes support for adapting existing listener implementations to the new API.
This commit is contained in:
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An exception thrown when a successful authentication is rejected by a
|
|
||||||
* AuthenticationSuccessListener in an extension.
|
|
||||||
*/
|
|
||||||
public class GuacamoleAuthenticationRejectedException
|
|
||||||
extends GuacamoleSecurityException {
|
|
||||||
|
|
||||||
public GuacamoleAuthenticationRejectedException() {
|
|
||||||
super("authentication rejected by listener extension");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An exception thrown when a request to close a tunnel is vetoed by a
|
|
||||||
* TunnelCloseListener in an extension.
|
|
||||||
*/
|
|
||||||
public class GuacamoleTunnelConnectedException extends GuacamoleClientException {
|
|
||||||
|
|
||||||
public GuacamoleTunnelConnectedException() {
|
|
||||||
super("tunnel close vetoed by listener extension");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An exception thrown when a successful tunnel connection is rejected by a
|
|
||||||
* TunnelConnectListener in an extension.
|
|
||||||
*/
|
|
||||||
public class GuacamoleTunnelRejectedException extends GuacamoleClientException {
|
|
||||||
|
|
||||||
public GuacamoleTunnelRejectedException() {
|
|
||||||
super("tunnel connection rejected by listener extension");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -26,6 +26,11 @@ import org.apache.guacamole.net.auth.UserContext;
|
|||||||
* An event which is triggered whenever a user's credentials pass
|
* An event which is triggered whenever a user's credentials pass
|
||||||
* authentication. The credentials that passed authentication are included
|
* authentication. The credentials that passed authentication are included
|
||||||
* within this event, and can be retrieved using getCredentials().
|
* within this event, and can be retrieved using getCredentials().
|
||||||
|
* <p>
|
||||||
|
* If a {@link org.apache.guacamole.net.event.listener.Listener} throws
|
||||||
|
* a GuacamoleException when handling an event of this type, successful authentication
|
||||||
|
* is effectively <em>vetoed</em> and will be subsequently processed as though the
|
||||||
|
* authentication failed.
|
||||||
*/
|
*/
|
||||||
public class AuthenticationSuccessEvent implements UserEvent, CredentialEvent {
|
public class AuthenticationSuccessEvent implements UserEvent, CredentialEvent {
|
||||||
|
|
||||||
|
@@ -28,6 +28,10 @@ import org.apache.guacamole.net.auth.UserContext;
|
|||||||
* being closed can be accessed through getTunnel(), and the UserContext
|
* being closed can be accessed through getTunnel(), and the UserContext
|
||||||
* associated with the request which is closing the tunnel can be retrieved
|
* associated with the request which is closing the tunnel can be retrieved
|
||||||
* with getUserContext().
|
* with getUserContext().
|
||||||
|
* <p>
|
||||||
|
* If a {@link org.apache.guacamole.net.event.listener.Listener} throws
|
||||||
|
* a GuacamoleException when handling an event of this type, the request to close
|
||||||
|
* the tunnel is effectively <em>vetoed</em> and will remain connected.
|
||||||
*/
|
*/
|
||||||
public class TunnelCloseEvent implements UserEvent, CredentialEvent, TunnelEvent {
|
public class TunnelCloseEvent implements UserEvent, CredentialEvent, TunnelEvent {
|
||||||
|
|
||||||
|
@@ -28,6 +28,10 @@ import org.apache.guacamole.net.auth.UserContext;
|
|||||||
* being connected can be accessed through getTunnel(), and the UserContext
|
* being connected can be accessed through getTunnel(), and the UserContext
|
||||||
* associated with the request which is connecting the tunnel can be retrieved
|
* associated with the request which is connecting the tunnel can be retrieved
|
||||||
* with getUserContext().
|
* with getUserContext().
|
||||||
|
* <p>
|
||||||
|
* If a {@link org.apache.guacamole.net.event.listener.Listener} throws
|
||||||
|
* a GuacamoleException when handling an event of this type, the tunnel connection
|
||||||
|
* is effectively <em>vetoed</em> and will be subsequently closed.
|
||||||
*/
|
*/
|
||||||
public class TunnelConnectEvent implements UserEvent, CredentialEvent, TunnelEvent {
|
public class TunnelConnectEvent implements UserEvent, CredentialEvent, TunnelEvent {
|
||||||
|
|
||||||
|
@@ -26,8 +26,12 @@ import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
|||||||
* A listener whose authenticationFailed() hook will fire immediately
|
* A listener whose authenticationFailed() hook will fire immediately
|
||||||
* after a user's authentication attempt fails. Note that this hook cannot
|
* after a user's authentication attempt fails. Note that this hook cannot
|
||||||
* be used to cancel the authentication failure.
|
* be used to cancel the authentication failure.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* Listeners should instead implement the {@link Listener} interface
|
||||||
*/
|
*/
|
||||||
public interface AuthenticationFailureListener extends Listener {
|
@Deprecated
|
||||||
|
public interface AuthenticationFailureListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event hook which fires immediately after a user's authentication attempt
|
* Event hook which fires immediately after a user's authentication attempt
|
||||||
|
@@ -27,8 +27,12 @@ import org.apache.guacamole.net.event.AuthenticationSuccessEvent;
|
|||||||
* authentication attempt succeeds. If a user successfully authenticates,
|
* authentication attempt succeeds. If a user successfully authenticates,
|
||||||
* the authenticationSucceeded() hook has the opportunity to cancel the
|
* the authenticationSucceeded() hook has the opportunity to cancel the
|
||||||
* authentication and force it to fail.
|
* authentication and force it to fail.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* Listeners should instead implement the {@link Listener} interface
|
||||||
*/
|
*/
|
||||||
public interface AuthenticationSuccessListener extends Listener {
|
@Deprecated
|
||||||
|
public interface AuthenticationSuccessListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event hook which fires immediately after a user's authentication attempt
|
* Event hook which fires immediately after a user's authentication attempt
|
||||||
|
@@ -19,10 +19,33 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.net.event.listener;
|
package org.apache.guacamole.net.event.listener;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker interface extended by all listener types. This interface is used
|
* A listener for events that occur in handing various Guacamole requests
|
||||||
* simply to validate that a listener class identified in an extension
|
* such as authentication, tunnel connect/close, etc. Listeners are registered
|
||||||
* actually implements some listener interface.
|
* through the extension manifest mechanism. When an event occurs, listeners
|
||||||
|
* are notified in the order in which they are declared in the manifest and
|
||||||
|
* continues until either all listeners have been notified or with the first
|
||||||
|
* listener that throws a GuacamoleException or other runtime exception.
|
||||||
*/
|
*/
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the recipient that an event has occurred.
|
||||||
|
* <p>
|
||||||
|
* Throwing an exception from an event listener can act to veto an action in
|
||||||
|
* progress for some event types. See the Javadoc for specific event types for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* an object that describes the subject event
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the listener wishes to stop notification of the event to subsequent
|
||||||
|
* listeners. For some event types, this acts to veto an action in progress;
|
||||||
|
* e.g. treating a successful authentication as though it failed
|
||||||
|
*/
|
||||||
|
void handleEvent(Object event) throws GuacamoleException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,8 +25,12 @@ import org.apache.guacamole.net.event.TunnelCloseEvent;
|
|||||||
/**
|
/**
|
||||||
* A listener whose tunnelClosed() hook will fire immediately after an
|
* A listener whose tunnelClosed() hook will fire immediately after an
|
||||||
* existing tunnel is closed.
|
* existing tunnel is closed.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* Listeners should instead implement the {@link Listener} interface
|
||||||
*/
|
*/
|
||||||
public interface TunnelCloseListener extends Listener {
|
@Deprecated
|
||||||
|
public interface TunnelCloseListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event hook which fires immediately before an existing tunnel is closed.
|
* Event hook which fires immediately before an existing tunnel is closed.
|
||||||
|
@@ -25,8 +25,12 @@ import org.apache.guacamole.net.event.TunnelConnectEvent;
|
|||||||
/**
|
/**
|
||||||
* A listener whose tunnelConnected() hook will fire immediately after a new
|
* A listener whose tunnelConnected() hook will fire immediately after a new
|
||||||
* tunnel is connected.
|
* tunnel is connected.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* Listeners should instead implement the {@link Listener} interface
|
||||||
*/
|
*/
|
||||||
public interface TunnelConnectListener extends Listener {
|
@Deprecated
|
||||||
|
public interface TunnelConnectListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event hook which fires immediately after a new tunnel is connected.
|
* Event hook which fires immediately after a new tunnel is connected.
|
||||||
|
@@ -113,7 +113,7 @@ public class Extension {
|
|||||||
/**
|
/**
|
||||||
* The collection of all Listener classes defined within the extension.
|
* The collection of all Listener classes defined within the extension.
|
||||||
*/
|
*/
|
||||||
private final Collection<Class<Listener>> listenerClasses;
|
private final Collection<Class<?>> listenerClasses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The resource for the small favicon for the extension. If provided, this
|
* The resource for the small favicon for the extension. If provided, this
|
||||||
@@ -328,15 +328,15 @@ public class Extension {
|
|||||||
* If any given class does not exist, or if any given class is not a
|
* If any given class does not exist, or if any given class is not a
|
||||||
* subclass of AuthenticationProvider.
|
* subclass of AuthenticationProvider.
|
||||||
*/
|
*/
|
||||||
private Collection<Class<Listener>> getListenerClasses(Collection<String> names)
|
private Collection<Class<?>> getListenerClasses(Collection<String> names)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// If no classnames are provided, just return an empty list
|
// If no classnames are provided, just return an empty list
|
||||||
if (names == null)
|
if (names == null)
|
||||||
return Collections.<Class<Listener>>emptyList();
|
return Collections.<Class<?>>emptyList();
|
||||||
|
|
||||||
// Define all auth provider classes
|
// Define all auth provider classes
|
||||||
Collection<Class<Listener>> classes = new ArrayList<Class<Listener>>(names.size());
|
Collection<Class<?>> classes = new ArrayList<Class<?>>(names.size());
|
||||||
for (String name : names)
|
for (String name : names)
|
||||||
classes.add(getListenerClass(name));
|
classes.add(getListenerClass(name));
|
||||||
|
|
||||||
@@ -578,7 +578,7 @@ public class Extension {
|
|||||||
* @return
|
* @return
|
||||||
* All declared listener classes with this extension.
|
* All declared listener classes with this extension.
|
||||||
*/
|
*/
|
||||||
public Collection<Class<Listener>> getListenerClasses() {
|
public Collection<Class<?>> getListenerClasses() {
|
||||||
return listenerClasses;
|
return listenerClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -95,8 +95,8 @@ public class ExtensionModule extends ServletModule {
|
|||||||
/**
|
/**
|
||||||
* All currently-bound authentication providers, if any.
|
* All currently-bound authentication providers, if any.
|
||||||
*/
|
*/
|
||||||
private final List<ListenerProvider> boundListenerProviders =
|
private final List<Listener> boundListners =
|
||||||
new ArrayList<ListenerProvider>();
|
new ArrayList<Listener>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for adding and retrieving language resources.
|
* Service for adding and retrieving language resources.
|
||||||
@@ -195,19 +195,19 @@ public class ExtensionModule extends ServletModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds the given Listener class such that any service
|
* Binds the given provider class such that a listener is bound for each
|
||||||
* requiring access to the Listener can obtain it via
|
* listener interface implemented by the provider and such that all bound
|
||||||
* injection, along with any other bound Listener.
|
* listener instances can be obtained via injection.
|
||||||
*
|
* *
|
||||||
* @param listenerClass
|
* @param providerClass
|
||||||
* The Listener class to bind.
|
* The listener provider class to bind
|
||||||
*/
|
*/
|
||||||
private void bindListenerProvider(Class<? extends Listener> listenerClass) {
|
private void bindListeners(Class<?> providerClass) {
|
||||||
|
|
||||||
|
logger.debug("[{}] Binding listeners \"{}\".",
|
||||||
|
boundListners.size(), providerClass.getName());
|
||||||
|
boundListners.addAll(ListenerFactory.createListeners(providerClass));
|
||||||
|
|
||||||
// Bind listener
|
|
||||||
logger.debug("[{}] Binding Listener \"{}\".",
|
|
||||||
boundListenerProviders.size(), listenerClass.getName());
|
|
||||||
boundListenerProviders.add(new ListenerFacade(listenerClass));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,23 +218,23 @@ public class ExtensionModule extends ServletModule {
|
|||||||
* @param listeners
|
* @param listeners
|
||||||
* The Listener classes to bind.
|
* The Listener classes to bind.
|
||||||
*/
|
*/
|
||||||
private void bindListenerProviders(Collection<Class<Listener>> listeners) {
|
private void bindListeners(Collection<Class<?>> listeners) {
|
||||||
|
|
||||||
// Bind each listener within extension
|
// Bind each listener within extension
|
||||||
for (Class<Listener> listener : listeners)
|
for (Class<?> listener : listeners)
|
||||||
bindListenerProvider(listener);
|
bindListeners(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all currently-bound ListenerProvider instances.
|
* Returns a list of all currently-bound Listener instances.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* A List of all currently-bound ListenerProvider instances. The List is
|
* A List of all currently-bound Listener instances. The List is
|
||||||
* not modifiable.
|
* not modifiable.
|
||||||
*/
|
*/
|
||||||
@Provides
|
@Provides
|
||||||
public List<ListenerProvider> getListenerProviders() {
|
public List<Listener> getListeners() {
|
||||||
return Collections.unmodifiableList(boundListenerProviders);
|
return Collections.unmodifiableList(boundListners);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -378,7 +378,7 @@ public class ExtensionModule extends ServletModule {
|
|||||||
bindAuthenticationProviders(extension.getAuthenticationProviderClasses());
|
bindAuthenticationProviders(extension.getAuthenticationProviderClasses());
|
||||||
|
|
||||||
// Attempt to load all listeners
|
// Attempt to load all listeners
|
||||||
bindListenerProviders(extension.getListenerClasses());
|
bindListeners(extension.getListenerClasses());
|
||||||
|
|
||||||
// Add any translation resources
|
// Add any translation resources
|
||||||
serveLanguageResources(extension.getTranslationResources());
|
serveLanguageResources(extension.getTranslationResources());
|
||||||
|
@@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.extension;
|
|
||||||
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
|
||||||
import org.apache.guacamole.net.event.AuthenticationSuccessEvent;
|
|
||||||
import org.apache.guacamole.net.event.TunnelCloseEvent;
|
|
||||||
import org.apache.guacamole.net.event.TunnelConnectEvent;
|
|
||||||
import org.apache.guacamole.net.event.listener.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a wrapper around a Listener subclass, allowing listener
|
|
||||||
* extensions to be bound without regard for which specific listener interfaces
|
|
||||||
* are implemented.
|
|
||||||
*/
|
|
||||||
class ListenerFacade implements ListenerProvider {
|
|
||||||
|
|
||||||
private final Listener delegate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new ListenerFacade which delegates all listener methods
|
|
||||||
* calls to an instance of the given Listener subclass. If
|
|
||||||
* an instance of the given class cannot be created, creation of this
|
|
||||||
* facade will still succeed. Errors will be logged at the time listener
|
|
||||||
* creation fails, but subsequent events directed to the listener will be
|
|
||||||
* silently dropped.
|
|
||||||
*
|
|
||||||
* @param listenerClass
|
|
||||||
* The Listener subclass to instantiate.
|
|
||||||
*/
|
|
||||||
public ListenerFacade(Class<? extends Listener> listenerClass) {
|
|
||||||
delegate = ProviderFactory.newInstance("listener", listenerClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the delegate listener of an authentication success event, if the
|
|
||||||
* listener implements the AuthenticationSuccessListener interface.
|
|
||||||
*
|
|
||||||
* @param
|
|
||||||
* event The AuthenticationSuccessEvent describing the authentication
|
|
||||||
* success that just occurred.
|
|
||||||
* @return
|
|
||||||
* false if the delegate listener rejects the successful authentication,
|
|
||||||
* else true
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* if the delegate listener throws this exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean authenticationSucceeded(AuthenticationSuccessEvent event)
|
|
||||||
throws GuacamoleException {
|
|
||||||
return !(delegate instanceof AuthenticationSuccessListener)
|
|
||||||
|| ((AuthenticationSuccessListener) delegate).authenticationSucceeded(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the delegate listener of an authentication failure event, if the
|
|
||||||
* listener implements the AuthenticationSuccessListener interface.
|
|
||||||
*
|
|
||||||
* @param
|
|
||||||
* event The AuthenticationFailureEvent describing the authentication
|
|
||||||
* failure that just occurred.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* if the delegate listener throws this exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void authenticationFailed(AuthenticationFailureEvent event)
|
|
||||||
throws GuacamoleException {
|
|
||||||
if (delegate instanceof AuthenticationFailureListener) {
|
|
||||||
((AuthenticationFailureListener) delegate).authenticationFailed(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the delegate listener of a tunnel connected event, if the
|
|
||||||
* listener implements the TunnelConnectListener interface.
|
|
||||||
*
|
|
||||||
* @param
|
|
||||||
* event The TunnelConnectEvent describing the tunnel that was just connected
|
|
||||||
|
|
||||||
* @return
|
|
||||||
* false if the delegate listener rejects the tunnel connection,
|
|
||||||
* else true
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* if the delegate listener throws this exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean tunnelConnected(TunnelConnectEvent event)
|
|
||||||
throws GuacamoleException {
|
|
||||||
return !(delegate instanceof TunnelConnectListener)
|
|
||||||
|| ((TunnelConnectListener) delegate).tunnelConnected(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the delegate listener of a tunnel close event, if the
|
|
||||||
* listener implements the TunnelCloseListener interface.
|
|
||||||
*
|
|
||||||
* @param
|
|
||||||
* event The TunnelCloseEvent describing the tunnel that is to be close
|
|
||||||
|
|
||||||
* @return
|
|
||||||
* false if the delegate listener rejects the tunnel close request,
|
|
||||||
* else true
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* if the delegate listener throws this exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean tunnelClosed(TunnelCloseEvent event) throws GuacamoleException {
|
|
||||||
return !(delegate instanceof TunnelCloseListener)
|
|
||||||
|| ((TunnelCloseListener) delegate).tunnelClosed(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.extension;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
|
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
||||||
|
import org.apache.guacamole.net.event.AuthenticationSuccessEvent;
|
||||||
|
import org.apache.guacamole.net.event.TunnelCloseEvent;
|
||||||
|
import org.apache.guacamole.net.event.TunnelConnectEvent;
|
||||||
|
import org.apache.guacamole.net.event.listener.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory that reflectively instantiates Listener objects for a given
|
||||||
|
* provider class.
|
||||||
|
*/
|
||||||
|
class ListenerFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates all listeners represented by an instance of the given provider class.
|
||||||
|
* <p>
|
||||||
|
* If a provider class implements the simple Listener interface, that is the
|
||||||
|
* only listener type that will be returned. Otherwise, a list of Listener
|
||||||
|
* objects that adapt the legacy listener interfaces will be returned.
|
||||||
|
*
|
||||||
|
* @param providerClass
|
||||||
|
* a class that represents a listener provider
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* list of listeners represented by the given provider class
|
||||||
|
*/
|
||||||
|
static List<Listener> createListeners(Class<?> providerClass) {
|
||||||
|
|
||||||
|
Object provider = ProviderFactory.newInstance("listener", providerClass);
|
||||||
|
|
||||||
|
if (provider instanceof Listener) {
|
||||||
|
return Collections.singletonList((Listener) provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
return createListenerAdapters(provider);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private static List<Listener> createListenerAdapters(Object provider) {
|
||||||
|
|
||||||
|
final List<Listener> listeners = new ArrayList<Listener>();
|
||||||
|
|
||||||
|
if (provider instanceof AuthenticationSuccessListener) {
|
||||||
|
listeners.add(new AuthenticationSuccessListenerAdapter(
|
||||||
|
(AuthenticationSuccessListener) provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provider instanceof AuthenticationFailureListener) {
|
||||||
|
listeners.add(new AuthenticationFailureListenerAdapter(
|
||||||
|
(AuthenticationFailureListener) provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provider instanceof TunnelConnectListener) {
|
||||||
|
listeners.add(new TunnelConnectListenerAdapter(
|
||||||
|
(TunnelConnectListener) provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provider instanceof TunnelCloseListener) {
|
||||||
|
listeners.add(new TunnelCloseListenerAdapter(
|
||||||
|
(TunnelCloseListener) provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
return listeners;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An adapter the allows an AuthenticationSuccessListener to be used
|
||||||
|
* as an ordinary Listener.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private static class AuthenticationSuccessListenerAdapter implements Listener {
|
||||||
|
|
||||||
|
private final AuthenticationSuccessListener delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new adapter.
|
||||||
|
*
|
||||||
|
* @param delegate
|
||||||
|
* the delegate listener
|
||||||
|
*/
|
||||||
|
AuthenticationSuccessListenerAdapter(AuthenticationSuccessListener delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles an AuthenticationSuccessEvent by passing the event to the delegate
|
||||||
|
* listener. If the delegate returns false, the adapter throws a GuacamoleException
|
||||||
|
* to veto the authentication success event. All other event types are ignored.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* an object that describes the subject event
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* if thrown by the delegate listener
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleEvent(Object event) throws GuacamoleException {
|
||||||
|
if (event instanceof AuthenticationSuccessEvent) {
|
||||||
|
if (!delegate.authenticationSucceeded((AuthenticationSuccessEvent) event)) {
|
||||||
|
throw new GuacamoleSecurityException(
|
||||||
|
"listener vetoed successful authentication");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An adapter the allows an AuthenticationFailureListener to be used
|
||||||
|
* as an ordinary Listener.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private static class AuthenticationFailureListenerAdapter implements Listener {
|
||||||
|
|
||||||
|
private final AuthenticationFailureListener delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new adapter.
|
||||||
|
*
|
||||||
|
* @param delegate
|
||||||
|
* the delegate listener
|
||||||
|
*/
|
||||||
|
AuthenticationFailureListenerAdapter(AuthenticationFailureListener delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles an AuthenticationFailureEvent by passing the event to the delegate
|
||||||
|
* listener. All other event types are ignored.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* an object that describes the subject event
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* if thrown by the delegate listener
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleEvent(Object event) throws GuacamoleException {
|
||||||
|
if (event instanceof AuthenticationFailureEvent) {
|
||||||
|
delegate.authenticationFailed((AuthenticationFailureEvent) event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An adapter the allows a TunnelConnectListener to be used as an ordinary
|
||||||
|
* Listener.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private static class TunnelConnectListenerAdapter implements Listener {
|
||||||
|
|
||||||
|
private final TunnelConnectListener delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new adapter.
|
||||||
|
*
|
||||||
|
* @param delegate
|
||||||
|
* the delegate listener
|
||||||
|
*/
|
||||||
|
TunnelConnectListenerAdapter(TunnelConnectListener delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a TunnelConnectEvent by passing the event to the delegate listener.
|
||||||
|
* If the delegate returns false, the adapter throws a GuacamoleException
|
||||||
|
* to veto the tunnel connect event. All other event types are ignored.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* an object that describes the subject event
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* if thrown by the delegate listener
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleEvent(Object event) throws GuacamoleException {
|
||||||
|
if (event instanceof TunnelConnectEvent) {
|
||||||
|
if (!delegate.tunnelConnected((TunnelConnectEvent) event)) {
|
||||||
|
throw new GuacamoleException("listener vetoed tunnel connection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An adapter the allows a TunnelCloseListener to be used as an ordinary
|
||||||
|
* Listener.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private static class TunnelCloseListenerAdapter implements Listener {
|
||||||
|
|
||||||
|
private final TunnelCloseListener delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new adapter.
|
||||||
|
*
|
||||||
|
* @param delegate
|
||||||
|
* the delegate listener
|
||||||
|
*/
|
||||||
|
TunnelCloseListenerAdapter(TunnelCloseListener delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a TunnelCloseEvent by passing the event to the delegate listener.
|
||||||
|
* If the delegate returns false, the adapter throws a GuacamoleException
|
||||||
|
* to veto the tunnel connect event. All other event types are ignored.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* an object that describes the subject event
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* if thrown by the delegate listener
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleEvent(Object event) throws GuacamoleException {
|
||||||
|
if (event instanceof TunnelCloseEvent) {
|
||||||
|
if (!delegate.tunnelClosed((TunnelCloseEvent) event)) {
|
||||||
|
throw new GuacamoleException("listener vetoed tunnel close request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -24,7 +24,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.apache.guacamole.GuacamoleAuthenticationRejectedException;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
||||||
@@ -218,19 +218,17 @@ public class AuthenticationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify all bound AuthenticationSuccessListeners that a successful authentication
|
* Notify all bound listeners that a successful authentication
|
||||||
* has occurred. If any of the bound listeners returns false (indicating that the
|
* has occurred.
|
||||||
* authentication should be rejected) a GuacamoleRejectedAuthenticationException is
|
|
||||||
* thrown.
|
|
||||||
*
|
*
|
||||||
* @param authenticatedUser
|
* @param authenticatedUser
|
||||||
* The user that was successfully authenticated
|
* The user that was successfully authenticated
|
||||||
* @param session
|
* @param session
|
||||||
* Existing session for the user (if any)
|
* Existing session for the user (if any)
|
||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If a filter throws an exception or if any filter rejects the authentication
|
* If thrown by a listener
|
||||||
*/
|
*/
|
||||||
private void notifyAuthenticationSuccessListeners(
|
private void fireAuthenticationSuccessEvent(
|
||||||
AuthenticatedUser authenticatedUser, GuacamoleSession session)
|
AuthenticatedUser authenticatedUser, GuacamoleSession session)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
@@ -240,26 +238,21 @@ public class AuthenticationService {
|
|||||||
authenticatedUser.getAuthenticationProvider().getIdentifier());
|
authenticatedUser.getAuthenticationProvider().getIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationSuccessEvent event = new AuthenticationSuccessEvent(
|
listenerService.handleEvent(new AuthenticationSuccessEvent(
|
||||||
userContext, authenticatedUser.getCredentials());
|
userContext, authenticatedUser.getCredentials()));
|
||||||
|
|
||||||
if (!listenerService.authenticationSucceeded(event)) {
|
|
||||||
throw new GuacamoleAuthenticationRejectedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify all bound AuthenticationFailureListeners that an authentication has failed.
|
* Notify all bound listeners that an authentication attempt has failed.
|
||||||
*
|
*
|
||||||
* @param credentials
|
* @param credentials
|
||||||
* The credentials that failed to authenticate
|
* The credentials that failed to authenticate
|
||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If a filter throws an exception
|
* If thrown by a listener
|
||||||
*/
|
*/
|
||||||
private void notifyAuthenticationFailureListeners(Credentials credentials)
|
private void fireAuthenticationFailedEvent(Credentials credentials)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
listenerService.handleEvent(new AuthenticationFailureEvent(credentials));
|
||||||
listenerService.authenticationFailed(new AuthenticationFailureEvent(credentials));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -290,13 +283,13 @@ public class AuthenticationService {
|
|||||||
if (existingSession != null) {
|
if (existingSession != null) {
|
||||||
AuthenticatedUser updatedUser = updateAuthenticatedUser(
|
AuthenticatedUser updatedUser = updateAuthenticatedUser(
|
||||||
existingSession.getAuthenticatedUser(), credentials);
|
existingSession.getAuthenticatedUser(), credentials);
|
||||||
notifyAuthenticationSuccessListeners(updatedUser, existingSession);
|
fireAuthenticationSuccessEvent(updatedUser, existingSession);
|
||||||
return updatedUser;
|
return updatedUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, attempt authentication as a new user
|
// Otherwise, attempt authentication as a new user
|
||||||
AuthenticatedUser authenticatedUser = AuthenticationService.this.authenticateUser(credentials);
|
AuthenticatedUser authenticatedUser = AuthenticationService.this.authenticateUser(credentials);
|
||||||
notifyAuthenticationSuccessListeners(authenticatedUser, null);
|
fireAuthenticationSuccessEvent(authenticatedUser, null);
|
||||||
|
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
logger.info("User \"{}\" successfully authenticated from {}.",
|
logger.info("User \"{}\" successfully authenticated from {}.",
|
||||||
@@ -310,7 +303,7 @@ public class AuthenticationService {
|
|||||||
// Log and rethrow any authentication errors
|
// Log and rethrow any authentication errors
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
|
|
||||||
notifyAuthenticationFailureListeners(credentials);
|
fireAuthenticationFailedEvent(credentials);
|
||||||
|
|
||||||
// Get request and username for sake of logging
|
// Get request and username for sake of logging
|
||||||
HttpServletRequest request = credentials.getRequest();
|
HttpServletRequest request = credentials.getRequest();
|
||||||
|
@@ -22,118 +22,32 @@ package org.apache.guacamole.rest.event;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.extension.ListenerProvider;
|
import org.apache.guacamole.net.event.listener.Listener;
|
||||||
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
|
||||||
import org.apache.guacamole.net.event.AuthenticationSuccessEvent;
|
|
||||||
import org.apache.guacamole.net.event.TunnelConnectEvent;
|
|
||||||
import org.apache.guacamole.net.event.TunnelCloseEvent;
|
|
||||||
import org.apache.guacamole.net.event.listener.AuthenticationFailureListener;
|
|
||||||
import org.apache.guacamole.net.event.listener.AuthenticationSuccessListener;
|
|
||||||
import org.apache.guacamole.net.event.listener.TunnelCloseListener;
|
|
||||||
import org.apache.guacamole.net.event.listener.TunnelConnectListener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service used to notify listeners registered by extensions when events of
|
* A service used to notify listeners registered by extensions when events of
|
||||||
* interest occur.
|
* interest occur.
|
||||||
*/
|
*/
|
||||||
public class ListenerService implements ListenerProvider {
|
public class ListenerService implements Listener {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private List<ListenerProvider> listeners;
|
private List<Listener> listeners;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies all bound listeners of an authentication success event. Listeners
|
* Notifies registered listeners than an event has occurred. Notification continues
|
||||||
* are allowed to veto a successful authentication by returning false from the
|
* until a given listener throws a GuacamoleException or other runtime exception, or
|
||||||
* listener method. Regardless of whether a particular listener rejects the
|
* until all listeners have been notified.
|
||||||
* successful authentication, all listeners are notified.
|
|
||||||
*
|
*
|
||||||
* @param event
|
* @param event
|
||||||
* The AuthenticationSuccessEvent describing the successful authentication
|
* an object that describes the subject event
|
||||||
* that just occurred.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @throws GuacamoleException if a registered listener throws a GuacamoleException
|
||||||
* false if any bound listener returns false, else true
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If any bound listener throws this exception. If a listener throws an exception
|
|
||||||
* some listeners may not receive the authentication success event notification.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean authenticationSucceeded(AuthenticationSuccessEvent event)
|
public void handleEvent(Object event) throws GuacamoleException {
|
||||||
throws GuacamoleException {
|
for (final Listener listener : listeners) {
|
||||||
boolean result = true;
|
listener.handleEvent(event);
|
||||||
for (AuthenticationSuccessListener listener : listeners) {
|
|
||||||
result = result && listener.authenticationSucceeded(event);
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies all bound listeners of an authentication failure event.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* The AuthenticationSuccessEvent describing the authentication failure
|
|
||||||
* that just occurred.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If any bound listener throws this exception. If a listener throws an exception
|
|
||||||
* some listeners may not receive the authentication failure event notification.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void authenticationFailed(AuthenticationFailureEvent event)
|
|
||||||
throws GuacamoleException {
|
|
||||||
for (AuthenticationFailureListener listener : listeners) {
|
|
||||||
listener.authenticationFailed(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies all bound listeners of an tunnel connected event. Listeners
|
|
||||||
* are allowed to veto a tunnel connection by returning false from the
|
|
||||||
* listener method. Regardless of whether a particular listener rejects the
|
|
||||||
* tunnel connection, all listeners are notified.
|
|
||||||
* @param event
|
|
||||||
* The TunnelConnectedEvent describing the tunnel that was just connected
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* false if any bound listener returns false, else true
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If any bound listener throws this exception. If a listener throws an exception
|
|
||||||
* some listeners may not receive the tunnel connected event notification.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean tunnelConnected(TunnelConnectEvent event)
|
|
||||||
throws GuacamoleException {
|
|
||||||
boolean result = true;
|
|
||||||
for (TunnelConnectListener listener : listeners) {
|
|
||||||
result = result && listener.tunnelConnected(event);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies all bound listeners of an tunnel close event. Listeners
|
|
||||||
* are allowed to veto the request to close a tunnel by returning false from
|
|
||||||
* the listener method. Regardless of whether a particular listener rejects the
|
|
||||||
* tunnel close request, all listeners are notified.
|
|
||||||
* @param event
|
|
||||||
* The TunnelCloseEvent describing the tunnel that is to be closed
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* false if any bound listener returns false, else true
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If any bound listener throws this exception. If a listener throws an exception
|
|
||||||
* some listeners may not receive the tunnel close event notification.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean tunnelClosed(TunnelCloseEvent event) throws GuacamoleException {
|
|
||||||
boolean result = true;
|
|
||||||
for (TunnelCloseListener listener : listeners) {
|
|
||||||
result = result && listener.tunnelClosed(event);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,8 +25,6 @@ import java.util.List;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
import org.apache.guacamole.GuacamoleSession;
|
||||||
import org.apache.guacamole.GuacamoleTunnelConnectedException;
|
|
||||||
import org.apache.guacamole.GuacamoleTunnelRejectedException;
|
|
||||||
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
@@ -70,10 +68,8 @@ public class TunnelRequestService {
|
|||||||
private ListenerService listenerService;
|
private ListenerService listenerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies bound TunnelConnectListeners that a new tunnel has been connected.
|
* Notifies bound listeners that a new tunnel has been connected.
|
||||||
* Listeners are allowed to veto a connected tunnel by returning false from the
|
* Listeners may veto a connected tunnel by throwing any GuacamoleException.
|
||||||
* listener method. If the ListenerService indicates that any listener rejected
|
|
||||||
* the tunnel, the tunnel is closed an GuacamoleTunnelRejectedException is thrown.
|
|
||||||
*
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the user for whom the tunnel is
|
* The UserContext associated with the user for whom the tunnel is
|
||||||
@@ -88,25 +84,15 @@ public class TunnelRequestService {
|
|||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If thrown by a listener or if any listener vetoes the connected tunnel
|
* If thrown by a listener or if any listener vetoes the connected tunnel
|
||||||
*/
|
*/
|
||||||
private void notifyTunnelConnectListeners(UserContext userContext,
|
private void fireTunnelConnectEvent(UserContext userContext,
|
||||||
Credentials credentials, GuacamoleTunnel tunnel) throws GuacamoleException {
|
Credentials credentials, GuacamoleTunnel tunnel) throws GuacamoleException {
|
||||||
TunnelConnectEvent event = new TunnelConnectEvent(userContext, credentials, tunnel);
|
listenerService.handleEvent(new TunnelConnectEvent(userContext, credentials, tunnel));
|
||||||
if (!listenerService.tunnelConnected(event)) {
|
|
||||||
try {
|
|
||||||
tunnel.close();
|
|
||||||
}
|
|
||||||
catch (GuacamoleException closeEx) {
|
|
||||||
logger.warn("Error closing rejected tunnel connection: {}", closeEx.getMessage());
|
|
||||||
}
|
|
||||||
throw new GuacamoleTunnelRejectedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies bound TunnelCloseListeners that a tunnel is to be closed.
|
* Notifies bound listeners that a tunnel is to be closed.
|
||||||
* Listeners are allowed to veto a request to close a tunnel by returning false from
|
* Listeners are allowed to veto a request to close a tunnel by throwing any
|
||||||
* the listener method. If the ListenerService indicates that any listener vetoed the
|
* GuacamoleException.
|
||||||
* request to the close the tunnel, a GuacamoleTunnelConnectedException is thrown.
|
|
||||||
*
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the user for whom the tunnel is
|
* The UserContext associated with the user for whom the tunnel is
|
||||||
@@ -119,15 +105,12 @@ public class TunnelRequestService {
|
|||||||
* The tunnel that was connected
|
* The tunnel that was connected
|
||||||
*
|
*
|
||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If thrown by a listener or if any listener vetoes the request to close the tunnel
|
* If thrown by a listener.
|
||||||
*/
|
*/
|
||||||
private void notifyTunnelCloseListeners(UserContext userContext,
|
private void fireTunnelClosedEvent(UserContext userContext,
|
||||||
Credentials credentials, GuacamoleTunnel tunnel)
|
Credentials credentials, GuacamoleTunnel tunnel)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
TunnelCloseEvent event = new TunnelCloseEvent(userContext, credentials, tunnel);
|
listenerService.handleEvent(new TunnelCloseEvent(userContext, credentials, tunnel));
|
||||||
if (listenerService.tunnelClosed(event)) {
|
|
||||||
throw new GuacamoleTunnelConnectedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -317,7 +300,7 @@ public class TunnelRequestService {
|
|||||||
public void close() throws GuacamoleException {
|
public void close() throws GuacamoleException {
|
||||||
|
|
||||||
// notify listeners to allow close request to be vetoed
|
// notify listeners to allow close request to be vetoed
|
||||||
notifyTunnelCloseListeners(context,
|
fireTunnelClosedEvent(context,
|
||||||
session.getAuthenticatedUser().getCredentials(), tunnel);
|
session.getAuthenticatedUser().getCredentials(), tunnel);
|
||||||
|
|
||||||
long connectionEndTime = System.currentTimeMillis();
|
long connectionEndTime = System.currentTimeMillis();
|
||||||
@@ -406,7 +389,7 @@ public class TunnelRequestService {
|
|||||||
GuacamoleTunnel tunnel = createConnectedTunnel(userContext, type, id, info);
|
GuacamoleTunnel tunnel = createConnectedTunnel(userContext, type, id, info);
|
||||||
|
|
||||||
// Notify listeners to allow connection to be vetoed
|
// Notify listeners to allow connection to be vetoed
|
||||||
notifyTunnelConnectListeners(userContext,
|
fireTunnelConnectEvent(userContext,
|
||||||
session.getAuthenticatedUser().getCredentials(), tunnel);
|
session.getAuthenticatedUser().getCredentials(), tunnel);
|
||||||
|
|
||||||
// Associate tunnel with session
|
// Associate tunnel with session
|
||||||
|
Reference in New Issue
Block a user