diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingHttpServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingHttpServlet.java index 3c48fa444..a87042955 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingHttpServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingHttpServlet.java @@ -80,6 +80,11 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet { */ public static final String CREDENTIALS_ATTRIBUTE = "GUAC_CREDS"; + /** + * The session attribute holding the session-scoped clipboard storage. + */ + public static final String CLIPBOARD_ATTRIBUTE = "GUAC_CLIP"; + /** * The AuthenticationProvider to use to authenticate all requests. */ @@ -218,6 +223,25 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet { return (UserContext) session.getAttribute(CONTEXT_ATTRIBUTE); } + /** + * Returns the ClipboardState associated with the given session. If none + * exists yet, one is created. + * + * @param session The session to retrieve the ClipboardState from. + * @return The ClipboardState associated with the given session. + */ + public static ClipboardState getClipboardState(HttpSession session) { + + ClipboardState clipboard = (ClipboardState) session.getAttribute(CLIPBOARD_ATTRIBUTE); + if (clipboard == null) { + clipboard = new ClipboardState(); + session.setAttribute(CLIPBOARD_ATTRIBUTE, clipboard); + } + + return clipboard; + + } + /** * Returns whether the request given has updated credentials. If this * function returns false, the UserContext will not be updated. diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java index eaa9f923a..90214e519 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java @@ -243,6 +243,9 @@ public class BasicTunnelRequestUtility { if (context == null || credentials == null) throw new GuacamoleSecurityException("Cannot connect - user not logged in."); + // Get clipboard + final ClipboardState clipboard = AuthenticatingHttpServlet.getClipboardState(httpSession); + // Get client information GuacamoleClientInformation info = new GuacamoleClientInformation(); @@ -327,7 +330,7 @@ public class BasicTunnelRequestUtility { @Override public GuacamoleReader acquireReader() { // Monitor instructions which pertain to server-side events - return new MonitoringGuacamoleReader(listeners, super.acquireReader()); + return new MonitoringGuacamoleReader(clipboard, super.acquireReader()); } @Override diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/event/ClipboardChangeEvent.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/ClipboardState.java similarity index 61% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/event/ClipboardChangeEvent.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/ClipboardState.java index 9e8f65714..1aebd2206 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/event/ClipboardChangeEvent.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/ClipboardState.java @@ -1,16 +1,16 @@ /* - * Copyright (C) 2013 Glyptodon LLC - * + * Copyright (C) 2014 Glyptodon LLC. + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -20,32 +20,36 @@ * THE SOFTWARE. */ -package org.glyptodon.guacamole.net.basic.event; +package org.glyptodon.guacamole.net.basic; /** - * An event which is triggered whenever new clipboard data is received. - * + * Provides central storage for a cross-connection clipboard state. This + * clipboard state is shared only for a single HTTP session. Multiple HTTP + * sessions will all have their own state. + * * @author Michael Jumper */ -public class ClipboardChangeEvent { +public class ClipboardState { /** - * The new clipboard data. + * The current contents. */ - private final String data; + private String contents = ""; /** - * Creates a new ClipboardChangeEvent which represents the changing of - * clipboard contents (or, rather, the receipt of new clipboard contents). - * - * @param data The new clipboard contents. + * Returns the current clipboard contents. + * @return The current clipboard contents */ - public ClipboardChangeEvent(String data) { - this.data = data; + public String getContents() { + return contents; } - public String getData() { - return data; + /** + * Sets the current clipboard contents. + * @param contents The contents to assign to the clipboard. + */ + public void setContents(String contents) { + this.contents = contents; } - + } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/MonitoringGuacamoleReader.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/MonitoringGuacamoleReader.java index 77cc6d605..b09881c98 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/MonitoringGuacamoleReader.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/MonitoringGuacamoleReader.java @@ -22,18 +22,14 @@ package org.glyptodon.guacamole.net.basic; -import java.util.Collection; import java.util.List; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.io.GuacamoleReader; -import org.glyptodon.guacamole.net.basic.event.ClipboardChangeEvent; -import org.glyptodon.guacamole.net.basic.event.SessionListenerCollection; -import org.glyptodon.guacamole.net.basic.event.listener.ClipboardChangeListener; import org.glyptodon.guacamole.protocol.GuacamoleInstruction; /** * GuacamoleReader implementation which watches for specific instructions, - * firing server-side events when they are observed. + * maintaining state based on the observed instructions. * * @author Michael Jumper */ @@ -47,44 +43,19 @@ public class MonitoringGuacamoleReader implements GuacamoleReader { /** * Collection of all listeners which will receive events. */ - private final SessionListenerCollection listeners; - - /** - * Notifies all listeners in the given collection that clipboard data has - * changed. - * - * @param listeners A collection of all listeners that should be notified. - * @param data The new clipboard data. - * @throws GuacamoleException If any listener throws an error while being - * notified. - */ - private static boolean notifyClipboardChange(Collection listeners, String data) - throws GuacamoleException { - - // Build event for clipboard change - ClipboardChangeEvent event = new ClipboardChangeEvent(data); - - // Notify all listeners - for (Object listener : listeners) { - if (listener instanceof ClipboardChangeListener) - ((ClipboardChangeListener) listener).clipboardChanged(event); - } - - return true; - - } + private final ClipboardState clipboard; /** * Creates a new MonitoringGuacamoleReader which watches the instructions * read by the given GuacamoleReader, firing events when specific * instructions are seen. * - * @param listeners The collection of listeners receiving events. + * @param clipboard The clipboard state to maintain. * @param reader The reader to observe. */ - public MonitoringGuacamoleReader(SessionListenerCollection listeners, + public MonitoringGuacamoleReader(ClipboardState clipboard, GuacamoleReader reader) { - this.listeners = listeners; + this.clipboard = clipboard; this.reader = reader; } @@ -107,7 +78,7 @@ public class MonitoringGuacamoleReader implements GuacamoleReader { if (instruction.getOpcode().equals("clipboard")) { List args = instruction.getArgs(); if (args.size() >= 1) - notifyClipboardChange(listeners, args.get(0)); + clipboard.setContents(args.get(0)); } return instruction; diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/event/listener/ClipboardChangeListener.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/event/listener/ClipboardChangeListener.java deleted file mode 100644 index 6ea3f6b8a..000000000 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/event/listener/ClipboardChangeListener.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package org.glyptodon.guacamole.net.basic.event.listener; - -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.basic.event.ClipboardChangeEvent; - -/** - * A listener whose clipboardChanged() hook will fire immediately after - * clipboard data is received. - * - * @author Michael Jumper - */ -public interface ClipboardChangeListener { - - /** - * Event hook which fires immediately after an existing tunnel is closed. - * The return value of this hook dictates whether the tunnel is allowed to - * be closed. - * - * @param e The TunnelCloseEvent describing the tunnel being closed and - * any associated credentials. - * @throws GuacamoleException If an error occurs while handling the - * tunnel close event. Throwing an exception - * will also stop the tunnel from being closed. - */ - void clipboardChanged(ClipboardChangeEvent e) - throws GuacamoleException; - -}