diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/ConnectionGroupUtility.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/ConnectionGroupUtility.java
new file mode 100644
index 000000000..9ea13973a
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/ConnectionGroupUtility.java
@@ -0,0 +1,67 @@
+
+/*
+ * 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 .
+ */
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.UserContext;
+
+/**
+ * A class that provides helper methods for the ConnectionGroup CRUD servlets.
+ *
+ * @author James Muehlner
+ */
+class ConnectionGroupUtility {
+
+ // This class should not be instantiated
+ private ConnectionGroupUtility() {}
+
+ /**
+ * Get the ConnectionGroupDirectory with the parent connection group
+ * specified by parentID.
+ *
+ * @param context The UserContext to search for the connectionGroup directory.
+ * @param parentID The ID of the parent connection group to search for.
+ *
+ * @return The ConnectionGroupDirectory with the parent connection group,
+ * if found.
+ * @throws GuacamoleException If an error is encountered while getting the
+ * connection group directory.
+ */
+ static Directory findConnectionGroupDirectory(
+ UserContext context, String parentID) throws GuacamoleException {
+
+ // Find the correct connection group directory
+ ConnectionGroup rootGroup = context.getRootConnectionGroup();
+ Directory directory;
+
+ Directory connectionGroupDirectory =
+ rootGroup.getConnectionGroupDirectory();
+
+ ConnectionGroup parentGroup = connectionGroupDirectory.get(parentID);
+
+ if(parentGroup == null)
+ return null;
+
+ directory = parentGroup.getConnectionGroupDirectory();
+
+ return directory;
+ }
+}
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Create.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Create.java
new file mode 100644
index 000000000..61fee7de7
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Create.java
@@ -0,0 +1,71 @@
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
+/*
+ * 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 javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.UserContext;
+import net.sourceforge.guacamole.net.basic.AuthenticatingHttpServlet;
+
+/**
+ * Simple HttpServlet which handles connection group creation.
+ *
+ * @author James Muehlner
+ */
+public class Create extends AuthenticatingHttpServlet {
+
+ /**
+ * Prefix given to a parameter name when that parameter is a protocol-
+ * specific parameter meant for the configuration.
+ */
+ public static final String PARAMETER_PREFIX = "_";
+
+ @Override
+ protected void authenticatedService(
+ UserContext context,
+ HttpServletRequest request, HttpServletResponse response)
+ throws GuacamoleException {
+
+ // Get name
+ String name = request.getParameter("name");
+
+ // Get the ID of the parent connection group
+ String parentID = request.getParameter("parentID");
+
+ // Find the correct connection group directory
+ Directory directory =
+ ConnectionGroupUtility.findConnectionGroupDirectory(context, parentID);
+
+ if(directory == null)
+ throw new GuacamoleException("Connection group directory not found.");
+
+ // Create connection skeleton
+ ConnectionGroup connectionGroup = new DummyConnectionGroup();
+ connectionGroup.setName(name);
+
+ // Add connection
+ directory.add(connectionGroup);
+
+ }
+
+}
+
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Delete.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Delete.java
new file mode 100644
index 000000000..d2f9f3ac5
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Delete.java
@@ -0,0 +1,56 @@
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
+/*
+ * 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 javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.UserContext;
+import net.sourceforge.guacamole.net.basic.AuthenticatingHttpServlet;
+
+/**
+ * Simple HttpServlet which handles connection group deletion.
+ *
+ * @author Michael Jumper
+ */
+public class Delete extends AuthenticatingHttpServlet {
+
+ @Override
+ protected void authenticatedService(
+ UserContext context,
+ HttpServletRequest request, HttpServletResponse response)
+ throws GuacamoleException {
+
+ // Get ID
+ String identifier = request.getParameter("id");
+
+ // Attempt to get connection group directory
+ Directory directory =
+ context.getRootConnectionGroup().getConnectionGroupDirectory();
+
+ // Remove connection
+ directory.remove(identifier);
+
+
+ }
+
+}
+
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/DummyConnectionGroup.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/DummyConnectionGroup.java
new file mode 100644
index 000000000..abc0cf202
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/DummyConnectionGroup.java
@@ -0,0 +1,39 @@
+
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.GuacamoleSocket;
+import net.sourceforge.guacamole.net.auth.AbstractConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Connection;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.protocol.GuacamoleClientInformation;
+
+/**
+ * Basic ConnectionGroup skeleton, providing a means of storing Connection data
+ * prior to CRUD operations. This ConnectionGroup has no functionality for actually
+ * performing a connection operation, and does not promote any of the
+ * semantics that would otherwise be present because of the authentication
+ * provider. It is up to the authentication provider to create a new
+ * ConnectionGroup based on the information contained herein.
+ *
+ * @author James Muehlner
+ */
+public class DummyConnectionGroup extends AbstractConnectionGroup {
+
+ @Override
+ public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException {
+ throw new UnsupportedOperationException("Connection unsupported in DummyConnectionGroup.");
+ }
+
+ @Override
+ public Directory getConnectionDirectory() throws GuacamoleException {
+ throw new UnsupportedOperationException("Connection directory unsupported in DummyConnectionGroup.");
+ }
+
+ @Override
+ public Directory getConnectionGroupDirectory() throws GuacamoleException {
+ throw new UnsupportedOperationException("Connection group directory unsuppprted in DummyConnectionGroup.");
+ }
+
+}
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/List.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/List.java
new file mode 100644
index 000000000..5d75991af
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/List.java
@@ -0,0 +1,214 @@
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
+/*
+ * 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 java.io.IOException;
+import java.util.Set;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.GuacamoleSecurityException;
+import net.sourceforge.guacamole.GuacamoleServerException;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.User;
+import net.sourceforge.guacamole.net.auth.UserContext;
+import net.sourceforge.guacamole.net.auth.permission.ConnectionPermission;
+import net.sourceforge.guacamole.net.auth.permission.ObjectPermission;
+import net.sourceforge.guacamole.net.auth.permission.Permission;
+import net.sourceforge.guacamole.net.auth.permission.SystemPermission;
+import net.sourceforge.guacamole.net.basic.AuthenticatingHttpServlet;
+
+/**
+ * Simple HttpServlet which outputs XML containing a list of all authorized
+ * connection groups for the current user.
+ *
+ * @author Michael Jumper
+ */
+public class List extends AuthenticatingHttpServlet {
+
+ /**
+ * System administration permission.
+ */
+ private static final Permission SYSTEM_PERMISSION =
+ new SystemPermission(SystemPermission.Type.ADMINISTER);
+
+
+ /**
+ * Checks whether the given user has permission to perform the given
+ * object operation. Security exceptions are handled appropriately - only
+ * non-security exceptions pass through.
+ *
+ * @param user The user whose permissions should be verified.
+ * @param type The type of operation to check for permission for.
+ * @param identifier The identifier of the connection the operation
+ * would be performed upon.
+ * @return true if permission is granted, false otherwise.
+ *
+ * @throws GuacamoleException If an error occurs while checking permissions.
+ */
+ private boolean hasConfigPermission(User user, ObjectPermission.Type type,
+ String identifier)
+ throws GuacamoleException {
+
+ // Build permission
+ Permission permission = new ConnectionPermission(
+ type,
+ identifier
+ );
+
+ try {
+ // Return result of permission check, if possible
+ return user.hasPermission(permission);
+ }
+ catch (GuacamoleSecurityException e) {
+ // If cannot check due to security restrictions, no permission
+ return false;
+ }
+
+ }
+
+ /**
+ * Writes the XML for the given connection group.
+ *
+ * @param self The user whose permissions dictate the availability of the
+ * data written.
+ * @param xml The XMLStremWriter to use when writing the data.
+ * @param group The connection group whose XML representation will be
+ * written.
+ * @throws GuacamoleException If an error occurs while reading the
+ * requested data.
+ * @throws XMLStreamException If an error occurs while writing the XML.
+ */
+ private void writeConnectionGroup(User self, XMLStreamWriter xml,
+ ConnectionGroup group) throws GuacamoleException, XMLStreamException {
+
+ // Write group
+ xml.writeStartElement("group");
+ xml.writeAttribute("id", group.getIdentifier());
+ xml.writeAttribute("name", group.getName());
+
+ // Write group type
+ switch (group.getType()) {
+
+ case ORGANIZATIONAL:
+ xml.writeAttribute("type", "organizational");
+ break;
+
+ case BALANCING:
+ xml.writeAttribute("type", "balancing");
+ break;
+
+ }
+
+ // Write contained connection groups
+ writeConnectionGroups(self, xml, group.getConnectionGroupDirectory());
+
+ // End of group
+ xml.writeEndElement();
+
+ }
+
+ /**
+ * Writes the XML for the given directory of connection groups.
+ *
+ * @param self The user whose permissions dictate the availability of the
+ * data written.
+ * @param xml The XMLStremWriter to use when writing the data.
+ * @param directory The directory whose XML representation will be
+ * written.
+ * @throws GuacamoleException If an error occurs while reading the
+ * requested data.
+ * @throws XMLStreamException If an error occurs while writing the XML.
+ */
+ private void writeConnectionGroups(User self, XMLStreamWriter xml,
+ Directory directory)
+ throws GuacamoleException, XMLStreamException {
+
+ // If no connections, write nothing
+ Set identifiers = directory.getIdentifiers();
+ if (identifiers.isEmpty())
+ return;
+
+ // Begin connections
+ xml.writeStartElement("groups");
+
+ // For each entry, write corresponding connection element
+ for (String identifier : identifiers) {
+
+ // Write each group
+ ConnectionGroup group = directory.get(identifier);
+ writeConnectionGroup(self, xml, group);
+
+ }
+
+ // End connections
+ xml.writeEndElement();
+
+ }
+
+ @Override
+ protected void authenticatedService(
+ UserContext context,
+ HttpServletRequest request, HttpServletResponse response)
+ throws GuacamoleException {
+
+ // Do not cache
+ response.setHeader("Cache-Control", "no-cache");
+
+ // Write XML content type
+ response.setHeader("Content-Type", "text/xml");
+
+ // Set encoding
+ response.setCharacterEncoding("UTF-8");
+
+ // Get root group
+ ConnectionGroup root = context.getRootConnectionGroup();
+
+ // Write actual XML
+ try {
+
+ // Get self
+ User self = context.self();
+
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ XMLStreamWriter xml = outputFactory.createXMLStreamWriter(response.getWriter());
+
+ // Write content of root group
+ xml.writeStartDocument();
+ writeConnectionGroup(self, xml, root);
+ xml.writeEndDocument();
+
+ }
+ catch (XMLStreamException e) {
+ throw new GuacamoleServerException(
+ "Unable to write connection group list XML.", e);
+ }
+ catch (IOException e) {
+ throw new GuacamoleServerException(
+ "I/O error writing connection group list XML.", e);
+ }
+
+ }
+
+}
+
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Move.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Move.java
new file mode 100644
index 000000000..09acd2312
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Move.java
@@ -0,0 +1,68 @@
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
+/*
+ * 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 javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.UserContext;
+import net.sourceforge.guacamole.net.basic.AuthenticatingHttpServlet;
+
+/**
+ * Simple HttpServlet which handles moving connection groups.
+ *
+ * @author James Muehlner
+ */
+public class Move extends AuthenticatingHttpServlet {
+
+ /**
+ * Prefix given to a parameter name when that parameter is a protocol-
+ * specific parameter meant for the configuration.
+ */
+ public static final String PARAMETER_PREFIX = "_";
+
+ @Override
+ protected void authenticatedService(
+ UserContext context,
+ HttpServletRequest request, HttpServletResponse response)
+ throws GuacamoleException {
+
+ // Get ID
+ String identifier = request.getParameter("id");
+
+ // Get the identifier of the new parent connection group
+ String parentID = request.getParameter("parentID");
+
+ // Attempt to get the new parent connection group directory
+ Directory newParentDirectory =
+ ConnectionGroupUtility.findConnectionGroupDirectory(context, parentID);
+
+ // Attempt to get root connection group directory
+ Directory directory =
+ context.getRootConnectionGroup().getConnectionGroupDirectory();
+
+ // Move connection group
+ directory.move(identifier, newParentDirectory);
+
+ }
+
+}
+
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Update.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Update.java
new file mode 100644
index 000000000..2e7aa794b
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/Update.java
@@ -0,0 +1,66 @@
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
+/*
+ * 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 javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.UserContext;
+import net.sourceforge.guacamole.net.basic.AuthenticatingHttpServlet;
+
+/**
+ * Simple HttpServlet which handles connection group update.
+ *
+ * @author James Muehlner
+ */
+public class Update extends AuthenticatingHttpServlet {
+
+ /**
+ * Prefix given to a parameter name when that parameter is a protocol-
+ * specific parameter meant for the configuration.
+ */
+ public static final String PARAMETER_PREFIX = "_";
+
+ @Override
+ protected void authenticatedService(
+ UserContext context,
+ HttpServletRequest request, HttpServletResponse response)
+ throws GuacamoleException {
+
+ // Get ID, name, and protocol
+ String identifier = request.getParameter("id");
+ String name = request.getParameter("name");
+
+ // Attempt to get connection group directory
+ Directory directory =
+ context.getRootConnectionGroup().getConnectionGroupDirectory();
+
+ // Create connection group skeleton
+ ConnectionGroup connectionGroup = directory.get(identifier);
+ connectionGroup.setName(name);
+
+ // Update connection group
+ directory.update(connectionGroup);
+
+ }
+
+}
+
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/package-info.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/package-info.java
new file mode 100644
index 000000000..6cb070963
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connectiongroups/package-info.java
@@ -0,0 +1,6 @@
+
+/**
+ * Servlets dedicated to CRUD operations related to ConnectionGroups.
+ */
+package net.sourceforge.guacamole.net.basic.crud.connectiongroups;
+
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/ConnectionUtility.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/ConnectionUtility.java
new file mode 100644
index 000000000..63ff3f42a
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/ConnectionUtility.java
@@ -0,0 +1,68 @@
+
+/*
+ * 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 .
+ */
+package net.sourceforge.guacamole.net.basic.crud.connections;
+
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.auth.Connection;
+import net.sourceforge.guacamole.net.auth.ConnectionGroup;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.UserContext;
+
+/**
+ * A class that provides helper methods for the Connection CRUD servlets.
+ *
+ * @author James Muehlner
+ */
+class ConnectionUtility {
+
+ // This class should not be instantiated
+ private ConnectionUtility() {}
+
+ /**
+ * Get the ConnectionDirectory with the parent connection group specified by
+ * parentID.
+ *
+ * @param context The UserContext to search for the connection directory.
+ * @param parentID The ID of the parent connection group to search for.
+ *
+ * @return The ConnectionDirectory with the parent connection group,
+ * if found.
+ * @throws GuacamoleException If an error is encountered while getting the
+ * connection directory.
+ */
+ static Directory findConnectionDirectory(
+ UserContext context, String parentID) throws GuacamoleException {
+
+ // Find the correct connection directory
+ ConnectionGroup rootGroup = context.getRootConnectionGroup();
+ Directory directory;
+
+ Directory connectionGroupDirectory =
+ rootGroup.getConnectionGroupDirectory();
+
+ ConnectionGroup parentGroup = connectionGroupDirectory.get(parentID);
+
+ if(parentGroup == null)
+ return null;
+
+ directory = parentGroup.getConnectionDirectory();
+
+ return directory;
+ }
+}
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/Create.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/Create.java
index d5557fb1c..69b424d8f 100644
--- a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/Create.java
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/Create.java
@@ -50,10 +50,16 @@ public class Create extends AuthenticatingHttpServlet {
// Get name and protocol
String name = request.getParameter("name");
String protocol = request.getParameter("protocol");
+
+ // Get the ID of the parent connection group
+ String parentID = request.getParameter("parentID");
- // Attempt to get connection directory
- Directory directory =
- context.getRootConnectionGroup().getConnectionDirectory();
+ // Find the correct connection directory
+ Directory directory =
+ ConnectionUtility.findConnectionDirectory(context, parentID);
+
+ if(directory == null)
+ throw new GuacamoleException("Connection directory not found.");
// Create config
GuacamoleConfiguration config = new GuacamoleConfiguration();
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/DummyConnection.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/DummyConnection.java
index 7bd4492a8..a9f9d8a83 100644
--- a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/DummyConnection.java
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/DummyConnection.java
@@ -22,12 +22,12 @@ public class DummyConnection extends AbstractConnection {
@Override
public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException {
- throw new UnsupportedOperationException("Connection unsuppported in DummyConnection.");
+ throw new UnsupportedOperationException("Connection unsupported in DummyConnection.");
}
@Override
public List getHistory() throws GuacamoleException {
- throw new UnsupportedOperationException("History unsuppported in DummyConnection.");
+ throw new UnsupportedOperationException("History unsupported in DummyConnection.");
}
}
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/Move.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/Move.java
new file mode 100644
index 000000000..a7e618650
--- /dev/null
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/connections/Move.java
@@ -0,0 +1,68 @@
+package net.sourceforge.guacamole.net.basic.crud.connections;
+
+/*
+ * 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 javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.auth.Connection;
+import net.sourceforge.guacamole.net.auth.Directory;
+import net.sourceforge.guacamole.net.auth.UserContext;
+import net.sourceforge.guacamole.net.basic.AuthenticatingHttpServlet;
+
+/**
+ * Simple HttpServlet which handles moving connections.
+ *
+ * @author Michael Jumper
+ */
+public class Move extends AuthenticatingHttpServlet {
+
+ /**
+ * Prefix given to a parameter name when that parameter is a protocol-
+ * specific parameter meant for the configuration.
+ */
+ public static final String PARAMETER_PREFIX = "_";
+
+ @Override
+ protected void authenticatedService(
+ UserContext context,
+ HttpServletRequest request, HttpServletResponse response)
+ throws GuacamoleException {
+
+ // Get ID
+ String identifier = request.getParameter("id");
+
+ // Get the identifier of the new parent connection group
+ String parentID = request.getParameter("parentID");
+
+ // Attempt to get the new parent connection directory
+ Directory newParentDirectory =
+ ConnectionUtility.findConnectionDirectory(context, parentID);
+
+ // Attempt to get root connection directory
+ Directory directory =
+ context.getRootConnectionGroup().getConnectionDirectory();
+
+ // Move connection
+ directory.move(identifier, newParentDirectory);
+
+ }
+
+}
+
diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/permissions/List.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/permissions/List.java
index ace0ba6ed..355aee7ea 100644
--- a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/permissions/List.java
+++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/crud/permissions/List.java
@@ -31,6 +31,7 @@ import net.sourceforge.guacamole.GuacamoleServerException;
import net.sourceforge.guacamole.net.auth.Directory;
import net.sourceforge.guacamole.net.auth.User;
import net.sourceforge.guacamole.net.auth.UserContext;
+import net.sourceforge.guacamole.net.auth.permission.ConnectionGroupPermission;
import net.sourceforge.guacamole.net.auth.permission.ConnectionPermission;
import net.sourceforge.guacamole.net.auth.permission.ObjectPermission;
import net.sourceforge.guacamole.net.auth.permission.Permission;
@@ -60,9 +61,10 @@ public class List extends AuthenticatingHttpServlet {
throws GuacamoleException {
switch (type) {
- case CREATE_USER: return "create-user";
- case CREATE_CONNECTION: return "create-connection";
- case ADMINISTER: return "admin";
+ case CREATE_USER: return "create-user";
+ case CREATE_CONNECTION: return "create-connection";
+ case CREATE_CONNECTION_GROUP: return "create-connection-group";
+ case ADMINISTER: return "admin";
}
throw new GuacamoleException("Unknown permission type: " + type);
@@ -166,6 +168,20 @@ public class List extends AuthenticatingHttpServlet {
}
+ // Connection group permission
+ else if (permission instanceof ConnectionGroupPermission) {
+
+ // Get permission
+ ConnectionGroupPermission cgp =
+ (ConnectionGroupPermission) permission;
+
+ // Write permission
+ xml.writeEmptyElement("connection-group");
+ xml.writeAttribute("type", toString(cgp.getType()));
+ xml.writeAttribute("name", cgp.getObjectIdentifier());
+
+ }
+
// User permission
else if (permission instanceof UserPermission) {
diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml
index 83f6c8998..fd0e8bcda 100644
--- a/guacamole/src/main/webapp/WEB-INF/web.xml
+++ b/guacamole/src/main/webapp/WEB-INF/web.xml
@@ -88,6 +88,17 @@
/connections/update
+
+
+ Connection move servlet.
+ ConnectionMove
+ net.sourceforge.guacamole.net.basic.crud.connections.Move
+
+
+ ConnectionMove
+ /connections/move
+
+
Connection deletion servlet.
@@ -98,6 +109,61 @@
ConnectionDelete
/connections/delete
+
+
+
+ ConnectionGroup creation servlet.
+ ConnectionGroupCreate
+ net.sourceforge.guacamole.net.basic.crud.connectiongroups.Create
+
+
+ ConnectionGroupCreate
+ /connectiongroups/create
+
+
+
+
+ ConnectionGroup list servlet.
+ ConnectionGroups
+ net.sourceforge.guacamole.net.basic.crud.connectiongroups.List
+
+
+ ConnectionGroups
+ /connectiongroups
+
+
+
+
+ ConnectionGroup update servlet.
+ ConnectionGroupUpdate
+ net.sourceforge.guacamole.net.basic.crud.connectiongroups.Update
+
+
+ ConnectionGroupUpdate
+ /connectiongroups/update
+
+
+
+
+ ConnectionGroup move servlet.
+ ConnectionGroupMove
+ net.sourceforge.guacamole.net.basic.crud.connectiongroups.Move
+
+
+ ConnectionGroupMove
+ /connectiongroups/move
+
+
+
+
+ ConnectionGroup deletion servlet.
+ ConnectionGroupDelete
+ net.sourceforge.guacamole.net.basic.crud.connectiongroups.Delete
+
+
+ ConnectionGroupDelete
+ /connectiongroups/delete
+