diff --git a/guacamole/pom.xml b/guacamole/pom.xml
index b76f8b088..0de815902 100644
--- a/guacamole/pom.xml
+++ b/guacamole/pom.xml
@@ -129,14 +129,14 @@
com.sun.jersey
jersey-server
- 1.7
+ 1.17.1
com.sun.jersey.contribs
jersey-guice
- 1.7
+ 1.17.1
@@ -152,6 +152,13 @@
commons-codec
1.4
+
+
+
+ com.sun.jersey
+ jersey-json
+ 1.17.1
+
diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/APIError.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/APIError.java
new file mode 100644
index 000000000..be68456f8
--- /dev/null
+++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/APIError.java
@@ -0,0 +1,47 @@
+package org.glyptodon.guacamole.net.basic.rest;
+
+/*
+ * 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 object to represent an error to be sent from the REST API.
+ * @author James Muehlner
+ */
+public class APIError {
+
+ /**
+ * The error message.
+ */
+ private String message;
+
+ /**
+ * Get the error message.
+ * @return The error message.
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * Create a new APIError with the specified error message.
+ * @param message The error message.
+ */
+ public APIError(String message) {
+ this.message = message;
+ }
+}
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 1ac01a6e7..c1e6bf856 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
@@ -26,6 +26,7 @@ import org.glyptodon.guacamole.net.basic.rest.auth.AuthTokenGenerator;
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.properties.GuacamoleProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,6 +63,7 @@ public class RESTModule extends AbstractModule {
bind(AuthenticationProvider.class).toInstance(authProvider);
bind(TokenUserContextMap.class).toInstance(new BasicTokenUserContextMap());
+ bind(ConnectionService.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 00627e59d..d11992563 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
@@ -18,10 +18,12 @@ package org.glyptodon.guacamole.net.basic.rest;
* along with this program. If not, see .
*/
+import com.google.inject.Scopes;
import com.google.inject.servlet.ServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-import org.glyptodon.guacamole.net.basic.rest.auth.LoginService;
-import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionService;
+import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
+import org.glyptodon.guacamole.net.basic.rest.auth.LoginRESTService;
+import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionRESTService;
/**
* A Guice Module to set up the servlet mappings for the Guacamole REST API.
@@ -32,11 +34,15 @@ public class RESTServletModule extends ServletModule {
@Override
protected void configureServlets() {
-
- bind(ConnectionService.class);
- bind(LoginService.class);
-
- serve("*").with(GuiceContainer.class);
+
+ // Set up the API endpoints
+ bind(ConnectionRESTService.class);
+ bind(LoginRESTService.class);
+
+ // Set up the servlet and JSON mappings
+ bind(GuiceContainer.class);
+ bind(JacksonJsonProvider.class).in(Scopes.SINGLETON);
+ serve("/*").with(GuiceContainer.class);
}
}
diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/LoginService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/LoginRESTService.java
similarity index 98%
rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/LoginService.java
rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/LoginRESTService.java
index 19e97392e..f0ae5a9a7 100644
--- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/LoginService.java
+++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/auth/LoginRESTService.java
@@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
@Path("/api/login")
-public class LoginService {
+public class LoginRESTService {
/**
* The authentication provider used to authenticate this user.
@@ -65,7 +65,7 @@ public class LoginService {
/**
* Logger for this class.
*/
- private static final Logger logger = LoggerFactory.getLogger(LoginService.class);
+ private static final Logger logger = LoggerFactory.getLogger(LoginRESTService.class);
/**
* Authenticates a user, generates an auth token, associates that auth token
@@ -76,7 +76,6 @@ public class LoginService {
* @return The auth token for the newly logged-in user.
*/
@POST
- @Path("/")
public String login(@QueryParam("username") String username,
@QueryParam("password") String password) {
diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/Connection.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/Connection.java
new file mode 100644
index 000000000..9e4406f3d
--- /dev/null
+++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/Connection.java
@@ -0,0 +1,104 @@
+package org.glyptodon.guacamole.net.basic.rest.connection;
+
+/*
+ * 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.util.List;
+import org.glyptodon.guacamole.GuacamoleException;
+import org.glyptodon.guacamole.net.auth.ConnectionRecord;
+import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
+
+/**
+ * A simple connection to expose through the REST endpoints.
+ *
+ * @author James Muehlner
+ */
+public class Connection {
+
+ /**
+ * The name of this connection.
+ */
+ private String name;
+
+ /**
+ * The identifier of this connection.
+ */
+ private String identifier;
+
+ /**
+ * The configuration associated with this connection.
+ */
+ private GuacamoleConfiguration configuration;
+
+ /**
+ * The history records associated with this connection.
+ */
+ private List extends ConnectionRecord> history;
+
+ /**
+ * Create an empty Connection.
+ */
+ public Connection() {}
+
+ /**
+ * Create a Connection from a org.glyptodon.guacamole.net.auth.Connection.
+ * @param connection The connection to create this Connection from.
+ * @throws GuacamoleException If a problem is encountered while
+ * instantiating this new Connection.
+ */
+ public Connection(org.glyptodon.guacamole.net.auth.Connection connection)
+ throws GuacamoleException {
+ this.name = connection.getName();
+ this.identifier = connection.getIdentifier();
+ this.configuration = connection.getConfiguration();
+ this.history = connection.getHistory();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ public void setIdentifier(String identifier) {
+ this.identifier = identifier;
+ }
+
+ public GuacamoleConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ public void setConfiguration(GuacamoleConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ public List extends ConnectionRecord> getHistory() {
+ return history;
+ }
+
+ public void setHistory(List extends ConnectionRecord> history) {
+ this.history = history;
+ }
+
+}
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
new file mode 100644
index 000000000..27961ade7
--- /dev/null
+++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionRESTService.java
@@ -0,0 +1,108 @@
+package org.glyptodon.guacamole.net.basic.rest.connection;
+
+/*
+ * 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 com.google.inject.servlet.RequestScoped;
+import java.util.ArrayList;
+import java.util.List;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+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.APIError;
+import org.glyptodon.guacamole.net.basic.rest.auth.TokenUserContextMap;
+
+/**
+ * A REST Service for handling connection CRUD operations.
+ *
+ * @author James Muehlner
+ */
+@Path("/api/connection")
+@RequestScoped
+public class ConnectionRESTService {
+
+ /**
+ * The map of auth tokens to users for the REST endpoints.
+ */
+ @Inject
+ private TokenUserContextMap tokenUserMap;
+
+ /**
+ * A service for managing the REST endpoint Connection objects.
+ */
+ @Inject
+ private ConnectionService connectionService;
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public List getConnections(@QueryParam("token") String authToken, @QueryParam("parentID") String parentID) {
+ UserContext userContext = tokenUserMap.get(authToken);
+
+ // authentication failed.
+ if(userContext == null)
+ throw new WebApplicationException(Response.Status.UNAUTHORIZED);
+
+
+ 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 WebApplicationException(
+ Response.status(Response.Status.BAD_REQUEST)
+ .entity(new APIError("No ConnectionGroup found with the provided parentID."))
+ .build());
+
+ Directory connectionDirectory =
+ parentConnectionGroup.getConnectionDirectory();
+
+ // Get the list of connection names
+ List connections
+ = new ArrayList();
+ Iterable identifiers = connectionDirectory.getIdentifiers();
+
+ // Get the connection for each name
+ for(String identifier : identifiers)
+ connections.add(connectionDirectory.get(identifier));
+
+ return connectionService.convertConnectionList(connections);
+ } catch(GuacamoleSecurityException e) {
+ throw new WebApplicationException(e, Response.Status.UNAUTHORIZED);
+ } catch(GuacamoleException e) {
+ throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+}
diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionService.java
index 3f4125787..182261035 100644
--- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionService.java
+++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/ConnectionService.java
@@ -1,5 +1,9 @@
package org.glyptodon.guacamole.net.basic.rest.connection;
+import java.util.ArrayList;
+import java.util.List;
+import org.glyptodon.guacamole.GuacamoleException;
+
/*
* Guacamole - Clientless Remote Desktop
* Copyright (C) 2010 Michael Jumper
@@ -18,48 +22,31 @@ package org.glyptodon.guacamole.net.basic.rest.connection;
* along with this program. If not, see .
*/
-import com.google.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
-import org.glyptodon.guacamole.GuacamoleException;
-import org.glyptodon.guacamole.GuacamoleSecurityException;
-import org.glyptodon.guacamole.net.auth.UserContext;
-import org.glyptodon.guacamole.net.basic.rest.auth.TokenUserContextMap;
-
/**
- * A REST Service for handling connection CRUD operations.
+ * A service for performing useful manipulations on REST Connections.
*
* @author James Muehlner
*/
-@Path("/api/connection")
public class ConnectionService {
/**
- * The map of auth tokens to users for the REST endpoints.
+ * Converts a list of org.glyptodon.guacamole.net.auth.Connection to
+ * Connection objects for exposure with the REST endpoints.
+ *
+ * @param connections The org.glyptodon.guacamole.net.auth.Connection to
+ * convert for REST endpoint use.
+ * @return A List of Connection objects for use with the REST endpoint.
+ * @throws GuacamoleException If an error occurs while converting the
+ * connections.
*/
- @Inject
- private TokenUserContextMap tokenUserMap;
-
- @Path("/")
- @GET
- public String getConnections(@QueryParam("token") String authToken) {
- UserContext userContext = tokenUserMap.get(authToken);
-
- // authentication failed.
- if(userContext == null)
- throw new WebApplicationException(Response.Status.UNAUTHORIZED);
+ public List convertConnectionList(List extends org.glyptodon.guacamole.net.auth.Connection> connections)
+ throws GuacamoleException {
+ List restConnections = new ArrayList();
- try {
- //TODO: Make this work for realzies
- return userContext.getRootConnectionGroup().getConnectionDirectory().getIdentifiers().toString();
- } catch(GuacamoleSecurityException e) {
- throw new WebApplicationException(e, Response.Status.UNAUTHORIZED);
- } catch(GuacamoleException e) {
- throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
+ for(org.glyptodon.guacamole.net.auth.Connection connection : connections) {
+ restConnections.add(new Connection(connection));
}
- }
-
+
+ return restConnections;
+ }
}
diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml
index b02dc535d..452f763a5 100644
--- a/guacamole/src/main/webapp/WEB-INF/web.xml
+++ b/guacamole/src/main/webapp/WEB-INF/web.xml
@@ -255,6 +255,16 @@
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