/** * Copyright (C) 2010-2017 Structr GmbH * * This file is part of Structr <http://structr.org>. * * Structr is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * Structr 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Structr. If not, see <http://www.gnu.org/licenses/>. */ package org.structr.websocket.command; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.structr.common.Permission; import org.structr.common.error.FrameworkException; import org.structr.core.GraphObject; import org.structr.core.app.App; import org.structr.core.app.StructrApp; import org.structr.core.entity.AbstractNode; import org.structr.core.entity.LinkedTreeNode; import org.structr.core.graph.NodeInterface; import org.structr.core.graph.RelationshipInterface; import org.structr.core.graph.TransactionCommand; import org.structr.core.graph.Tx; import org.structr.core.property.PropertyMap; import org.structr.websocket.StructrWebSocket; import org.structr.websocket.message.MessageBuilder; import org.structr.websocket.message.WebSocketMessage; //~--- classes ---------------------------------------------------------------- /** * * */ public class UpdateCommand extends AbstractCommand { private static final Logger logger = LoggerFactory.getLogger(UpdateCommand.class.getName()); static { StructrWebSocket.addCommand(UpdateCommand.class); } private int count = 0; //~--- methods -------------------------------------------------------- @Override public void processMessage(final WebSocketMessage webSocketData) throws FrameworkException { final App app = StructrApp.getInstance(getWebSocket().getSecurityContext()); final Boolean recValue = (Boolean) webSocketData.getNodeData().get("recursive"); final boolean rec = recValue != null ? recValue : false; final GraphObject obj = getGraphObject(webSocketData.getId()); if (obj == null) { logger.warn("Graph object with uuid {} not found.", webSocketData.getId()); getWebSocket().send(MessageBuilder.status().code(404).build(), true); return; } webSocketData.getNodeData().remove("recursive"); // If it's a node, check permissions try (final Tx tx = app.tx()) { if (obj instanceof AbstractNode) { final AbstractNode node = (AbstractNode) obj; if (!node.isGranted(Permission.write, getWebSocket().getSecurityContext())) { getWebSocket().send(MessageBuilder.status().message("No write permission").code(400).build(), true); logger.warn("No write permission for {} on {}", new Object[]{getWebSocket().getCurrentUser().toString(), obj.toString()}); tx.success(); return; } tx.success(); } } final Set<GraphObject> entities = new LinkedHashSet<>(); PropertyMap properties = null; try (final Tx tx = app.tx()) { collectEntities(entities, obj, null, rec); properties = PropertyMap.inputTypeToJavaType(this.getWebSocket().getSecurityContext(), obj.getClass(), webSocketData.getNodeData()); tx.success(); } final Iterator<GraphObject> iterator = entities.iterator(); while (iterator.hasNext()) { count = 0; try (final Tx tx = app.tx()) { while (iterator.hasNext() && count++ < 100) { setProperties(iterator.next(), properties, true); } // commit and close transaction tx.success(); } } } @Override public boolean requiresEnclosingTransaction() { return false; } @Override public String getCommand() { return "UPDATE"; } //~--- set methods ---------------------------------------------------- private void setProperties(final GraphObject obj, final PropertyMap properties, final boolean rec) throws FrameworkException { obj.setProperties(obj.getSecurityContext(), properties); if (obj instanceof NodeInterface) { TransactionCommand.registerNodeCallback((NodeInterface) obj, callback); } else if (obj instanceof RelationshipInterface) { TransactionCommand.registerRelCallback((RelationshipInterface) obj, callback); } } private void collectEntities(final Set<GraphObject> entities, final GraphObject obj, final PropertyMap properties, final boolean rec) throws FrameworkException { entities.add(obj); if (rec && obj instanceof LinkedTreeNode) { LinkedTreeNode node = (LinkedTreeNode) obj; for (Object child : node.treeGetChildren()) { collectEntities(entities, (GraphObject) child, properties, rec); } } } }