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 37086403e..c386e10c8 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/RESTServiceModule.java @@ -39,7 +39,6 @@ import org.apache.guacamole.rest.connectiongroup.ConnectionGroupModule; 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.tunnel.TunnelRESTService; import org.apache.guacamole.rest.user.UserModule; /** @@ -90,7 +89,6 @@ public class RESTServiceModule extends ServletModule { bind(LanguageRESTService.class); bind(PatchRESTService.class); bind(TokenRESTService.class); - bind(TunnelRESTService.class); // Root-level resources bind(SessionRESTService.class); 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 c9e9834f1..211e5d522 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 @@ -31,6 +31,7 @@ import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleSession; import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.rest.ObjectRetrievalService; +import org.apache.guacamole.rest.tunnel.TunnelCollectionResource; /** * A REST resource which exposes all data associated with a Guacamole user's @@ -101,4 +102,17 @@ public class SessionResource { } + /** + * Retrieves a resource representing all tunnels associated with session + * exposed by this SessionResource. + * + * @return + * A resource representing all tunnels associated with the + * AuthenticationProvider having the given identifier. + */ + @Path("tunnels") + public TunnelCollectionResource getTunnelCollectionResource() { + return new TunnelCollectionResource(session); + } + } 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 new file mode 100644 index 000000000..60e48ec4b --- /dev/null +++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/StreamResource.java @@ -0,0 +1,131 @@ +/* + * 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.tunnel; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.tunnel.StreamInterceptingTunnel; + +/** + * A REST resource providing access to a Guacamole protocol-level stream + * within a tunnel. + * + * @author Michael Jumper + */ +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class StreamResource { + + /** + * The tunnel whose stream is exposed through this StreamResource. + */ + private final StreamInterceptingTunnel tunnel; + + /** + * The index of the stream being exposed. + */ + private final int streamIndex; + + /** + * The media type of the data within the stream being exposed. + */ + private final String mediaType; + + /** + * Creates a new StreamResource which provides access to the given + * stream. + * + * @param tunnel + * The tunnel whose stream is being exposed. + * + * @param streamIndex + * The index of the stream to expose via this StreamResource. + * + * @param mediaType + * The media type of the data within the stream. + */ + public StreamResource(StreamInterceptingTunnel tunnel, int streamIndex, + String mediaType) { + this.tunnel = tunnel; + this.streamIndex = streamIndex; + this.mediaType = mediaType; + } + + /** + * Intercepts and returns the entire contents the stream represented by + * this StreamResource. + * + * @return + * A response through which the entire contents of the intercepted + * stream will be sent. + */ + @GET + public Response getStreamContents() { + + // Intercept all output + StreamingOutput stream = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException { + try { + tunnel.interceptStream(streamIndex, output); + } + catch (GuacamoleException e) { + throw new IOException(e); + } + } + + }; + + return Response.ok(stream, mediaType).build(); + + } + + /** + * Intercepts the stream represented by this StreamResource, sending the + * contents of the given InputStream over that stream as "blob" + * instructions. + * + * @param data + * An InputStream containing the data to be sent over the intercepted + * stream. + * + * @throws GuacamoleException + * If the intercepted stream closes with an error. + */ + @POST + @Consumes(MediaType.WILDCARD) + public void setStreamContents(InputStream data) throws GuacamoleException { + + // Send input over stream + tunnel.interceptStream(streamIndex, data); + + } + +} 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 new file mode 100644 index 000000000..342cc763f --- /dev/null +++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java @@ -0,0 +1,105 @@ +/* + * 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.tunnel; + +import java.util.Map; +import java.util.Set; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleResourceNotFoundException; +import org.apache.guacamole.GuacamoleSession; +import org.apache.guacamole.tunnel.StreamInterceptingTunnel; + +/** + * A REST resource which exposes the active tunnels of a Guacamole session. + * + * @author Michael Jumper + */ +@Path("/tunnels") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class TunnelCollectionResource { + + /** + * The GuacamoleSession containing the tunnels exposed by this resource. + */ + private final GuacamoleSession session; + + /** + * Creates a new TunnelCollectionResource which exposes the active tunnels + * of the given GuacamoleSession. + * + * @param session + * The GuacamoleSession whose tunnels should be exposed by this + * resource. + */ + public TunnelCollectionResource(GuacamoleSession session) { + this.session = session; + } + + /** + * Returns the UUIDs of all tunnels exposed by this + * TunnelCollectionResource. + * + * @return + * A set containing the UUIDs of all tunnels exposed by this + * TunnelCollectionResource. + */ + @GET + public Set getTunnelUUIDs() { + return session.getTunnels().keySet(); + } + + /** + * Retrieves the tunnel having the given UUID, returning a TunnelResource + * representing that tunnel. If no such tunnel exists, an exception will be + * thrown. + * + * @param tunnelUUID + * The UUID of the tunnel to return via a TunnelResource. + * + * @return + * A TunnelResource which represents the tunnel having the given UUID. + * + * @throws GuacamoleException + * If no such tunnel exists. + */ + @Path("{tunnel}") + public TunnelResource getTunnel(@PathParam("tunnel") String tunnelUUID) + throws GuacamoleException { + + Map tunnels = session.getTunnels(); + + // Pull tunnel with given UUID + final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID); + if (tunnel == null) + throw new GuacamoleResourceNotFoundException("No such tunnel."); + + // Return corresponding tunnel resource + return new TunnelResource(tunnel); + + } + +} diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelRESTService.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelRESTService.java deleted file mode 100644 index 49740d1b2..000000000 --- a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelRESTService.java +++ /dev/null @@ -1,202 +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.tunnel; - -import com.google.inject.Inject; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; -import java.util.Set; -import javax.ws.rs.Consumes; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -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; -import javax.ws.rs.core.StreamingOutput; -import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.GuacamoleResourceNotFoundException; -import org.apache.guacamole.GuacamoleSession; -import org.apache.guacamole.rest.auth.AuthenticationService; -import org.apache.guacamole.tunnel.StreamInterceptingTunnel; - -/** - * A REST Service for retrieving and managing the tunnels of active - * connections, including any associated objects. - * - * @author Michael Jumper - */ -@Path("/tunnels") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public class TunnelRESTService { - - /** - * The media type to send as the content type of stream contents if no - * other media type is specified. - */ - private static final String DEFAULT_MEDIA_TYPE = "application/octet-stream"; - - /** - * A service for authenticating users from auth tokens. - */ - @Inject - private AuthenticationService authenticationService; - - /** - * Returns the UUIDs of all currently-active tunnels associated with the - * session identified by the given auth token. - * - * @param authToken - * The authentication token that is used to authenticate the user - * performing the operation. - * - * @return - * A set containing the UUIDs of all currently-active tunnels. - * - * @throws GuacamoleException - * If the session associated with the given auth token cannot be - * retrieved. - */ - @GET - public Set getTunnelUUIDs(@QueryParam("token") String authToken) - throws GuacamoleException { - GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); - return session.getTunnels().keySet(); - } - - /** - * Intercepts and returns the entire contents of a specific stream. - * - * @param authToken - * The authentication token that is used to authenticate the user - * performing the operation. - * - * @param tunnelUUID - * The UUID of the tunnel containing the stream being intercepted. - * - * @param streamIndex - * The index of the stream to intercept. - * - * @param mediaType - * The media type (mimetype) of the data within the stream. - * - * @param filename - * The filename to use for the sake of identifying the data returned. - * - * @return - * A response through which the entire contents of the intercepted - * stream will be sent. - * - * @throws GuacamoleException - * If the session associated with the given auth token cannot be - * retrieved, or if no such tunnel exists. - */ - @GET - @Path("/{tunnel}/streams/{index}/{filename}") - public Response getStreamContents(@QueryParam("token") String authToken, - @PathParam("tunnel") String tunnelUUID, - @PathParam("index") final int streamIndex, - @QueryParam("type") @DefaultValue(DEFAULT_MEDIA_TYPE) String mediaType, - @PathParam("filename") String filename) - throws GuacamoleException { - - GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); - Map tunnels = session.getTunnels(); - - // Pull tunnel with given UUID - final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID); - if (tunnel == null) - throw new GuacamoleResourceNotFoundException("No such tunnel."); - - // Intercept all output - StreamingOutput stream = new StreamingOutput() { - - @Override - public void write(OutputStream output) throws IOException { - try { - tunnel.interceptStream(streamIndex, output); - } - catch (GuacamoleException e) { - throw new IOException(e); - } - } - - }; - - return Response.ok(stream, mediaType).build(); - - } - - /** - * Intercepts a specific stream, sending the contents of the given - * InputStream over that stream as "blob" instructions. - * - * @param authToken - * The authentication token that is used to authenticate the user - * performing the operation. - * - * @param tunnelUUID - * The UUID of the tunnel containing the stream being intercepted. - * - * @param streamIndex - * The index of the stream to intercept. - * - * @param filename - * The filename to use for the sake of identifying the data being sent. - * - * @param data - * An InputStream containing the data to be sent over the intercepted - * stream. - * - * @throws GuacamoleException - * If the session associated with the given auth token cannot be - * retrieved, if no such tunnel exists, or if the intercepted stream - * itself closes with an error. - */ - @POST - @Consumes(MediaType.WILDCARD) - @Path("/{tunnel}/streams/{index}/{filename}") - public void setStreamContents(@QueryParam("token") String authToken, - @PathParam("tunnel") String tunnelUUID, - @PathParam("index") final int streamIndex, - @PathParam("filename") String filename, - InputStream data) - throws GuacamoleException { - - GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); - Map tunnels = session.getTunnels(); - - // Pull tunnel with given UUID - final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID); - if (tunnel == null) - throw new GuacamoleResourceNotFoundException("No such tunnel."); - - // Send input over stream - tunnel.interceptStream(streamIndex, data); - - } - -} 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 new file mode 100644 index 000000000..3bfcae200 --- /dev/null +++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java @@ -0,0 +1,94 @@ +/* + * 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.tunnel; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +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 org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.tunnel.StreamInterceptingTunnel; + +/** + * A REST resource which abstracts the operations available for an individual + * tunnel. + * + * @author Michael Jumper + */ +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class TunnelResource { + + /** + * The media type to send as the content type of stream contents if no + * other media type is specified. + */ + private static final String DEFAULT_MEDIA_TYPE = "application/octet-stream"; + + /** + * The tunnel that this TunnelResource represents. + */ + private final StreamInterceptingTunnel tunnel; + + /** + * Creates a new TunnelResource which exposes the operations and + * subresources available for the given tunnel. + * + * @param tunnel + * The tunnel that this TunnelResource should represent. + */ + public TunnelResource(StreamInterceptingTunnel tunnel) { + this.tunnel = tunnel; + } + + /** + * Intercepts and returns the entire contents of a specific stream. + * + * @param streamIndex + * The index of the stream to intercept. + * + * @param mediaType + * The media type (mimetype) of the data within the stream. + * + * @param filename + * The filename to use for the sake of identifying the data returned. + * + * @return + * A response through which the entire contents of the intercepted + * stream will be sent. + * + * @throws GuacamoleException + * If the session associated with the given auth token cannot be + * retrieved, or if no such tunnel exists. + */ + @Path("streams/{index}/{filename}") + public StreamResource getStream(@PathParam("index") final int streamIndex, + @QueryParam("type") @DefaultValue(DEFAULT_MEDIA_TYPE) String mediaType, + @PathParam("filename") String filename) + throws GuacamoleException { + + return new StreamResource(tunnel, streamIndex, mediaType); + + } + +} diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/package-info.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/package-info.java new file mode 100644 index 000000000..d4f07a7dc --- /dev/null +++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * Classes related to the manipulation of Guacamole tunnels and underlying + * streams. + */ +package org.apache.guacamole.rest.tunnel;