/*FreeMind - A Program for creating and viewing Mindmaps *Copyright (C) 2000-2009 Christian Foltin and others. * *See COPYING for Details * *This program is free software; you can redistribute it and/or *modify it under the terms of the GNU General Public License *as published by the Free Software Foundation; either version 2 *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 General Public License for more details. * *You should have received a copy of the GNU General Public License *along with this program; if not, write to the Free Software *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Created on 03.02.2009 */ package plugins.collaboration.socket; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.StringWriter; import java.net.Socket; import plugins.collaboration.socket.SocketBasics.UnableToGetLockException; import freemind.controller.actions.generated.instance.CollaborationActionBase; import freemind.controller.actions.generated.instance.CollaborationGoodbye; import freemind.controller.actions.generated.instance.CollaborationHello; import freemind.controller.actions.generated.instance.CollaborationReceiveLock; import freemind.controller.actions.generated.instance.CollaborationRequireLock; import freemind.controller.actions.generated.instance.CollaborationTransaction; import freemind.controller.actions.generated.instance.CollaborationUnableToLock; import freemind.controller.actions.generated.instance.CollaborationWelcome; import freemind.controller.actions.generated.instance.CollaborationWhoAreYou; import freemind.controller.actions.generated.instance.CollaborationWrongCredentials; import freemind.main.Tools; import freemind.modes.mindmapmode.MindMapController; /** * This class handles the communication from the master to a single client. It * is thus instanciated for each client (by the MindMapMaster). * * @author foltin * @date 13.09.2012 */ public class ServerCommunication extends CommunicationBase { protected MindMapMaster mMindMapMaster = null; public ServerCommunication(MindMapMaster pSocketStarter, Socket pClient, MindMapController pMindMapController) throws Exception { super("Client Communication", pClient, pMindMapController, new DataOutputStream(pClient.getOutputStream()), new DataInputStream(pClient.getInputStream())); mMindMapMaster = pSocketStarter; CollaborationWhoAreYou commandWho = new CollaborationWhoAreYou(); send(commandWho); setCurrentState(STATE_WAIT_FOR_HELLO); } public void processCommand(CollaborationActionBase pCommand) throws Exception { if (pCommand instanceof CollaborationGoodbye) { CollaborationGoodbye goodbye = (CollaborationGoodbye) pCommand; logger.info("Goodbye received from " + goodbye.getUserId()); terminateSocket(); return; } boolean commandHandled = false; if (pCommand instanceof CollaborationHello) { // here, we are strict in checking the state, as not the whole world // should get access to the map! if (getCurrentState() != STATE_WAIT_FOR_HELLO) { printWrongState(pCommand); } else { CollaborationHello commandHello = (CollaborationHello) pCommand; setName(commandHello.getUserId()); // verify password: if (mMindMapMaster.getPassword().equals( commandHello.getPassword())) { // send map: CollaborationWelcome welcomeCommand = new CollaborationWelcome(); logger.info("Store map in welcome command..."); StringWriter writer = new StringWriter(); mController.getMap().getXml(writer); welcomeCommand.setMap(writer.toString()); welcomeCommand.setFilename(mController.getMap().getFile() .getName()); send(welcomeCommand); setCurrentState(STATE_IDLE); } else { // Send error message CollaborationWrongCredentials wrongMessage = new CollaborationWrongCredentials(); try { send(wrongMessage); } finally { terminateSocket(); } } commandHandled = true; } } if (pCommand instanceof CollaborationTransaction) { if (getCurrentState() != STATE_WAIT_FOR_COMMAND) { printWrongState(pCommand); } else { CollaborationTransaction trans = (CollaborationTransaction) pCommand; try { if (!Tools .safeEquals(mMindMapMaster.getLockId(), trans.getId())) { logger.severe("Wrong transaction id received. Expected: " + mMindMapMaster.getLockId() + ", received: " + trans.getId()); } else { mMindMapMaster.broadcastCommand(trans.getDoAction(), trans.getUndoAction(), trans.getId()); mMindMapMaster.executeTransaction(getActionPair(trans)); } } finally { mMindMapMaster.unlock(); setCurrentState(STATE_IDLE); commandHandled = true; } } } if (pCommand instanceof CollaborationRequireLock) { if (getCurrentState() != STATE_IDLE) { printWrongState(pCommand); } try { String lockId = mMindMapMaster.lock(this.getName()); logger.info("Got lock for " + getName()); CollaborationReceiveLock lockCommand = new CollaborationReceiveLock(); lockCommand.setId(lockId); send(lockCommand); setCurrentState(STATE_WAIT_FOR_COMMAND); commandHandled = true; } catch (UnableToGetLockException e) { freemind.main.Resources.getInstance().logException(e); CollaborationUnableToLock unableToLock = new CollaborationUnableToLock(); send(unableToLock); } catch (InterruptedException e) { freemind.main.Resources.getInstance().logException(e); } } if (!commandHandled) { logger.warning("Received unknown message of type " + pCommand.getClass()); } } public void terminateSocket() throws IOException { mMindMapMaster.removeConnection(this); commitSuicide(); close(); } }