/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source: /cvsroot/slrp/boca/com.ibm.adtech.boca.model/src/com/ibm/adtech/boca/model/repository/update/ServerUpdatesProcessor.java,v $ * Created by: Matthew Roy ( <a href="mailto:mroy@us.ibm.com">mroy@us.ibm.com </a>) * Created on: 5/5/2006 * Revision: $Id: ServerUpdatesProcessor.java 180 2007-07-31 14:24:13Z mroy $ * * Contributors: * IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.datasource.update; import java.util.Collection; import java.util.HashMap; import java.util.Set; import org.openanzo.datasource.IAuthorizationService; import org.openanzo.datasource.IServerQuadStore; import org.openanzo.exceptions.AnzoException; import org.openanzo.exceptions.ExceptionConstants; import org.openanzo.ontologies.openanzo.Dataset; import org.openanzo.ontologies.openanzo.NamedGraph; import org.openanzo.rdf.Constants; import org.openanzo.rdf.Statement; import org.openanzo.rdf.URI; import org.openanzo.rdf.Constants.GRAPHS; import org.openanzo.rdf.Constants.NAMESPACES; import org.openanzo.rdf.datatype.TypeMaps; import org.openanzo.rdf.utils.Collections; import org.openanzo.rdf.utils.UriGenerator; import org.openanzo.rdf.vocabulary.RDF; import org.openanzo.services.Privilege; /** * ServerUpdatesProcessor handles updates sent from the client, and applies them to the server * * @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>) * */ public class ServerQuadStoreUpdateHandler implements MultiStageUpdatesProcessor.NamedGraphUpdateHandler { //private static final Logger log = LoggerFactory.getLogger(ServerQuadStoreUpdateHandler.class); private final IServerQuadStore quadStore; private final ServerUpdateTransaction currentTransactionUpdateResults; private final boolean isReseting; private final HashMap<URI, Boolean> canAdd = new HashMap<URI, Boolean>(); private final HashMap<URI, Boolean> canRemove = new HashMap<URI, Boolean>(); private Boolean canInsertNamedGraphs = null; private Boolean canRemoveNamedGraphs = null; private final IAuthorizationService authorizationService; private final HashMap<URI, URI> namedGraphUUID = new HashMap<URI, URI>(); /** * ServerQuadStoreUpdateHandler * * @param quadStore * @param currentTransactionUpdateResults * @param authorizationService * @param isReseting */ public ServerQuadStoreUpdateHandler(IServerQuadStore quadStore, ServerUpdateTransaction currentTransactionUpdateResults, IAuthorizationService authorizationService, boolean isReseting) { this.quadStore = quadStore; this.currentTransactionUpdateResults = currentTransactionUpdateResults; this.isReseting = isReseting; this.authorizationService = authorizationService; } public boolean handleStatement(boolean additions, boolean noAclCheck, Statement statement) throws AnzoException { if (currentTransactionUpdateResults.hasError()) { return false; } if (additions) { if (noAclCheck || isReseting || currentTransactionUpdateResults.getServerPrincipal().isSysadmin() || checkAddAccess(statement.getNamedGraphUri())) { quadStore.add(statement); return true; } else { throw new AnzoException(ExceptionConstants.DATASOURCE.NO_ADD_ERROR, statement.getSubject().toString(), statement.getPredicate().toString(), statement.getObject().toString(), statement.getNamedGraphUri().toString()); } } else { if (noAclCheck || isReseting || currentTransactionUpdateResults.getServerPrincipal().isSysadmin() || checkRemoveAccess(statement.getNamedGraphUri())) { quadStore.remove(statement); return true; } else { throw new AnzoException(ExceptionConstants.DATASOURCE.NO_REMOVE_ERROR, statement.getSubject().toString(), statement.getPredicate().toString(), statement.getObject().toString(), statement.getNamedGraphUri().toString()); } } } public boolean handleAddPrivilege(Statement statement) throws AnzoException { currentTransactionUpdateResults.getAclAdditions().add(statement); URI namedGraphUri = (URI) statement.getSubject(); URI privilege = statement.getPredicate(); URI role = (URI) statement.getObject(); if (privilege.equals(NamedGraph.canBeAddedToByProperty) && currentTransactionUpdateResults.getServerPrincipal().getRoles().contains(role)) { canAdd.put(namedGraphUri, Boolean.valueOf(true)); } else if (privilege.equals(NamedGraph.canBeRemovedFromByProperty) && currentTransactionUpdateResults.getServerPrincipal().getRoles().contains(role)) { canRemove.put(namedGraphUri, Boolean.valueOf(true)); } quadStore.addAcl(namedGraphUri, role, privilege.equals(NamedGraph.canBeAddedToByProperty) ? Privilege.ADD : privilege.equals(NamedGraph.canBeRemovedFromByProperty) ? Privilege.REMOVE : Privilege.READ); return true; } public boolean handleRemovePrivilege(Statement statement) throws AnzoException { currentTransactionUpdateResults.getAclRemovals().add(statement); URI namedGraphUri = (URI) statement.getSubject(); URI privilege = statement.getPredicate(); URI role = (URI) statement.getObject(); if (privilege.equals(NamedGraph.canBeAddedToByProperty) && currentTransactionUpdateResults.getServerPrincipal().getRoles().contains(role)) { canAdd.remove(namedGraphUri); } else if (privilege.equals(NamedGraph.canBeRemovedFromByProperty) && currentTransactionUpdateResults.getServerPrincipal().getRoles().contains(role)) { canRemove.remove(namedGraphUri); } quadStore.removeAcl(namedGraphUri, role, privilege.equals(NamedGraph.canBeAddedToByProperty) ? Privilege.ADD : privilege.equals(NamedGraph.canBeRemovedFromByProperty) ? Privilege.REMOVE : Privilege.READ); return true; } private URI getNamedGraphUUID(URI namedGraphUri) throws AnzoException { URI uuid = namedGraphUUID.get(namedGraphUri); if (uuid == null) { uuid = quadStore.getNamedGraphUUID(namedGraphUri); if (uuid != null) { namedGraphUUID.put(namedGraphUri, uuid); } } return uuid; } public boolean handleAddNamedGraph(URI namedGraphUri, URI metadataGraphUri, MultiStageUpdatesProcessor.AclSet aclSet, MultiStageUpdatesProcessor.AclSet metaAclSet, boolean revisioned, boolean persisted, Collection<Statement> extraStatements) throws AnzoException { if (currentTransactionUpdateResults.hasError()) { return false; } if (namedGraphUri.toString().startsWith(NAMESPACES.NAMEDGRAPH_PREFIX + "reserved/")) { throw new AnzoException(ExceptionConstants.DATASOURCE.NO_ADD_RESERVED_URI, namedGraphUri.toString()); } URI uuid = getNamedGraphUUID(namedGraphUri); boolean canAddTo = false; if (uuid == null) { boolean canAdd = isReseting || currentTransactionUpdateResults.getServerPrincipal().isSysadmin() || checkInsertNamedGraphAccess(GRAPHS.GRAPHS_DATASET); if (canAdd) { if (metadataGraphUri == null) { metadataGraphUri = UriGenerator.generateMetadataGraphUri(namedGraphUri); } this.canAdd.put(namedGraphUri, true); this.canAdd.put(metadataGraphUri, true); this.canRemove.put(namedGraphUri, true); this.canRemove.put(metadataGraphUri, true); uuid = (revisioned) ? UriGenerator.generateNamedGraphUUIDRevisioned() : UriGenerator.generateNamedGraphUUIDNonRevisioned(); quadStore.addNewNamedGraph(namedGraphUri, metadataGraphUri, uuid, revisioned ? NamedGraphType.REVISIONED : (persisted ? NamedGraphType.NON_REVISIONED_PERSISTED : NamedGraphType.NON_REVISIONED_NON_PERSISTED)); if (!namedGraphUri.equals(GRAPHS.GRAPHS_DATASET) && !namedGraphUri.equals(GRAPHS.METADATA_GRAPHS_DATASET)) { handleStatement(true, true, Constants.valueFactory.createStatement(GRAPHS.GRAPHS_DATASET, Dataset.namedGraphProperty, namedGraphUri, GRAPHS.GRAPHS_DATASET)); handleStatement(true, true, Constants.valueFactory.createStatement(GRAPHS.METADATA_GRAPHS_DATASET, Dataset.namedGraphProperty, metadataGraphUri, GRAPHS.METADATA_GRAPHS_DATASET)); } URI userUri = null; if (isReseting) { userUri = (currentTransactionUpdateResults.getServerPrincipal() == null) ? Constants.DEFAULT_INTERNAL_USER : currentTransactionUpdateResults.getServerPrincipal().getUserURI(); } else { userUri = currentTransactionUpdateResults.getServerPrincipal().getUserURI(); } namedGraphUUID.put(namedGraphUri, uuid); quadStore.add(Constants.valueFactory.createStatement(namedGraphUri, RDF.TYPE, NamedGraph.TYPE, metadataGraphUri)); quadStore.add(Constants.valueFactory.createStatement(namedGraphUri, NamedGraph.hasMetadataGraphProperty, metadataGraphUri, metadataGraphUri)); quadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.uuidProperty, uuid, metadataGraphUri)); quadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.createdProperty, Constants.valueFactory.createTypedLiteral(TypeMaps.getXMLCaledar(currentTransactionUpdateResults.getTransactionTimestamp())), metadataGraphUri)); quadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.createdByProperty, userUri, metadataGraphUri)); quadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.datasourceProperty, quadStore.getInstanceURI(), metadataGraphUri)); if (!metaAclSet.aclMap.containsKey(NamedGraph.canBeReadByProperty) && !Constants.DEFAULT_SYSADMIN.equals(currentTransactionUpdateResults.getServerPrincipal().getUserURI())) { handleStatement(true, true, Constants.valueFactory.createStatement(metadataGraphUri, NamedGraph.canBeReadByProperty, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), metadataGraphUri)); quadStore.addAcl(metadataGraphUri, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), Privilege.READ); } if (!metaAclSet.aclMap.containsKey(NamedGraph.canBeAddedToByProperty) && !Constants.DEFAULT_SYSADMIN.equals(currentTransactionUpdateResults.getServerPrincipal().getUserURI())) { handleStatement(true, true, Constants.valueFactory.createStatement(metadataGraphUri, NamedGraph.canBeAddedToByProperty, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), metadataGraphUri)); quadStore.addAcl(metadataGraphUri, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), Privilege.ADD); } if (!metaAclSet.aclMap.containsKey(NamedGraph.canBeRemovedFromByProperty) && !Constants.DEFAULT_SYSADMIN.equals(currentTransactionUpdateResults.getServerPrincipal().getUserURI())) { handleStatement(true, true, Constants.valueFactory.createStatement(metadataGraphUri, NamedGraph.canBeRemovedFromByProperty, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), metadataGraphUri)); quadStore.addAcl(metadataGraphUri, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), Privilege.REMOVE); } if (!aclSet.aclMap.containsKey(NamedGraph.canBeReadByProperty) && !Constants.DEFAULT_SYSADMIN.equals(currentTransactionUpdateResults.getServerPrincipal().getUserURI())) { handleStatement(true, true, Constants.valueFactory.createStatement(namedGraphUri, NamedGraph.canBeReadByProperty, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), metadataGraphUri)); quadStore.addAcl(namedGraphUri, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), Privilege.READ); } if (!aclSet.aclMap.containsKey(NamedGraph.canBeAddedToByProperty) && !Constants.DEFAULT_SYSADMIN.equals(currentTransactionUpdateResults.getServerPrincipal().getUserURI())) { handleStatement(true, true, Constants.valueFactory.createStatement(namedGraphUri, NamedGraph.canBeAddedToByProperty, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), metadataGraphUri)); quadStore.addAcl(namedGraphUri, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), Privilege.ADD); } if (!aclSet.aclMap.containsKey(NamedGraph.canBeRemovedFromByProperty) && !Constants.DEFAULT_SYSADMIN.equals(currentTransactionUpdateResults.getServerPrincipal().getUserURI())) { handleStatement(true, true, Constants.valueFactory.createStatement(namedGraphUri, NamedGraph.canBeRemovedFromByProperty, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), metadataGraphUri)); quadStore.addAcl(namedGraphUri, currentTransactionUpdateResults.getServerPrincipal().getUserURI(), Privilege.REMOVE); } for (Statement stmt : aclSet.aclMap.values()) { quadStore.addAcl((URI) stmt.getSubject(), (URI) stmt.getObject(), stmt.getPredicate().equals(NamedGraph.canBeAddedToByProperty) ? Privilege.ADD : stmt.getPredicate().equals(NamedGraph.canBeRemovedFromByProperty) ? Privilege.REMOVE : Privilege.READ); } for (Statement stmt : metaAclSet.aclMap.values()) { quadStore.addAcl((URI) stmt.getSubject(), (URI) stmt.getObject(), stmt.getPredicate().equals(NamedGraph.canBeAddedToByProperty) ? Privilege.ADD : stmt.getPredicate().equals(NamedGraph.canBeRemovedFromByProperty) ? Privilege.REMOVE : Privilege.READ); } canAddTo = true; } else { throw new AnzoException(ExceptionConstants.DATASOURCE.NO_INSERT_NAMEDGRAPH_ACL_ERROR, namedGraphUri.toString()); } } else { if (metadataGraphUri == null) { metadataGraphUri = UriGenerator.generateMetadataGraphUri(namedGraphUri); } canAddTo = isReseting || currentTransactionUpdateResults.getServerPrincipal().isSysadmin() || checkAddAccess(metadataGraphUri); for (Statement stmt : aclSet.aclMap.values()) { handleAddPrivilege(stmt); } for (Statement stmt : metaAclSet.aclMap.values()) { handleAddPrivilege(stmt); } } if (canAddTo && extraStatements != null) { for (Statement stmt : extraStatements) { handleStatement(true, true, stmt); } } return true; } public boolean handleRemoveNamedGraph(URI namedGraphUri) throws AnzoException { if (currentTransactionUpdateResults.hasError()) { return false; } URI uuid = getNamedGraphUUID(namedGraphUri); if (uuid != null) { URI metadataGraphUri = UriGenerator.generateMetadataGraphUri(namedGraphUri); if (isReseting || currentTransactionUpdateResults.getServerPrincipal().isSysadmin() || checkRemoveNamedGraphAccess(metadataGraphUri, GRAPHS.GRAPHS_DATASET)) { quadStore.removeNamedGraph(namedGraphUri, uuid, currentTransactionUpdateResults.getTransactionTimestamp()); if (!namedGraphUri.equals(GRAPHS.GRAPHS_DATASET) && !namedGraphUri.equals(GRAPHS.METADATA_GRAPHS_DATASET)) { handleStatement(false, true, Constants.valueFactory.createStatement(GRAPHS.GRAPHS_DATASET, Dataset.namedGraphProperty, namedGraphUri, GRAPHS.GRAPHS_DATASET)); handleStatement(false, true, Constants.valueFactory.createStatement(GRAPHS.METADATA_GRAPHS_DATASET, Dataset.namedGraphProperty, metadataGraphUri, GRAPHS.METADATA_GRAPHS_DATASET)); } return true; } else { throw new AnzoException(ExceptionConstants.DATASOURCE.NO_REMOVE_NAMEDGRAPH_ACL_ERROR, namedGraphUri.toString()); } } return false; } private boolean checkAddAccess(URI namedGraphUri) throws AnzoException { if (isReseting) { return true; } Boolean can = canAdd.get(namedGraphUri); if (can == null) { Set<URI> roles = authorizationService.getRolesForGraph(currentTransactionUpdateResults.getContext(), namedGraphUri, Privilege.ADD); can = Boolean.valueOf(Collections.memberOf(roles, currentTransactionUpdateResults.getServerPrincipal().getRoles())); canAdd.put(namedGraphUri, can); } return can; } private boolean checkRemoveAccess(URI namedGraphUri) throws AnzoException { if (isReseting) { return true; } Boolean can = canRemove.get(namedGraphUri); if (can == null) { Set<URI> roles = authorizationService.getRolesForGraph(currentTransactionUpdateResults.getContext(), namedGraphUri, Privilege.REMOVE); can = Boolean.valueOf(Collections.memberOf(roles, currentTransactionUpdateResults.getServerPrincipal().getRoles())); canRemove.put(namedGraphUri, can); } return can; } private Boolean checkInsertNamedGraphAccess(URI datasetUri) throws AnzoException { if (isReseting) { return true; } if (canInsertNamedGraphs == null) { Set<URI> roles = authorizationService.getRolesForGraph(currentTransactionUpdateResults.getContext(), datasetUri, Privilege.ADD); canInsertNamedGraphs = Boolean.valueOf(Collections.memberOf(roles, currentTransactionUpdateResults.getServerPrincipal().getRoles())); } return canInsertNamedGraphs; } private boolean checkRemoveNamedGraphAccess(URI namedGraphUri, URI datasetUri) throws AnzoException { if (isReseting) { return true; } if (currentTransactionUpdateResults.getContext().getOperationPrincipal().isSysadmin()) { return true; } if (canRemoveNamedGraphs == null) { Set<URI> roles = authorizationService.getRolesForGraph(currentTransactionUpdateResults.getContext(), datasetUri, Privilege.REMOVE); canRemoveNamedGraphs = Boolean.valueOf(Collections.memberOf(roles, currentTransactionUpdateResults.getServerPrincipal().getRoles())); } if (canRemoveNamedGraphs) { Boolean can = canRemove.get(namedGraphUri); if (can == null) { Set<URI> roles = authorizationService.getRolesForGraph(currentTransactionUpdateResults.getContext(), namedGraphUri, Privilege.REMOVE); can = Boolean.valueOf(Collections.memberOf(roles, currentTransactionUpdateResults.getServerPrincipal().getRoles())); canRemove.put(namedGraphUri, can); } return can; } return false; } }