/** * $Id: mxSession.java,v 1.1 2012/11/15 13:26:50 gaudenz Exp $ * Copyright (c) 2007-2012, JGraph Ltd */ package com.mxgraph.sharing; import org.w3c.dom.Node; import com.mxgraph.sharing.mxSharedState.mxDiagramChangeListener; import com.mxgraph.util.mxUtils; /** * Implements a session that may be attached to a shared diagram. The session * contains a synchronized buffer which is used to hold the pending edits which * are to be sent to a specific client. The update mechnism between the server * and the client uses HTTP requests (polling). The request is kept on the server * for an amount of time or wakes up / returns immediately if the buffer is no * longer empty. */ public class mxSession implements mxDiagramChangeListener { /** * Default timeout is 10000 ms. */ public static int DEFAULT_TIMEOUT = 10000; /** * Holds the session ID. */ protected String id; /** * Reference to the shared diagram. */ protected mxSharedState diagram; /** * Holds the send buffer for this session. */ protected StringBuffer buffer = new StringBuffer(); /** * Holds the last active time millis. */ protected long lastTimeMillis = 0; /** * Constructs a new session with the given ID. * * @param id Specifies the session ID to be used. * @param diagram Reference to the shared diagram. */ public mxSession(String id, mxSharedState diagram) { this.id = id; this.diagram = diagram; this.diagram.addDiagramChangeListener(this); lastTimeMillis = System.currentTimeMillis(); } /** * Returns the session ID. */ public String getId() { return id; } /** * Initializes the session buffer and returns a string that represents the * state of the session. * * @return Returns the initial state of the session. */ public synchronized String init() { synchronized (this) { buffer = new StringBuffer(); notify(); } return getInitialMessage(); } /** * Returns an XML string that represents the current state of the session * and the shared diagram. A globally unique ID is used as the session's * namespace, which is used on the client side to prefix IDs of newly * created cells. */ public String getInitialMessage() { String ns = mxUtils.getMd5Hash(id); StringBuffer result = new StringBuffer("<message namespace=\"" + ns + "\">"); result.append("<state>"); result.append(diagram.getState()); result.append("</state>"); result.append("<delta>"); result.append(diagram.getDelta()); result.append("</delta>"); result.append("</message>"); return result.toString(); } /** * Posts the change represented by the given XML string to the shared diagram. * * @param message XML that represents the change. */ public void receive(Node message) { //System.out.println(getId() + ": " + mxUtils.getPrettyXml(message)); Node child = message.getFirstChild(); while (child != null) { if (child.getNodeName().equals("delta")) { diagram.processDelta(this, child); } child = child.getNextSibling(); } /*System.out.println(mxUtils.getPrettyXml(new mxCodec() .encode(((mxSharedGraphModel) diagram).getModel())));*/ } /** * Returns the changes received by other sessions for the shared diagram. * The method returns an empty XML node if no change was received within * 10 seconds. * * @return Returns a string representing the changes to the shared diagram. */ public String poll() throws InterruptedException { return poll(DEFAULT_TIMEOUT); } /** * Returns the changes received by other sessions for the shared diagram. * The method returns an empty XML node if no change was received within * the given timeout. * * @param timeout Time in milliseconds to wait for changes. * @return Returns a string representing the changes to the shared diagram. */ public String poll(long timeout) throws InterruptedException { lastTimeMillis = System.currentTimeMillis(); StringBuffer result = new StringBuffer("<message>"); synchronized (this) { if (buffer.length() == 0) { wait(timeout); } if (buffer.length() > 0) { result.append("<delta>"); result.append(buffer.toString()); result.append("</delta>"); buffer = new StringBuffer(); } notify(); } result.append("</message>"); return result.toString(); } /* * (non-Javadoc) * @see com.mxgraph.sharing.mxSharedDiagram.mxDiagramChangeListener#diagramChanged(java.lang.Object, org.w3c.dom.Node) */ public synchronized void diagramChanged(Object sender, String edits) { if (sender != this) { synchronized (this) { buffer.append(edits); notify(); } } } /** * Returns the number of milliseconds this session has been inactive. */ public long inactiveTimeMillis() { return System.currentTimeMillis() - lastTimeMillis; } /** * Destroys the session and removes its listener from the shared diagram. */ public void destroy() { diagram.removeDiagramChangeListener(this); } }