GUACAMOLE-5: All REST resources MUST be non-generic. Type parameters of generic classes will otherwise be handled as Object by Jersey due to type erasure, resulting in class cast exceptions due to JSON being deserialized as a Map instead of the intended type.

This commit is contained in:
Michael Jumper
2016-07-14 14:37:33 -07:00
parent bd8c37c737
commit cdd71411fb
6 changed files with 157 additions and 12 deletions

View File

@@ -0,0 +1,72 @@
/*
* 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.activeconnection;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
import org.apache.guacamole.rest.directory.DirectoryResource;
/**
* A REST resource which abstracts the operations available on a Directory of
* ActiveConnections.
*
* @author Michael Jumper
*/
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ActiveConnectionDirectoryResource
extends DirectoryResource<ActiveConnection, APIActiveConnection> {
/**
* Creates a new ActiveConnectionDirectoryResource which exposes the
* operations and subresources available for the given ActiveConnection
* Directory.
*
* @param userContext
* The UserContext associated with the given Directory.
*
* @param directory
* The Directory being exposed.
*
* @param translator
* A DirectoryObjectTranslator implementation which handles
* ActiveConnections.
*
* @param resourceFactory
* A factory which can be used to create instances of resources
* representing ActiveConnections.
*/
@AssistedInject
public ActiveConnectionDirectoryResource(@Assisted UserContext userContext,
@Assisted Directory<ActiveConnection> directory,
DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> translator,
DirectoryObjectResourceFactory<ActiveConnection, APIActiveConnection> resourceFactory) {
super(userContext, directory, translator, resourceFactory);
}
}

View File

@@ -27,6 +27,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
import org.apache.guacamole.net.auth.ActiveConnection; import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.rest.directory.DirectoryObjectResource; import org.apache.guacamole.rest.directory.DirectoryObjectResource;
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
import org.apache.guacamole.rest.directory.DirectoryResource;
/** /**
* Guice Module which configures injections required for handling * Guice Module which configures injections required for handling
@@ -41,6 +42,10 @@ public class ActiveConnectionModule extends AbstractModule {
// Create the required DirectoryResourceFactory implementation // Create the required DirectoryResourceFactory implementation
install(new FactoryModuleBuilder() install(new FactoryModuleBuilder()
.implement(
new TypeLiteral<DirectoryResource<ActiveConnection, APIActiveConnection>>() {},
ActiveConnectionDirectoryResource.class
)
.build(new TypeLiteral<DirectoryResourceFactory<ActiveConnection, APIActiveConnection>>() {})); .build(new TypeLiteral<DirectoryResourceFactory<ActiveConnection, APIActiveConnection>>() {}));
// Create the required DirectoryObjectResourceFactory implementation // Create the required DirectoryObjectResourceFactory implementation

View File

@@ -0,0 +1,71 @@
/*
* 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.connection;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
import org.apache.guacamole.rest.directory.DirectoryResource;
/**
* A REST resource which abstracts the operations available on a Directory of
* Connections.
*
* @author Michael Jumper
*/
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ConnectionDirectoryResource
extends DirectoryResource<Connection, APIConnection> {
/**
* Creates a new ConnectionDirectoryResource which exposes the operations
* and subresources available for the given Connection Directory.
*
* @param userContext
* The UserContext associated with the given Directory.
*
* @param directory
* The Directory being exposed.
*
* @param translator
* A DirectoryObjectTranslator implementation which handles
* Connections.
*
* @param resourceFactory
* A factory which can be used to create instances of resources
* representing Connections.
*/
@AssistedInject
public ConnectionDirectoryResource(@Assisted UserContext userContext,
@Assisted Directory<Connection> directory,
DirectoryObjectTranslator<Connection, APIConnection> translator,
DirectoryObjectResourceFactory<Connection, APIConnection> resourceFactory) {
super(userContext, directory, translator, resourceFactory);
}
}

View File

@@ -27,6 +27,7 @@ import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.assistedinject.FactoryModuleBuilder;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
import org.apache.guacamole.rest.directory.DirectoryResource;
/** /**
* Guice Module which configures injections required for handling Connection * Guice Module which configures injections required for handling Connection
@@ -41,6 +42,10 @@ public class ConnectionModule extends AbstractModule {
// Create the required DirectoryResourceFactory implementation // Create the required DirectoryResourceFactory implementation
install(new FactoryModuleBuilder() install(new FactoryModuleBuilder()
.implement(
new TypeLiteral<DirectoryResource<Connection, APIConnection>>() {},
ConnectionDirectoryResource.class
)
.build(new TypeLiteral<DirectoryResourceFactory<Connection, APIConnection>>() {})); .build(new TypeLiteral<DirectoryResourceFactory<Connection, APIConnection>>() {}));
// Create the required DirectoryObjectResourceFactory implementation // Create the required DirectoryObjectResourceFactory implementation

View File

@@ -19,8 +19,6 @@
package org.apache.guacamole.rest.directory; package org.apache.guacamole.rest.directory;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.GET; import javax.ws.rs.GET;
@@ -51,7 +49,7 @@ import org.apache.guacamole.net.auth.Identifiable;
*/ */
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public class DirectoryObjectResource<InternalType extends Identifiable, ExternalType> { public abstract class DirectoryObjectResource<InternalType extends Identifiable, ExternalType> {
/** /**
* The Directory which contains the object represented by this * The Directory which contains the object represented by this
@@ -84,9 +82,7 @@ public class DirectoryObjectResource<InternalType extends Identifiable, External
* A DirectoryObjectTranslator implementation which handles the type of * A DirectoryObjectTranslator implementation which handles the type of
* object given. * object given.
*/ */
@AssistedInject public DirectoryObjectResource(Directory<InternalType> directory, InternalType object,
public DirectoryObjectResource(@Assisted Directory<InternalType> directory,
@Assisted InternalType object,
DirectoryObjectTranslator<InternalType, ExternalType> translator) { DirectoryObjectTranslator<InternalType, ExternalType> translator) {
this.directory = directory; this.directory = directory;
this.object = object; this.object = object;

View File

@@ -19,8 +19,6 @@
package org.apache.guacamole.rest.directory; package org.apache.guacamole.rest.directory;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -69,7 +67,7 @@ import org.apache.guacamole.rest.PATCH;
*/ */
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public class DirectoryResource<InternalType extends Identifiable, ExternalType> { public abstract class DirectoryResource<InternalType extends Identifiable, ExternalType> {
/** /**
* The UserContext associated with the Directory being exposed by this * The UserContext associated with the Directory being exposed by this
@@ -113,9 +111,7 @@ public class DirectoryResource<InternalType extends Identifiable, ExternalType>
* A factory which can be used to create instances of resources * A factory which can be used to create instances of resources
* representing individual objects contained within the given Directory. * representing individual objects contained within the given Directory.
*/ */
@AssistedInject public DirectoryResource(UserContext userContext, Directory<InternalType> directory,
public DirectoryResource(@Assisted UserContext userContext,
@Assisted Directory<InternalType> directory,
DirectoryObjectTranslator<InternalType, ExternalType> translator, DirectoryObjectTranslator<InternalType, ExternalType> translator,
DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory) { DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory) {
this.userContext = userContext; this.userContext = userContext;