diff --git a/guacamole/pom.xml b/guacamole/pom.xml
index 0693e6aae..3e8941da7 100644
--- a/guacamole/pom.xml
+++ b/guacamole/pom.xml
@@ -254,6 +254,11 @@
slf4j-api
1.7.7
+
+ org.slf4j
+ jul-to-slf4j
+ 1.7.7
+
ch.qos.logback
logback-classic
@@ -435,34 +440,39 @@
com.google.inject
guice
- 3.0
+ 4.2.3
com.google.inject.extensions
guice-assistedinject
- 3.0
+ 4.2.3
com.google.inject.extensions
guice-servlet
- 3.0
+ 4.2.3
- com.sun.jersey
- jersey-server
- 1.17.1
+ org.glassfish.jersey.containers
+ jersey-container-servlet-core
+ 2.31
+
+
+ org.glassfish.jersey.inject
+ jersey-hk2
+ 2.31
-
+
- com.sun.jersey.contribs
- jersey-guice
- 1.17.1
-
+ org.glassfish.hk2
+ guice-bridge
+ 2.6.1
+
@@ -473,9 +483,9 @@
- com.sun.jersey
- jersey-json
- 1.17.1
+ org.glassfish.jersey.media
+ jersey-media-json-jackson
+ 2.31
diff --git a/guacamole/src/main/java/org/apache/guacamole/GuacamoleApplication.java b/guacamole/src/main/java/org/apache/guacamole/GuacamoleApplication.java
new file mode 100644
index 000000000..7f3e4603c
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/GuacamoleApplication.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import com.google.inject.Injector;
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+import javax.ws.rs.ApplicationPath;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
+import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
+/**
+ * JAX-RS Application which serves as the root definition of the Guacamole
+ * REST API. The HK2 dependency injection used by Jersey is automatically
+ * bridged to Guice, allowing injections managed by Guice to be injected within
+ * classes served by Jersey.
+ */
+@ApplicationPath("/*")
+public class GuacamoleApplication extends ResourceConfig {
+
+ /**
+ * Creates a new GuacamoleApplication which defines the Guacamole REST API,
+ * automatically configuring Jersey's HK2 dependency injection to
+ * additionally pull services from a Guice injector.
+ *
+ * @param servletContext
+ * The ServletContext which has already associated with a Guice
+ * injector via a GuacamoleServletContextListener.
+ *
+ * @param serviceLocator
+ * The HK2 service locator (injector).
+ */
+ @Inject
+ public GuacamoleApplication(ServletContext servletContext,
+ ServiceLocator serviceLocator) {
+
+ // Bridge Jersey logging (java.util.logging) to SLF4J
+ SLF4JBridgeHandler.removeHandlersForRootLogger();
+ SLF4JBridgeHandler.install();
+
+ // Bridge HK2 service locator with Guice injector
+ Injector guiceInjector = (Injector) servletContext.getAttribute(GuacamoleServletContextListener.GUICE_INJECTOR);
+ GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
+ GuiceIntoHK2Bridge bridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
+ bridge.bridgeGuiceInjector(guiceInjector);
+
+ // Automatically scan for REST resources
+ packages("org.apache.guacamole.rest");
+
+ // Use Jackson for JSON
+ register(JacksonFeature.class);
+
+ }
+
+}
diff --git a/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java b/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java
index e8ad6a81f..f793575e6 100644
--- a/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java
+++ b/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java
@@ -21,11 +21,12 @@ package org.apache.guacamole;
import org.apache.guacamole.tunnel.TunnelModule;
import com.google.inject.Guice;
-import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.google.inject.servlet.GuiceServletContextListener;
import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.inject.Inject;
import javax.servlet.ServletContextEvent;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
@@ -41,9 +42,45 @@ import org.slf4j.LoggerFactory;
/**
* A ServletContextListener to listen for initialization of the servlet context
* in order to set up dependency injection.
+ *
+ * NOTE: Guacamole's REST API uses Jersey 2.x which does not natively support
+ * dependency injection using Guice. It DOES support dependency injection using
+ * HK2, which supports bi-directional bridging with Guice.
+ *
+ * The overall process is thus:
+ *
+ * 1. Application initialization proceeds using GuacamoleServletContextListener,
+ * a subclass of GuiceServletContextListener, with all HTTP requests being
+ * routed through GuiceFilter which serves as the absolute root.
+ *
+ * 2. GuacamoleServletContextListener prepares the Guice injector, storing the
+ * injector within the ServletContext such that it can later be bridged with
+ * HK2.
+ *
+ * 3. Several of the modules used to prepare the Guice injector are
+ * ServletModule subclasses, which define HTTP request paths that GuiceFilter
+ * should route to specific servlets. One of these paths is "/api/*" (the
+ * root of the REST API) which is routed to Jersey's ServletContainer servlet
+ * (the root of Jersey's JAX-RS implementation).
+ *
+ * 4. Configuration information passed to Jersey's ServletContainer tells Jersey
+ * to use the GuacamoleApplication class (a subclass of ResourceConfig) to
+ * define the rest of the resources and any other configuration.
+ *
+ * 5. When Jersey creates its instance of GuacamoleApplication, the
+ * initialization process of GuacamoleApplication pulls the Guice injector
+ * from the ServletContext, completes the HK2 bridging, and configures Jersey
+ * to automatically locate and inject all REST services.
*/
public class GuacamoleServletContextListener extends GuiceServletContextListener {
+ /**
+ * The name of the ServletContext attribute which will contain a reference
+ * to the Guice injector once the contextInitialized() event has been
+ * handled.
+ */
+ public static final String GUICE_INJECTOR = "GUAC_GUICE_INJECTOR";
+
/**
* Logger for this class.
*/
@@ -65,6 +102,12 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
@Inject
private List authProviders;
+ /**
+ * Internal reference to the Guice injector that was lazily created when
+ * getInjector() was first invoked.
+ */
+ private final AtomicReference guiceInjector = new AtomicReference<>();
+
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
@@ -78,33 +121,47 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
throw new RuntimeException(e);
}
+ // NOTE: The superclass implementation of contextInitialized() is
+ // expected to invoke getInjector(), hence the need to call AFTER
+ // setting up the environment and session map
super.contextInitialized(servletContextEvent);
+ // Inject any annotated members of this class
+ Injector injector = getInjector();
+ injector.injectMembers(this);
+
+ // Store reference to injector for use by Jersey and HK2 bridge
+ servletContextEvent.getServletContext().setAttribute(GUICE_INJECTOR, injector);
+
}
@Override
protected Injector getInjector() {
+ return guiceInjector.updateAndGet((current) -> {
- // Create injector
- Injector injector = Guice.createInjector(Stage.PRODUCTION,
- new EnvironmentModule(environment),
- new LogModule(environment),
- new ExtensionModule(environment),
- new RESTServiceModule(sessionMap),
- new TunnelModule()
- );
+ // Use existing injector if already created
+ if (current != null)
+ return current;
- // Inject any annotated members of this class
- injector.injectMembers(this);
+ // Create new injector if necessary
+ Injector injector = Guice.createInjector(Stage.PRODUCTION,
+ new EnvironmentModule(environment),
+ new LogModule(environment),
+ new ExtensionModule(environment),
+ new RESTServiceModule(sessionMap),
+ new TunnelModule()
+ );
- return injector;
+ return injector;
+ });
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
- super.contextDestroyed(servletContextEvent);
+ // Clean up reference to Guice injector
+ servletContextEvent.getServletContext().removeAttribute(GUICE_INJECTOR);
// Shutdown TokenSessionMap
if (sessionMap != null)
@@ -116,6 +173,9 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
authProvider.shutdown();
}
+ // Continue any Guice-specific cleanup
+ super.contextDestroyed(servletContextEvent);
+
}
}
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java b/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java
index 01103b0ed..e37b106a9 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/APIException.java
@@ -33,18 +33,15 @@ import org.apache.guacamole.GuacamoleException;
public class APIException extends WebApplicationException {
/**
- * Construct a new APIException based on the given GuacamoleException and
- * HTTP status. The details of the GuacamoleException relevant to the REST
- * API will be exposed via an APIError.
- *
- * @param status
- * The HTTP status which corresponds to the GuacamoleException.
+ * Construct a new APIException based on the given GuacamoleException. The
+ * details of the GuacamoleException relevant to the REST API will be
+ * exposed via an APIError.
*
* @param exception
* The GuacamoleException that occurred.
*/
- public APIException(Response.Status status, GuacamoleException exception) {
- super(Response.status(status)
+ public APIException(GuacamoleException exception) {
+ super(Response.status(exception.getHttpStatusCode())
.type(MediaType.APPLICATION_JSON)
.entity(new APIError(exception))
.build());
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/LimitedRequestInputStream.java b/guacamole/src/main/java/org/apache/guacamole/rest/LimitedRequestInputStream.java
new file mode 100644
index 000000000..840ef1917
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/LimitedRequestInputStream.java
@@ -0,0 +1,152 @@
+/*
+ * 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.rest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.guacamole.GuacamoleClientOverrunException;
+
+/**
+ * InputStream implementation which limits the body of REST API requests to
+ * a particular maximum size. If an attempt is made to read from a REST API
+ * request which exceeds this limit, the read attempt will be aborted by
+ * throwing an APIException.
+ */
+public class LimitedRequestInputStream extends InputStream {
+
+ /**
+ * The InputStream being limited.
+ */
+ private final InputStream stream;
+
+ /**
+ * The maximum number of bytes to allow to be read or skipped.
+ */
+ private final long maxLength;
+
+ /**
+ * The total number of bytes that have been read or skipped from the stream
+ * thus far.
+ */
+ private long bytesRead = 0;
+
+ /**
+ * Wraps the given InputStream, ensuring that the overall number of bytes
+ * read or skipped does not exceed the given maximum length.
+ *
+ * @param stream
+ * The InputStream to limit.
+ *
+ * @param maxLength
+ * The maximum number of bytes to allow to be read or skipped.
+ */
+ public LimitedRequestInputStream(InputStream stream, long maxLength) {
+ this.stream = stream;
+ this.maxLength = maxLength;
+ }
+
+ /**
+ * Immediately verifies that the stream length limit has not been exceeded.
+ * If the length limit has been exceeded, an APIException is thrown
+ * indicating that the request body is too large.
+ *
+ * @throws APIException
+ * If the length limit has been exceeded.
+ */
+ private synchronized void recheckLength() throws APIException {
+ if (bytesRead > maxLength)
+ throw new APIException(new GuacamoleClientOverrunException("Request body/entity too large."));
+ }
+
+ /**
+ * Updates the current number of bytes read based on the return value of a
+ * read-like operation such as read() or skip(). If the maximum stream
+ * length is exceeded as a result of the read, an APIException indicating
+ * this is thrown.
+ *
+ * NOTE: To avoid unnecessary read operations, recheckLength() should be
+ * manually called before performing any read operation. This function will
+ * perform the same checks, but can inherently only do so AFTER the read
+ * operation has occurred.
+ *
+ * @param change
+ * The number of bytes that have been read or skipped, or -1 if the
+ * read-like operation has failed (and no bytes have been read).
+ *
+ * @return
+ * The provided number of bytes read/skipped.
+ *
+ * @throws APIException
+ * If the read-like operation that occurred has caused the stream
+ * length to exceed its maximum.
+ */
+ private synchronized long limitedRead(long change) throws APIException {
+
+ if (change != -1) {
+ bytesRead += change;
+ recheckLength();
+ }
+
+ return change;
+
+ }
+
+ @Override
+ public void close() throws IOException {
+ stream.close();
+ }
+
+ @Override
+ public int available() throws IOException {
+ return stream.available();
+ }
+
+ @Override
+ public long skip(long l) throws IOException {
+ recheckLength();
+ return limitedRead(stream.skip(l));
+ }
+
+ @Override
+ public int read(byte[] bytes, int i, int i1) throws IOException {
+ recheckLength();
+ return (int) limitedRead(stream.read(bytes, i, i1));
+ }
+
+ @Override
+ public int read(byte[] bytes) throws IOException {
+ recheckLength();
+ return (int) limitedRead(stream.read(bytes));
+ }
+
+ @Override
+ public int read() throws IOException {
+
+ recheckLength();
+
+ int value = stream.read();
+ if (value != -1)
+ limitedRead(1);
+
+ return value;
+
+ }
+
+}
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/PATCH.java b/guacamole/src/main/java/org/apache/guacamole/rest/PATCH.java
deleted file mode 100644
index 171719eed..000000000
--- a/guacamole/src/main/java/org/apache/guacamole/rest/PATCH.java
+++ /dev/null
@@ -1,35 +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.rest;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import javax.ws.rs.HttpMethod;
-
-/**
- * An annotation for using the HTTP PATCH method in the REST endpoints.
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@HttpMethod("PATCH")
-public @interface PATCH {}
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java
index e6c9b4c5b..85430ae19 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTExceptionMapper.java
@@ -19,9 +19,10 @@
package org.apache.guacamole.rest;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -82,6 +83,10 @@ public class RESTExceptionMapper implements ExceptionMapper {
@Override
public Response toResponse(Throwable t) {
+
+ // Pass WebApplicationException responses through untouched
+ if (t instanceof WebApplicationException)
+ return ((WebApplicationException) t).getResponse();
// Ensure any associated session is invalidated if unauthorized
if (t instanceof GuacamoleUnauthorizedException) {
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/RESTMethodMatcher.java b/guacamole/src/main/java/org/apache/guacamole/rest/RESTMethodMatcher.java
deleted file mode 100644
index 875f4161c..000000000
--- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTMethodMatcher.java
+++ /dev/null
@@ -1,128 +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.rest;
-
-import com.google.inject.matcher.AbstractMatcher;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.Path;
-import org.apache.guacamole.GuacamoleException;
-
-/**
- * A Guice Matcher which matches only methods which throw GuacamoleException
- * (or a subclass thereof) and are explicitly annotated as with an HTTP method
- * annotation like @GET
or @POST
. Any method which
- * throws GuacamoleException and is annotated with an annotation that is
- * annotated with @HttpMethod
will match.
- */
-public class RESTMethodMatcher extends AbstractMatcher {
-
- /**
- * Returns whether the given method throws the specified exception type,
- * including any subclasses of that type.
- *
- * @param method
- * The method to test.
- *
- * @param exceptionType
- * The exception type to test for.
- *
- * @return
- * true if the given method throws an exception of the specified type,
- * false otherwise.
- */
- private boolean methodThrowsException(Method method,
- Class extends Exception> exceptionType) {
-
- // Check whether the method throws an exception of the specified type
- for (Class> thrownType : method.getExceptionTypes()) {
- if (exceptionType.isAssignableFrom(thrownType))
- return true;
- }
-
- // No such exception is declared to be thrown
- return false;
-
- }
-
- /**
- * Returns whether the given method is annotated as a REST method. A REST
- * method is annotated with an annotation which is annotated with
- * @HttpMethod
or @Path
.
- *
- * @param method
- * The method to test.
- *
- * @return
- * true if the given method is annotated as a REST method, false
- * otherwise.
- */
- private boolean isRESTMethod(Method method) {
-
- // Check whether the required REST annotations are present
- for (Annotation annotation : method.getAnnotations()) {
-
- // A method is a REST method if it is annotated with @HttpMethod
- Class extends Annotation> annotationType = annotation.annotationType();
- if (annotationType.isAnnotationPresent(HttpMethod.class))
- return true;
-
- // A method is a REST method if it is annotated with @Path
- if (Path.class.isAssignableFrom(annotationType))
- return true;
-
- }
-
- // A method is also REST method if it overrides a REST method within
- // the superclass
- Class> superclass = method.getDeclaringClass().getSuperclass();
- if (superclass != null) {
-
- // Recheck against identical method within superclass
- try {
- return isRESTMethod(superclass.getMethod(method.getName(),
- method.getParameterTypes()));
- }
-
- // If there is no such method, then this method cannot possibly be
- // a REST method
- catch (NoSuchMethodException e) {
- return false;
- }
-
- }
-
- // Lacking a superclass, the search stops here - it's not a REST method
- return false;
-
- }
-
- @Override
- public boolean matches(Method method) {
-
- // Guacamole REST methods are REST methods which throw
- // GuacamoleExceptions
- return isRESTMethod(method)
- && methodThrowsException(method, GuacamoleException.class);
-
- }
-
-}
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java b/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
index 4efab0ff5..32878b1ee 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java
@@ -19,18 +19,14 @@
package org.apache.guacamole.rest;
-import org.apache.guacamole.rest.event.ListenerService;
-import org.apache.guacamole.rest.session.UserContextResourceFactory;
-import org.apache.guacamole.rest.session.SessionRESTService;
import com.google.inject.Scopes;
import com.google.inject.assistedinject.FactoryModuleBuilder;
-import com.google.inject.matcher.Matchers;
import com.google.inject.servlet.ServletModule;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import org.aopalliance.intercept.MethodInterceptor;
+import java.util.Collections;
+import org.apache.guacamole.rest.event.ListenerService;
+import org.apache.guacamole.rest.session.UserContextResourceFactory;
+import org.apache.guacamole.GuacamoleApplication;
import org.apache.guacamole.rest.activeconnection.ActiveConnectionModule;
-import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
-import org.apache.guacamole.rest.auth.TokenRESTService;
import org.apache.guacamole.rest.auth.AuthTokenGenerator;
import org.apache.guacamole.rest.auth.AuthenticationService;
import org.apache.guacamole.rest.auth.DecorationService;
@@ -38,15 +34,14 @@ import org.apache.guacamole.rest.auth.SecureRandomAuthTokenGenerator;
import org.apache.guacamole.rest.auth.TokenSessionMap;
import org.apache.guacamole.rest.connection.ConnectionModule;
import org.apache.guacamole.rest.connectiongroup.ConnectionGroupModule;
-import org.apache.guacamole.rest.extension.ExtensionRESTService;
-import org.apache.guacamole.rest.language.LanguageRESTService;
-import org.apache.guacamole.rest.patch.PatchRESTService;
import org.apache.guacamole.rest.session.SessionResourceFactory;
import org.apache.guacamole.rest.sharingprofile.SharingProfileModule;
import org.apache.guacamole.rest.tunnel.TunnelCollectionResourceFactory;
import org.apache.guacamole.rest.tunnel.TunnelResourceFactory;
import org.apache.guacamole.rest.user.UserModule;
import org.apache.guacamole.rest.usergroup.UserGroupModule;
+import org.glassfish.jersey.servlet.ServletContainer;
+import org.glassfish.jersey.servlet.ServletProperties;
import org.webjars.servlet.WebjarsServlet;
/**
@@ -84,17 +79,7 @@ public class RESTServiceModule extends ServletModule {
bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class);
bind(DecorationService.class);
- // Automatically translate GuacamoleExceptions for REST methods
- bind(RESTExceptionMapper.class);
-
- // Set up the API endpoints
- bind(ExtensionRESTService.class);
- bind(LanguageRESTService.class);
- bind(PatchRESTService.class);
- bind(TokenRESTService.class);
-
// Root-level resources
- bind(SessionRESTService.class);
install(new FactoryModuleBuilder().build(SessionResourceFactory.class));
install(new FactoryModuleBuilder().build(TunnelCollectionResourceFactory.class));
install(new FactoryModuleBuilder().build(TunnelResourceFactory.class));
@@ -108,10 +93,12 @@ public class RESTServiceModule extends ServletModule {
install(new UserModule());
install(new UserGroupModule());
- // Set up the servlet and JSON mappings
- bind(GuiceContainer.class);
- bind(JacksonJsonProvider.class).in(Scopes.SINGLETON);
- serve("/api/*").with(GuiceContainer.class);
+ // Serve REST services using Jersey 2.x
+ bind(ServletContainer.class).in(Scopes.SINGLETON);
+ serve("/api/*").with(ServletContainer.class, Collections.singletonMap(
+ ServletProperties.JAXRS_APPLICATION_CLASS,
+ GuacamoleApplication.class.getName()
+ ));
// Serve Webjar JavaScript dependencies
bind(WebjarsServlet.class).in(Scopes.SINGLETON);
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/RequestSizeFilter.java b/guacamole/src/main/java/org/apache/guacamole/rest/RequestSizeFilter.java
new file mode 100644
index 000000000..f638224ad
--- /dev/null
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/RequestSizeFilter.java
@@ -0,0 +1,108 @@
+/*
+ * 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.rest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Provider;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.environment.Environment;
+import org.apache.guacamole.properties.LongGuacamoleProperty;
+
+/**
+ * Filter which restricts REST API requests to a particular maximum size.
+ */
+@Singleton
+@Provider
+public class RequestSizeFilter implements ContainerRequestFilter {
+
+ /**
+ * Informs the RequestSizeFilter to NOT enforce its request size limits on
+ * requests serviced by the annotated method.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public static @interface DoNotLimit {}
+
+ /**
+ * The default maximum number of bytes to accept within the entity body of
+ * any particular REST request.
+ */
+ private final long DEFAULT_MAX_REQUEST_SIZE = 2097152;
+
+ /**
+ * The maximum number of bytes to accept within the entity body of any
+ * particular REST request. If not specified, requests will be limited to
+ * 2 MB by default. Specifying 0 disables request size limitations.
+ */
+ private final LongGuacamoleProperty API_MAX_REQUEST_SIZE = new LongGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "api-max-request-size"; }
+
+ };
+
+ /**
+ * The Guacamole server environment.
+ */
+ @Inject
+ private Environment environment;
+
+ /**
+ * Information describing the resource that was requested.
+ */
+ @Context
+ private ResourceInfo resourceInfo;
+
+ @Override
+ public void filter(ContainerRequestContext context) throws IOException {
+
+ // Retrieve configured request size limits
+ final long maxRequestSize;
+ try {
+ maxRequestSize = environment.getProperty(API_MAX_REQUEST_SIZE, DEFAULT_MAX_REQUEST_SIZE);
+ }
+ catch (GuacamoleException e) {
+ throw new APIException(e);
+ }
+
+ // Ignore request size if limit is disabled
+ if (maxRequestSize == 0 || resourceInfo.getResourceMethod().isAnnotationPresent(DoNotLimit.class))
+ return;
+
+ // Restrict maximum size of requests which have an input stream
+ // available to be limited
+ InputStream stream = context.getEntityStream();
+ if (stream != null)
+ context.setEntityStream(new LimitedRequestInputStream(stream, maxRequestSize));
+
+ }
+
+}
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java
index 47ba3d42b..514daa124 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java
@@ -19,9 +19,9 @@
package org.apache.guacamole.rest.activeconnection;
-import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
+import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java b/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java
index 5770a079a..a663ab783 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java
@@ -19,10 +19,10 @@
package org.apache.guacamole.rest.auth;
-import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
+import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.GuacamoleException;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/auth/DecorationService.java b/guacamole/src/main/java/org/apache/guacamole/rest/auth/DecorationService.java
index b63b037b3..7537e99ef 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/auth/DecorationService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/auth/DecorationService.java
@@ -19,9 +19,9 @@
package org.apache.guacamole.rest.auth;
-import com.google.inject.Inject;
import java.util.Iterator;
import java.util.List;
+import javax.inject.Inject;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AuthenticatedUser;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/auth/TokenRESTService.java b/guacamole/src/main/java/org/apache/guacamole/rest/auth/TokenRESTService.java
index 887b4f029..427af7f39 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/auth/TokenRESTService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/auth/TokenRESTService.java
@@ -20,10 +20,10 @@
package org.apache.guacamole.rest.auth;
import com.google.common.io.BaseEncoding;
-import com.google.inject.Inject;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java
index 7d4f0d552..cbd7c5e8d 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java
@@ -19,10 +19,10 @@
package org.apache.guacamole.rest.connection;
-import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.util.Map;
+import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
index ce9cb8371..e9b4b225b 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.PATCH;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -44,7 +45,6 @@ import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermission;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
import org.apache.guacamole.rest.APIPatch;
-import org.apache.guacamole.rest.PATCH;
/**
* A REST resource which abstracts the operations available on all Guacamole
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/event/ListenerService.java b/guacamole/src/main/java/org/apache/guacamole/rest/event/ListenerService.java
index e92cc8a66..a2b645b44 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/event/ListenerService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/event/ListenerService.java
@@ -20,7 +20,7 @@
package org.apache.guacamole.rest.event;
import java.util.List;
-import com.google.inject.Inject;
+import javax.inject.Inject;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.event.listener.Listener;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/extension/ExtensionRESTService.java b/guacamole/src/main/java/org/apache/guacamole/rest/extension/ExtensionRESTService.java
index 487bb7c11..49a3e872c 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/extension/ExtensionRESTService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/extension/ExtensionRESTService.java
@@ -19,8 +19,8 @@
package org.apache.guacamole.rest.extension;
-import com.google.inject.Inject;
import java.util.List;
+import javax.inject.Inject;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.apache.guacamole.GuacamoleException;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java b/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java
index c45ae9a81..0fea582e0 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java
@@ -109,10 +109,7 @@ public class APISortPredicate {
// Bail out if sort property is not valid
catch (IllegalArgumentException e) {
- throw new APIException(
- Response.Status.BAD_REQUEST,
- new GuacamoleClientException(String.format("Invalid sort property: \"%s\"", value))
- );
+ throw new APIException(new GuacamoleClientException(String.format("Invalid sort property: \"%s\"", value)));
}
}
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/identifier/RelatedObjectSetResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/identifier/RelatedObjectSetResource.java
index 446b0453e..77b0b4091 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/identifier/RelatedObjectSetResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/identifier/RelatedObjectSetResource.java
@@ -23,13 +23,13 @@ import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.PATCH;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.RelatedObjectSet;
import org.apache.guacamole.rest.APIPatch;
-import org.apache.guacamole.rest.PATCH;
/**
* A REST resource which abstracts the operations available on arbitrary sets
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/language/LanguageRESTService.java b/guacamole/src/main/java/org/apache/guacamole/rest/language/LanguageRESTService.java
index 3f5f32cff..4fccbaef0 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/language/LanguageRESTService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/language/LanguageRESTService.java
@@ -19,8 +19,8 @@
package org.apache.guacamole.rest.language;
-import com.google.inject.Inject;
import java.util.Map;
+import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/patch/PatchRESTService.java b/guacamole/src/main/java/org/apache/guacamole/rest/patch/PatchRESTService.java
index e8e5f003d..115b37c93 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/patch/PatchRESTService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/patch/PatchRESTService.java
@@ -19,12 +19,12 @@
package org.apache.guacamole.rest.patch;
-import com.google.inject.Inject;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java
index 739a39c5e..38b337e0e 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java
@@ -22,6 +22,7 @@ package org.apache.guacamole.rest.permission;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.PATCH;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.guacamole.GuacamoleClientException;
@@ -31,7 +32,6 @@ import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.Permission;
import org.apache.guacamole.net.auth.permission.SystemPermission;
import org.apache.guacamole.rest.APIPatch;
-import org.apache.guacamole.rest.PATCH;
/**
* A REST resource which abstracts the operations available on the permissions
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java
index 6a980f1cd..546026b53 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java
@@ -19,7 +19,7 @@
package org.apache.guacamole.rest.session;
-import com.google.inject.Inject;
+import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java
index 606e78b4d..702ec867d 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java
@@ -19,9 +19,9 @@
package org.apache.guacamole.rest.session;
-import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
+import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java
index edaf9f466..cbb04d172 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java
@@ -21,9 +21,9 @@ package org.apache.guacamole.rest.session;
import org.apache.guacamole.rest.directory.DirectoryResource;
import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
-import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
+import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/StreamResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/StreamResource.java
index 70b2ff026..c33255e3e 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/StreamResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/StreamResource.java
@@ -31,6 +31,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.StreamingOutput;
import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.rest.RequestSizeFilter;
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
/**
@@ -127,6 +128,7 @@ public class StreamResource {
*/
@POST
@Consumes(MediaType.WILDCARD)
+ @RequestSizeFilter.DoNotLimit
public void setStreamContents(InputStream data) throws GuacamoleException {
// Send input over stream
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java
index d4fac136b..abd7b422d 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java
@@ -19,11 +19,11 @@
package org.apache.guacamole.rest.tunnel;
-import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.util.Map;
import java.util.Set;
+import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java
index 74347b721..7c0ec7eef 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java
@@ -19,9 +19,9 @@
package org.apache.guacamole.rest.tunnel;
-import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
+import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java
index fa56b1932..6851701f1 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java
@@ -19,10 +19,10 @@
package org.apache.guacamole.tunnel;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
import java.util.List;
import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.GuacamoleSession;
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/http/RestrictedGuacamoleHTTPTunnelServlet.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/http/RestrictedGuacamoleHTTPTunnelServlet.java
index 4a7ef78cc..39f4a2508 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/http/RestrictedGuacamoleHTTPTunnelServlet.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/http/RestrictedGuacamoleHTTPTunnelServlet.java
@@ -19,11 +19,10 @@
package org.apache.guacamole.tunnel.http;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.tunnel.TunnelRequestService;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.servlet.GuacamoleHTTPTunnelServlet;
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/RestrictedGuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/RestrictedGuacamoleWebSocketTunnelServlet.java
index 237bfbaf8..b9e2d3df6 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/RestrictedGuacamoleWebSocketTunnelServlet.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty8/RestrictedGuacamoleWebSocketTunnelServlet.java
@@ -19,8 +19,8 @@
package org.apache.guacamole.tunnel.websocket.jetty8;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.tunnel.TunnelRequestService;
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/RestrictedGuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/RestrictedGuacamoleWebSocketTunnelServlet.java
index 9497e5460..2b602160a 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/RestrictedGuacamoleWebSocketTunnelServlet.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/jetty9/RestrictedGuacamoleWebSocketTunnelServlet.java
@@ -19,8 +19,8 @@
package org.apache.guacamole.tunnel.websocket.jetty9;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
import org.apache.guacamole.tunnel.TunnelRequestService;
diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/RestrictedGuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/RestrictedGuacamoleWebSocketTunnelServlet.java
index abc28733d..510149527 100644
--- a/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/RestrictedGuacamoleWebSocketTunnelServlet.java
+++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/websocket/tomcat/RestrictedGuacamoleWebSocketTunnelServlet.java
@@ -19,8 +19,8 @@
package org.apache.guacamole.tunnel.websocket.tomcat;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.tunnel.TunnelRequestService;
diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml
index bc067c704..52a52a624 100644
--- a/guacamole/src/main/webapp/WEB-INF/web.xml
+++ b/guacamole/src/main/webapp/WEB-INF/web.xml
@@ -28,7 +28,7 @@
index.html
-
+
guiceFilter
com.google.inject.servlet.GuiceFilter
@@ -37,7 +37,6 @@
guiceFilter
/*
-
org.apache.guacamole.GuacamoleServletContextListener