Package org.jdesktop.wonderland.server.cell

Source Code of org.jdesktop.wonderland.server.cell.CellEditConnectionHandler$ReparentCellResource

/**
* Open Wonderland
*
* Copyright (c) 2010 - 2011, Open Wonderland Foundation, All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* The Open Wonderland Foundation designates this particular file as
* subject to the "Classpath" exception as provided by the Open Wonderland
* Foundation in the License file that accompanied this code.
*/

/**
* Project Wonderland
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied
* this code.
*/
package org.jdesktop.wonderland.server.cell;

import com.jme.math.Vector3f;
import com.sun.sgs.app.AppContext;
import com.sun.sgs.kernel.ComponentRegistry;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jdesktop.wonderland.common.auth.WonderlandIdentity;
import org.jdesktop.wonderland.common.cell.CellEditConnectionType;
import org.jdesktop.wonderland.common.cell.CellID;
import org.jdesktop.wonderland.common.cell.CellTransform;
import org.jdesktop.wonderland.common.cell.MultipleParentException;
import org.jdesktop.wonderland.common.cell.messages.CellCreateMessage;
import org.jdesktop.wonderland.common.cell.messages.CellCreatedMessage;
import org.jdesktop.wonderland.common.cell.messages.CellDeleteMessage;
import org.jdesktop.wonderland.common.cell.messages.CellDuplicateMessage;
import org.jdesktop.wonderland.common.cell.messages.CellEditMessage;
import org.jdesktop.wonderland.common.cell.messages.CellEditMessage.EditType;
import org.jdesktop.wonderland.common.cell.messages.CellReparentMessage;
import org.jdesktop.wonderland.common.cell.security.ChildrenAction;
import org.jdesktop.wonderland.common.cell.state.CellServerState;
import org.jdesktop.wonderland.common.cell.state.PositionComponentServerState;
import org.jdesktop.wonderland.common.comms.ConnectionType;
import org.jdesktop.wonderland.common.messages.ErrorMessage;
import org.jdesktop.wonderland.common.messages.Message;
import org.jdesktop.wonderland.common.security.Action;
import org.jdesktop.wonderland.server.WonderlandContext;
import org.jdesktop.wonderland.server.comms.SecureClientConnectionHandler;
import org.jdesktop.wonderland.server.comms.WonderlandClientID;
import org.jdesktop.wonderland.server.comms.WonderlandClientSender;
import org.jdesktop.wonderland.server.security.Resource;

/**
* Handles CellEditMessages sent by the Wonderland client
*
* @author Jordan Slott <jslott@dev.java.net>
*/
class CellEditConnectionHandler implements SecureClientConnectionHandler, Serializable {

    public ConnectionType getConnectionType() {
        return CellEditConnectionType.CLIENT_TYPE;
    }

    public void registered(WonderlandClientSender sender) {
        // ignore
    }

    public Resource checkConnect(WonderlandClientID clientID, Properties properties) {
        return null;
    }

    public void clientConnected(WonderlandClientSender sender,
            WonderlandClientID clientID, Properties properties) {
        // ignore
    }

    public void connectionRejected(WonderlandClientID clientID) {
        // ignore
    }

    public void clientDisconnected(WonderlandClientSender sender,
            WonderlandClientID clientID) {
        // ignore
    }

    public Resource checkMessage(WonderlandClientID clientID, Message message) {
        CellResourceManager crm = AppContext.getManager(CellResourceManager.class);
        Resource out = null;

        // for each cell being modified, check that the caller has
        // permissions to modify the children of the parent cell
        CellEditMessage editMessage = (CellEditMessage) message;
        switch (editMessage.getEditType()) {
            case CREATE_CELL:
                CellCreateMessage ccm = (CellCreateMessage) editMessage;
                if (ccm.getParentCellID() != null) {
                    out = crm.getCellResource(ccm.getParentCellID());
                }
                break;
            case DELETE_CELL:
                {
                    // delete requires permission from both the cell being
                    // deleted and the parent cell
                    CellDeleteMessage cdm = (CellDeleteMessage) editMessage;
                    CellMO deleteMO = CellManagerMO.getCell(cdm.getCellID());
                    if (deleteMO == null ||
                            deleteMO.getCellID().equals(CellID.getEnvironmentCellID()))
                    {
                        break;
                    }
                    Resource child = crm.getCellResource(cdm.getCellID());
                    Resource parent = null;

                    // get the cell's parent, if any
                    CellMO parentMO = deleteMO.getParent();
                    if (parentMO != null) {
                        parent = crm.getCellResource(parentMO.getCellID());
                    }

                    // now create a delete resource with child & parent
                    if (child != null || parent != null) {
                        out = new DeleteCellResource(cdm.getCellID().toString(),
                                                     child, parent);
                    }
                }
                break;
            case DUPLICATE_CELL:
                CellDuplicateMessage cnm = (CellDuplicateMessage) editMessage;
                CellMO dupMO = CellManagerMO.getCell(cnm.getCellID());
                if (dupMO != null && dupMO.getParent() != null) {
                    out = crm.getCellResource(dupMO.getParent().getCellID());
                }
                break;

            case REPARENT_CELL:
                {
                    CellReparentMessage msg = (CellReparentMessage) editMessage;

                    CellMO childMO = CellManagerMO.getCell(msg.getCellID());
                    if (childMO==null)
                        break;

                    Resource child = crm.getCellResource(msg.getCellID());
                    Resource oldParent = null;
                    Resource newParent = null;

                    CellMO oldParentMO = childMO.getParent();
                    if (oldParentMO!=null)
                        oldParent = crm.getCellResource(oldParentMO.getCellID());

                    CellMO newParentMO = CellManagerMO.getCell(msg.getParentCellID());
                    if (newParentMO!=null)
                        newParent = crm.getCellResource(msg.getParentCellID());

                    if (child!=null || oldParent!=null || newParent!=null)
                        out = new ReparentCellResource(msg.getCellID().toString(), child, oldParent, newParent);
                }
                break;

        }

        return out;
    }

    public void messageReceived(WonderlandClientSender sender, WonderlandClientID clientID, Message message) {
       
        Logger logger = Logger.getLogger(CellEditConnectionHandler.class.getName());

        CellEditMessage editMessage = (CellEditMessage)message;
        if (editMessage.getEditType() == EditType.CREATE_CELL) {

            // The create message contains a setup class of the cell setup
            // information. Simply parse this stream, which will result in a
            // setup class of the property type.
            CellServerState setup = ((CellCreateMessage)editMessage).getCellSetup();
           
            // Fetch the server-side cell class name and create the cell
            String className = setup.getServerClassName();
            logger.fine("Attempting to load cell mo: " + className);
            CellMO cellMO = CellMOFactory.loadCellMO(className);
            if (cellMO == null) {
                /* Log a warning and move onto the next cell */
                logger.warning("Unable to load cell MO: " + className );
                sender.send(clientID, new ErrorMessage(editMessage.getMessageID(),
                        "Unable to load cell MO: " + className));
                return;
            }

            // Find the parent cell (if any)
            CellMO parent = null;
            CellID parentCellID = ((CellCreateMessage)editMessage).getParentCellID();
            if (parentCellID != null) {
                parent = CellManagerMO.getCell(parentCellID);
            }

            /* Call the cell's setup method */
            try {
                cellMO.setServerState(setup);

                if (parent == null) {
                    WonderlandContext.getCellManager().insertCellInWorld(cellMO);
                } else {
                    parent.addChild(cellMO);
                }
                //everything worked okay. send response message
                sender.send(clientID, new CellCreatedMessage(editMessage.getMessageID(), cellMO.getCellID()));

            } catch (ClassCastException cce) {
                logger.log(Level.WARNING, "Error setting up new cell " +
                        cellMO.getName() + " of type " +
                        cellMO.getClass() + ", it does not implement " +
                        "BeanSetupMO.", cce);
                sender.send(clientID,
                        new ErrorMessage(editMessage.getMessageID(),cce));
                return;
            } catch (MultipleParentException excp) {
                logger.log(Level.WARNING, "Error adding new cell " + cellMO.getName()
                        + " of type " + cellMO.getClass() + ", has multiple parents", excp);
                sender.send(clientID,
                        new ErrorMessage(editMessage.getMessageID(), excp));
                return;
            }
        }
        else if (editMessage.getEditType() == EditType.DELETE_CELL) {
            // Find the cell object given the ID of the cell. If the ID is
            // invalid, we just log an error and return.
            CellID cellID = ((CellDeleteMessage)editMessage).getCellID();
            CellMO cellMO = CellManagerMO.getCell(cellID);
            if (cellMO == null) {
                logger.warning("No cell found to delete with cell id " + cellID);
                return;
            }

            // Find out the parent of the cell. This may be null if the cell is
            // at the world root. This determines from where to remove the cell
            CellMO parentMO = cellMO.getParent();
            if (parentMO != null) {
                parentMO.removeChild(cellMO);
            }
            else {
                CellManagerMO.getCellManager().removeCellFromWorld(cellMO);
            }
        }
        else if (editMessage.getEditType() == EditType.DUPLICATE_CELL) {
            // Find the cell object given the ID of the cell. If the ID is
            // invalid, we just log an error and return.
            CellID cellID = ((CellDuplicateMessage)editMessage).getCellID();
            CellMO cellMO = CellManagerMO.getCell(cellID);
            if (cellMO == null) {
                logger.warning("No cell found to duplicate with cell id " + cellID);
                sender.send(clientID, new ErrorMessage(editMessage.getMessageID(),
                        "No cell found to duplicate with cell id " + cellID));
                return;
            }
            CellMO parentCellMO = cellMO.getParent();

            // We need to fetch the current state of the cell from the cell we
            // wish to duplicate. We also need the name of the server-side cell
            // class
            CellServerState state = cellMO.getServerState(null);
            String className = state.getServerClassName();

            // Attempt to create the cell using the cell factory and the class
            // name of the server-side cell.
            CellMO newCellMO = CellMOFactory.loadCellMO(className);
            if (newCellMO == null) {
                /* Log a warning and move onto the next cell */
                logger.warning("Unable to duplicate cell MO: " + className);
                sender.send(clientID, new ErrorMessage(editMessage.getMessageID(),
                        "Unable to duplicate cell MO: " + className));
                return;
            }

            // We want to modify the position of the new cell slight, so we
            // offset the position by (1, 1, 1).
            PositionComponentServerState position = (PositionComponentServerState)state.getComponentServerState(PositionComponentServerState.class);
            if (position == null) {
                logger.warning("Unable to determine the position of the cell " +
                        "to duplicate with id " + cellID);
                sender.send(clientID, new ErrorMessage(editMessage.getMessageID(),
                        "Unable to determine the position of the cell " +
                        "to duplicate with id " + cellID));
                return;
            }
            Vector3f offset = new Vector3f(1, 0, 1);
            Vector3f origin = position.getTranslation();
            position.setTranslation(offset.add(origin));
            state.addComponentServerState(position);

            // Set the desired name of the cell contained within the message
            state.setName(((CellDuplicateMessage)editMessage).getCellName());
           
            // Set the state of the new cell and add it to the same parent as
            // the old cell. If the old parent cell is null, we just insert it
            // as root.
            newCellMO.setServerState(state);
            try {
                if (parentCellMO == null) {
                    WonderlandContext.getCellManager().insertCellInWorld(newCellMO);
                }
                else {
                    parentCellMO.addChild(newCellMO);
                }
                sender.send(clientID, new CellCreatedMessage(editMessage.getMessageID(), newCellMO.getCellID()));
            } catch (MultipleParentException excp) {
                logger.log(Level.WARNING, "Error duplicating cell " +
                        newCellMO.getName() + " of type " + newCellMO.getClass() +
                        ", has multiple parents", excp);
                sender.send(clientID, new ErrorMessage(editMessage.getMessageID(),
                        excp));
                return;
            }
        }
        else if (editMessage.getEditType() == EditType.REPARENT_CELL) {
            // Find the cell id to move and the new parent id
            CellID cellID = ((CellReparentMessage)editMessage).getCellID();
            CellID newParentID = ((CellReparentMessage)editMessage).getParentCellID();

            // Figure out the new local coordinates of the cell wrt the new
            // parent

            // Change the parent cell
            CellMO child = CellManagerMO.getCell(cellID);
            CellMO oldParent = child.getParent();
            CellMO newParent = CellManagerMO.getCell(newParentID);

            if (oldParent == null) {
                CellManagerMO.getCellManager().removeCellFromWorld(child);
            } else {
                oldParent.removeChild(child);
            }

            CellTransform childTransform = ((CellReparentMessage) editMessage).getChildCellTransform();
            if (childTransform != null)
                child.setLocalTransform(childTransform);

            if (newParent == null) {
                try {
                    CellManagerMO.getCellManager().insertCellInWorld(child);
                } catch (MultipleParentException ex) {
                    Logger.getLogger(CellEditConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else {
                try {
                    newParent.addChild(child);
                } catch (MultipleParentException ex) {
                    Logger.getLogger(CellEditConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    public boolean messageRejected(WonderlandClientSender sender,
                                   WonderlandClientID clientID, Message message,
                                   Set<Action> requested, Set<Action> granted)
    {
        Logger logger = Logger.getLogger(CellEditConnectionHandler.class.getName());
        logger.warning("Message " + message + " rejected from " + clientID);

        return true;
    }

    /**
     * Returns the base URL of the web server.
     */
    private static URL getWebServerURL() throws MalformedURLException {
        return new URL(System.getProperty("wonderland.web.server.url"));
    }
   
    /**
     * Given a base URL of the server (e.g. http://localhost:8080) returns
     * the server name and port as a string (e.g. localhost:8080). Returns null
     * if the host name is not present.
     *
     * @return <server name>:<port>
     * @throw MalformedURLException If the given string URL is invalid
     */
    private static String getServerFromURL(URL serverURL) {
        String host = serverURL.getHost();
        int port = serverURL.getPort();
       
        if (host == null) {
            return null;
        }
        else if (port == -1) {
            return host;
        }
        return host + ":" + port;
    }

    /**
     * Deleting requires permission to modify the cell being deleted as well
     * as permission to modify the children of the parent cell, if any.  This
     * resource provides that mapping.  All request are mapped to the child
     * except requests for the ModifyChildren which are mapped to the parent.
     */
    private static class DeleteCellResource implements Resource {
        private String cellID;
        private Resource child;
        private Resource parent;

        public DeleteCellResource(String cellID, Resource child,
                                  Resource parent)
        {
            this.cellID = cellID;
            this.child = child;
            this.parent = parent;
        }

        public String getId() {
            return "DeleteCell_" + cellID;
        }

        public Result request(WonderlandIdentity identity, Action action) {
            if (action instanceof ChildrenAction && parent != null) {
                // route to parent (if any)
                return parent.request(identity, action);
            } else if (!(action instanceof ChildrenAction) && child != null) {
                // route to child (if any)
                return child.request(identity, action);
            }

            // if we got here, there is no-one to route to -- just grant the
            // request
            return Result.GRANT;
        }

        public boolean request(WonderlandIdentity identity, Action action,
                               ComponentRegistry registry)
        {
            if (action instanceof ChildrenAction && parent != null) {
                // route to parent (if any)
                return parent.request(identity, action, registry);
            } else if (!(action instanceof ChildrenAction) && child != null) {
                // route to child (if any)
                return child.request(identity, action, registry);
            }

            // if we got here, there is no-one to route to -- just grant the
            // request
            return true;
        }
    }

    private static class ReparentCellResource implements Resource {
        private String cellID;
        private Resource child;
        private Resource oldParent;
        private Resource newParent;

        public ReparentCellResource(String cellID, Resource child,
                                  Resource oldParent,
                                  Resource newParent)
        {
            this.cellID = cellID;
            this.child = child;
            this.oldParent = oldParent;
            this.newParent = newParent;
        }

        public String getId() {
            return "ReparentCell_" + cellID;
        }

        public Result request(WonderlandIdentity identity, Action action) {
            if (action instanceof ChildrenAction && oldParent != null) {
                Result tmp = Result.GRANT;
                if (oldParent!=null )
                    tmp = oldParent.request(identity, action);
                Result tmp2 = Result.GRANT;
                if (newParent!=null)
                    tmp2 = newParent.request(identity, action);

                return Result.combine(tmp, tmp2);
            } else if (!(action instanceof ChildrenAction) && child != null) {
                // route to child (if any)
                return child.request(identity, action);
            }

            // if we got here, there is no-one to route to -- just grant the
            // request
            return Result.GRANT;
        }

        public boolean request(WonderlandIdentity identity, Action action,
                               ComponentRegistry registry)
        {
            if (action instanceof ChildrenAction) {
                boolean tmp = true;
                if (oldParent!=null)
                    tmp = oldParent.request(identity, action, registry);
                boolean tmp2 = true;
                if (newParent!=null)
                    tmp2 = newParent.request(identity, action, registry);
                return (tmp && tmp2);
            } else if (!(action instanceof ChildrenAction) && child != null) {
                // route to child (if any)
                return child.request(identity, action, registry);
            }

            // if we got here, there is no-one to route to -- just grant the
            // request
            return true;
        }
    }
}
TOP

Related Classes of org.jdesktop.wonderland.server.cell.CellEditConnectionHandler$ReparentCellResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.