diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionGroupService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionGroupService.java index f4954cb32..2e96c54ac 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionGroupService.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionGroupService.java @@ -348,7 +348,7 @@ public class ConnectionGroupService { } /** - * Creates a new connection group having the given name and protocol. + * Creates a new connection group having the given name and type. * * @param name The name to assign to the new connection group. * @param userID The ID of the user who created this connection group. diff --git a/guacamole/nb-configuration.xml b/guacamole/nb-configuration.xml new file mode 100644 index 000000000..4da1f6c9b --- /dev/null +++ b/guacamole/nb-configuration.xml @@ -0,0 +1,18 @@ + + + + + + ide + + diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java index 94deb77e4..d7f31b8d7 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTModule.java @@ -28,6 +28,7 @@ import org.glyptodon.guacamole.net.basic.rest.auth.BasicTokenUserContextMap; import org.glyptodon.guacamole.net.basic.rest.auth.SecureRandomAuthTokenGenerator; import org.glyptodon.guacamole.net.basic.rest.auth.TokenUserContextMap; import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionService; +import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupService; import org.glyptodon.guacamole.properties.GuacamoleProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,6 +66,7 @@ public class RESTModule extends AbstractModule { bind(AuthenticationProvider.class).toInstance(authProvider); bind(TokenUserContextMap.class).toInstance(new BasicTokenUserContextMap()); bind(ConnectionService.class); + bind(ConnectionGroupService.class); bind(AuthenticationService.class); bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java index d11992563..ccb85adbf 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java @@ -24,6 +24,7 @@ import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import org.codehaus.jackson.jaxrs.JacksonJsonProvider; import org.glyptodon.guacamole.net.basic.rest.auth.LoginRESTService; import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionRESTService; +import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupRESTService; /** * A Guice Module to set up the servlet mappings for the Guacamole REST API. @@ -37,6 +38,7 @@ public class RESTServletModule extends ServletModule { // Set up the API endpoints bind(ConnectionRESTService.class); + bind(ConnectionGroupRESTService.class); bind(LoginRESTService.class); // Set up the servlet and JSON mappings diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionRESTService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionRESTService.java index c1ddc1e1c..acfca2b1a 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionRESTService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionRESTService.java @@ -250,7 +250,7 @@ public class ConnectionRESTService { * * @param authToken The authentication token that is used to authenticate * the user performing the operation. - * @param connectionID The ID of the Connection to delete. + * @param connectionID The ID of the Connection to move. * @param connection The connection to update. */ @POST @@ -289,7 +289,7 @@ public class ConnectionRESTService { * * @param authToken The authentication token that is used to authenticate * the user performing the operation. - * @param connectionID The ID of the Connection to delete. + * @param connectionID The ID of the Connection to move. * @param parentID The ID of the ConnectionGroup the connections * belong to. If null, the root connection group will be used. */ @@ -312,11 +312,8 @@ public class ConnectionRESTService { if(parentConnectionGroup == null) throw new GuacamoleClientException("No ConnectionGroup found with the provided parentID."); - // Make sure the connection is there before trying to delete - if(connectionDirectory.get(connectionID) == null) - throw new GuacamoleClientException("No Connection found with the provided ID."); - // Move the connection + connectionDirectory.move(connectionID, parentConnectionGroup.getConnectionDirectory()); } catch(GuacamoleSecurityException e) { throw new HTTPException(Status.UNAUTHORIZED, e.getMessage() != null ? e.getMessage() : "Permission denied."); } catch(GuacamoleClientException e) { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/APIConnectionGroup.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/APIConnectionGroup.java new file mode 100644 index 000000000..0dfbc177f --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/APIConnectionGroup.java @@ -0,0 +1,110 @@ +package org.glyptodon.guacamole.net.basic.rest.connectiongroup; + +import org.glyptodon.guacamole.net.auth.ConnectionGroup; +import org.glyptodon.guacamole.net.auth.ConnectionGroup.Type; + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * A simple connection group to expose through the REST endpoints. + * + * @author James Muehlner + */ +public class APIConnectionGroup { + + /** + * The name of this connection group. + */ + private String name; + + /** + * The identifier of this connection group. + */ + private String identifier; + + /** + * The type of this connection group. + */ + private Type type; + + /** + * Create an empty APIConnectionGroup. + */ + public APIConnectionGroup() {} + + /** + * Create a new APIConnectionGroup from the given ConnectionGroup record. + * + * @param connectionGroup The ConnectionGroup record to initialize this + * APIConnectionGroup from. + */ + public APIConnectionGroup(ConnectionGroup connectionGroup) { + this.identifier = connectionGroup.getIdentifier(); + this.name = connectionGroup.getName(); + this.type = connectionGroup.getType(); + } + + /** + * Returns the name of this connection group. + * @return The name of this connection group. + */ + public String getName() { + return name; + } + + /** + * Set the name of this connection group. + * @param name The name of this connection group. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns the identifier of this connection group. + * @return The identifier of this connection group. + */ + public String getIdentifier() { + return identifier; + } + + /** + * Set the identifier of this connection group. + * @param identifier The identifier of this connection group. + */ + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * Returns the type of this connection group. + * @return The type of this connection group. + */ + public Type getType() { + return type; + } + + /** + * Set the type of this connection group. + * @param type The Type of this connection group. + */ + public void setType(Type type) { + this.type = type; + } +} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/APIConnectionGroupWrapper.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/APIConnectionGroupWrapper.java new file mode 100644 index 000000000..c61d3812e --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/APIConnectionGroupWrapper.java @@ -0,0 +1,95 @@ +package org.glyptodon.guacamole.net.basic.rest.connectiongroup; + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.net.GuacamoleSocket; +import org.glyptodon.guacamole.net.auth.Connection; +import org.glyptodon.guacamole.net.auth.ConnectionGroup; +import org.glyptodon.guacamole.net.auth.Directory; +import org.glyptodon.guacamole.protocol.GuacamoleClientInformation; + +/** + * A wrapper to make an APIConnection look like a ConnectionGroup. + * Useful where a org.glyptodon.guacamole.net.auth.ConnectionGroup is required. + * + * @author James Muehlner + */ +public class APIConnectionGroupWrapper implements ConnectionGroup { + + /** + * The wrapped APIConnectionGroup. + */ + private APIConnectionGroup apiConnectionGroup; + + /** + * Create a new APIConnectionGroupWrapper to wrap the given + * APIConnectionGroup as a ConnectionGroup. + * @param apiConnectionGroup the APIConnectionGroup to wrap. + */ + public APIConnectionGroupWrapper(APIConnectionGroup apiConnectionGroup) { + this.apiConnectionGroup = apiConnectionGroup; + } + + @Override + public String getName() { + return apiConnectionGroup.getName(); + } + + @Override + public void setName(String name) { + apiConnectionGroup.setName(name); + } + + @Override + public String getIdentifier() { + return apiConnectionGroup.getIdentifier(); + } + + @Override + public void setIdentifier(String identifier) { + apiConnectionGroup.setIdentifier(identifier); + } + + @Override + public void setType(Type type) { + apiConnectionGroup.setType(type); + } + + @Override + public Type getType() { + return apiConnectionGroup.getType(); + } + + @Override + public Directory getConnectionDirectory() throws GuacamoleException { + throw new UnsupportedOperationException("Operation not supported."); + } + + @Override + public Directory getConnectionGroupDirectory() throws GuacamoleException { + throw new UnsupportedOperationException("Operation not supported."); + } + + @Override + public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException { + throw new UnsupportedOperationException("Operation not supported."); + } + +} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java new file mode 100644 index 000000000..825fdd290 --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java @@ -0,0 +1,326 @@ +package org.glyptodon.guacamole.net.basic.rest.connectiongroup; + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import com.google.inject.Inject; +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response.Status; +import org.glyptodon.guacamole.GuacamoleClientException; +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.GuacamoleSecurityException; +import org.glyptodon.guacamole.net.auth.ConnectionGroup; +import org.glyptodon.guacamole.net.auth.Directory; +import org.glyptodon.guacamole.net.auth.UserContext; +import org.glyptodon.guacamole.net.basic.rest.HTTPException; +import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A REST Service for handling connection group CRUD operations. + * + * @author James Muehlner + */ +@Path("/api/connectionGroup") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class ConnectionGroupRESTService { + + /** + * Logger for this class. + */ + private static final Logger logger = LoggerFactory.getLogger(ConnectionGroupRESTService.class); + + /** + * A service for authenticating users from auth tokens. + */ + @Inject + private AuthenticationService authenticationService; + + /** + * A service for managing the REST endpoint APIConnection objects. + */ + @Inject + private ConnectionGroupService connectionGroupService; + + /** + * Gets a list of connection groups with the given ConnectionGroup parentID. + * If no parentID is provided, returns the connection groups from the root group. + * + * @param authToken The authentication token that is used to authenticate + * the user performing the operation. + * @param parentID The ID of the ConnectionGroup the connection groups + * belong to. If null, the root connection group will be used. + * @return The connection list. + */ + @GET + public List getConnectionGroups(@QueryParam("token") String authToken, @QueryParam("parentID") String parentID) { + UserContext userContext = authenticationService.getUserContextFromAuthToken(authToken); + + try { + // If the parent connection group is passed in, try to find it. + ConnectionGroup parentConnectionGroup; + if(parentID == null) + parentConnectionGroup = userContext.getRootConnectionGroup(); + else { + ConnectionGroup rootGroup = userContext.getRootConnectionGroup(); + Directory connectionGroupDirectory = rootGroup.getConnectionGroupDirectory(); + parentConnectionGroup = connectionGroupDirectory.get(parentID); + } + + if(parentConnectionGroup == null) + throw new GuacamoleClientException("No ConnectionGroup found with the provided parentID."); + + Directory connectionGroupDirectory = + parentConnectionGroup.getConnectionGroupDirectory(); + + // Get the list of connection group names + List connectionGroups = new ArrayList(); + Iterable identifiers = connectionGroupDirectory.getIdentifiers(); + + // Get the connection group for each name + for(String identifier : identifiers) + connectionGroups.add(connectionGroupDirectory.get(identifier)); + + return connectionGroupService.convertConnectionGroupList(connectionGroups); + } catch(GuacamoleSecurityException e) { + throw new HTTPException(Status.UNAUTHORIZED, e.getMessage() != null ? e.getMessage() : "Permission denied."); + } catch(GuacamoleClientException e) { + throw new HTTPException(Status.BAD_REQUEST, e.getMessage() != null ? e.getMessage() : "Invalid Request."); + } catch(GuacamoleException e) { + logger.error("Unexpected GuacamoleException caught while listing connection groups.", e); + throw new HTTPException(Status.INTERNAL_SERVER_ERROR, e.getMessage() != null ? e.getMessage() : "Unexpected server error."); + } + } + + /** + * Gets an individual connection group. + * + * @param authToken The authentication token that is used to authenticate + * the user performing the operation. + * @param connectionGroupID The ID of the ConnectionGroup. + * @return The connection group. + */ + @GET + @Path("/{connectionGroupID}") + public APIConnectionGroup getConnectionGroup(@QueryParam("token") String authToken, + @PathParam("connectionGroupID") String connectionGroupID) { + UserContext userContext = authenticationService.getUserContextFromAuthToken(authToken); + + try { + // Get the connection group directory + ConnectionGroup rootGroup = userContext.getRootConnectionGroup(); + Directory connectionGroupDirectory = + rootGroup.getConnectionGroupDirectory(); + + // Get the connection group + ConnectionGroup connectionGroup = connectionGroupDirectory.get(connectionGroupID); + + if(connectionGroup == null) + throw new GuacamoleClientException("No ConnectionGroup found with the provided ID."); + + return new APIConnectionGroup(connectionGroup); + } catch(GuacamoleSecurityException e) { + throw new HTTPException(Status.UNAUTHORIZED, e.getMessage() != null ? e.getMessage() : "Permission denied."); + } catch(GuacamoleClientException e) { + throw new HTTPException(Status.BAD_REQUEST, e.getMessage() != null ? e.getMessage() : "Invalid Request."); + } catch(GuacamoleException e) { + logger.error("Unexpected GuacamoleException caught while getting connection group.", e); + throw new HTTPException(Status.INTERNAL_SERVER_ERROR, e.getMessage() != null ? e.getMessage() : "Unexpected server error."); + } + } + + /** + * Deletes an individual connection group. + * + * @param authToken The authentication token that is used to authenticate + * the user performing the operation. + * @param connectionGroupID The ID of the ConnectionGroup to delete. + */ + @DELETE + @Path("/{connectionGroupID}") + public void deleteConnectionGroup(@QueryParam("token") String authToken, @PathParam("connectionGroupID") String connectionGroupID) { + UserContext userContext = authenticationService.getUserContextFromAuthToken(authToken); + + try { + // Get the connection group directory + ConnectionGroup rootGroup = userContext.getRootConnectionGroup(); + Directory connectionGroupDirectory = + rootGroup.getConnectionGroupDirectory(); + + // Make sure the connection is there before trying to delete + if(connectionGroupDirectory.get(connectionGroupID) == null) + throw new GuacamoleClientException("No Connection found with the provided ID."); + + // Delete the connection group + connectionGroupDirectory.remove(connectionGroupID); + } catch(GuacamoleSecurityException e) { + throw new HTTPException(Status.UNAUTHORIZED, e.getMessage() != null ? e.getMessage() : "Permission denied."); + } catch(GuacamoleClientException e) { + throw new HTTPException(Status.BAD_REQUEST, e.getMessage() != null ? e.getMessage() : "Invalid Request."); + } catch(GuacamoleException e) { + logger.error("Unexpected GuacamoleException caught while deleting connection group.", e); + throw new HTTPException(Status.INTERNAL_SERVER_ERROR, e.getMessage() != null ? e.getMessage() : "Unexpected server error."); + } + } + + /** + * Creates a new connection group and returns the identifier of the new connection group. + * If a parentID is provided, the connection group will be created in the + * connection group with the parentID. Otherwise, the root connection group + * will be used. + * + * @param authToken The authentication token that is used to authenticate + * the user performing the operation. + * @param parentID The ID of the ConnectionGroup the connection groups + * belong to. If null, the root connection group will be used. + * @param connection The connection group to create. + * @return The identifier of the new connection group. + */ + @POST + public String createConnectionGroup(@QueryParam("token") String authToken, + @QueryParam("parentID") String parentID, APIConnectionGroup connectionGroup) { + UserContext userContext = authenticationService.getUserContextFromAuthToken(authToken); + + try { + if(connectionGroup == null) + throw new GuacamoleClientException("A connection group is required for this request."); + + // If the parent connection group is passed in, try to find it. + ConnectionGroup parentConnectionGroup; + if(parentID == null) + parentConnectionGroup = userContext.getRootConnectionGroup(); + else { + ConnectionGroup rootGroup = userContext.getRootConnectionGroup(); + Directory connectionGroupDirectory = rootGroup.getConnectionGroupDirectory(); + parentConnectionGroup = connectionGroupDirectory.get(parentID); + } + + if(parentConnectionGroup == null) + throw new GuacamoleClientException("No ConnectionGroup found with the provided parentID."); + + Directory connectionGroupDirectory = + parentConnectionGroup.getConnectionGroupDirectory(); + + // Create the connection group + connectionGroupDirectory.add(new APIConnectionGroupWrapper(connectionGroup)); + + // Return the new connection group identifier + return connectionGroup.getIdentifier(); + } catch(GuacamoleSecurityException e) { + throw new HTTPException(Status.UNAUTHORIZED, e.getMessage() != null ? e.getMessage() : "Permission denied."); + } catch(GuacamoleClientException e) { + throw new HTTPException(Status.BAD_REQUEST, e.getMessage() != null ? e.getMessage() : "Invalid Request."); + } catch(GuacamoleException e) { + logger.error("Unexpected GuacamoleException caught while creating connection.", e); + throw new HTTPException(Status.INTERNAL_SERVER_ERROR, e.getMessage() != null ? e.getMessage() : "Unexpected server error."); + } + } + + /** + * Updates a connection group. + * + * @param authToken The authentication token that is used to authenticate + * the user performing the operation. + * @param connectionID The ID of the ConnectionGroup to update. + * @param connection The connection group to update. + */ + @POST + @Path("/{connectionGroupID}") + public void updateConnectionGroup(@QueryParam("token") String authToken, + @PathParam("connectionGroupID") String connectionGroupID, APIConnectionGroup connectionGroup) { + UserContext userContext = authenticationService.getUserContextFromAuthToken(authToken); + + try { + if(connectionGroup == null) + throw new GuacamoleClientException("A connection is required for this request."); + + // Get the connection directory + ConnectionGroup rootGroup = userContext.getRootConnectionGroup(); + Directory connectionGroupDirectory = + rootGroup.getConnectionGroupDirectory(); + + // Make sure the connection group is there before trying to update + if(connectionGroupDirectory.get(connectionGroupID) == null) + throw new GuacamoleClientException("No ConnectionGroup with the provided ID."); + + // Update the connection group + connectionGroupDirectory.update(new APIConnectionGroupWrapper(connectionGroup)); + } catch(GuacamoleSecurityException e) { + throw new HTTPException(Status.UNAUTHORIZED, e.getMessage() != null ? e.getMessage() : "Permission denied."); + } catch(GuacamoleClientException e) { + throw new HTTPException(Status.BAD_REQUEST, e.getMessage() != null ? e.getMessage() : "Invalid Request."); + } catch(GuacamoleException e) { + logger.error("Unexpected GuacamoleException caught updating connection.", e); + throw new HTTPException(Status.INTERNAL_SERVER_ERROR, e.getMessage() != null ? e.getMessage() : "Unexpected server error."); + } + } + + /** + * Moves an individual connection group to a different connection group. + * + * @param authToken The authentication token that is used to authenticate + * the user performing the operation. + * @param connectionID The ID of the ConnectionGroup to move. + * @param parentID The ID of the ConnectionGroup the connection groups + * belong to. If null, the root connection group will be used. + */ + @PUT + @Path("/{connectionGroupID}") + public void moveConnectionGroup(@QueryParam("token") String authToken, + @PathParam("connectionGroupID") String connectionGroupID, @QueryParam("parentID") String parentID) { + UserContext userContext = authenticationService.getUserContextFromAuthToken(authToken); + + try { + // Get the connection group directory + ConnectionGroup rootGroup = userContext.getRootConnectionGroup(); + Directory connectionGroupDirectory = + rootGroup.getConnectionGroupDirectory(); + + // Find the new parent connection group + Directory newConnectionGroupDirectory = rootGroup.getConnectionGroupDirectory(); + ConnectionGroup parentConnectionGroup = newConnectionGroupDirectory.get(parentID); + + if(newConnectionGroupDirectory == null) + throw new GuacamoleClientException("No ConnectionGroup found with the provided parentID."); + + // Move the connection + connectionGroupDirectory.move(connectionGroupID, parentConnectionGroup.getConnectionGroupDirectory()); + } catch(GuacamoleSecurityException e) { + throw new HTTPException(Status.UNAUTHORIZED, e.getMessage() != null ? e.getMessage() : "Permission denied."); + } catch(GuacamoleClientException e) { + throw new HTTPException(Status.BAD_REQUEST, e.getMessage() != null ? e.getMessage() : "Invalid Request."); + } catch(GuacamoleException e) { + logger.error("Unexpected GuacamoleException caught moving connection.", e); + throw new HTTPException(Status.INTERNAL_SERVER_ERROR, e.getMessage() != null ? e.getMessage() : "Unexpected server error."); + } + } + +} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupService.java new file mode 100644 index 000000000..f16241f6c --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupService.java @@ -0,0 +1,50 @@ +package org.glyptodon.guacamole.net.basic.rest.connectiongroup; + +import java.util.ArrayList; +import java.util.List; +import org.glyptodon.guacamole.net.auth.Connection; +import org.glyptodon.guacamole.net.auth.ConnectionGroup; + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * A service for performing useful manipulations on REST ConnectionGroups. + * + * @author James Muehlner + */ +public class ConnectionGroupService { + + /** + * Converts a list of ConnectionGroup to a list of APIConnectionGroup + * objects for exposing with the REST endpoints. + * + * @param connectionGroups The ConnectionGroup to convert for REST endpoint use. + * @return A List of APIConnectionGroup objects for use with the REST endpoint. + */ + public List convertConnectionGroupList( + List connectionGroups) { + List restConnectionGroups = new ArrayList(); + + for(ConnectionGroup connectionGroup : connectionGroups) { + restConnectionGroups.add(new APIConnectionGroup(connectionGroup)); + } + + return restConnectionGroups; + } +} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/package-info.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/package-info.java new file mode 100644 index 000000000..9b0a3cf17 --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/package-info.java @@ -0,0 +1,7 @@ + +/** + * Classes related to the connection group manipulation aspect + * of the Guacamole REST API. + */ +package org.glyptodon.guacamole.net.basic.rest.connectiongroup; + diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml index 452f763a5..950848b6f 100644 --- a/guacamole/src/main/webapp/WEB-INF/web.xml +++ b/guacamole/src/main/webapp/WEB-INF/web.xml @@ -256,16 +256,6 @@ org.glyptodon.guacamole.net.basic.rest.RESTServletContextListener - - com.sun.jersey.api.json.POJOMappingFeature - true - - - - com.sun.jersey.config.property.packages - org.codehaus.jackson.jaxrs - - mp3 audio/mpeg