NIHVIVO-3404 Restructure the SelfEditorRelationshipPolicy to use the model in the RequestedAction, instead of a model assigned at system startup time. Also, break out the logic into separate RelationshipChecker objects, for easier maintenance.

This commit is contained in:
j2blake 2012-04-03 16:13:41 +00:00
parent 657e63f580
commit d41c67b015
2 changed files with 173 additions and 149 deletions

View file

@ -2,30 +2,17 @@
package edu.cornell.mannlib.vitro.webapp.auth.policy.specialrelationships;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Selector;
import com.hp.hpl.jena.rdf.model.SimpleSelector;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.Lock;
import edu.cornell.mannlib.vitro.webapp.auth.policy.BasicPolicyDecision;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
/**
* A collection of building-block methods so we can code a policy based on the
@ -37,11 +24,9 @@ public abstract class AbstractRelationshipPolicy implements PolicyIface {
.getLog(AbstractRelationshipPolicy.class);
protected final ServletContext ctx;
protected final OntModel model;
public AbstractRelationshipPolicy(ServletContext ctx, OntModel model) {
public AbstractRelationshipPolicy(ServletContext ctx) {
this.ctx = ctx;
this.model = model;
}
protected boolean canModifyResource(String uri) {
@ -54,133 +39,6 @@ public abstract class AbstractRelationshipPolicy implements PolicyIface {
uri, RoleLevel.SELF);
}
protected boolean isResourceOfType(String resourceUri, String typeUri) {
Selector selector = createSelector(resourceUri,
VitroVocabulary.RDF_TYPE, typeUri);
StmtIterator stmts = null;
model.enterCriticalSection(Lock.READ);
try {
stmts = model.listStatements(selector);
if (stmts.hasNext()) {
log.debug("resource '" + resourceUri + "' is of type '"
+ typeUri + "'");
return true;
} else {
log.debug("resource '" + resourceUri + "' is not of type '"
+ typeUri + "'");
return false;
}
} finally {
if (stmts != null) {
stmts.close();
}
model.leaveCriticalSection();
}
}
protected List<String> getObjectsOfProperty(String resourceUri,
String propertyUri) {
List<String> list = new ArrayList<String>();
Selector selector = createSelector(resourceUri, propertyUri, null);
StmtIterator stmts = null;
model.enterCriticalSection(Lock.READ);
try {
stmts = model.listStatements(selector);
while (stmts.hasNext()) {
list.add(stmts.next().getObject().toString());
}
log.debug("Objects of property '" + propertyUri + "' on resource '"
+ resourceUri + "': " + list);
return list;
} finally {
if (stmts != null) {
stmts.close();
}
model.leaveCriticalSection();
}
}
protected List<String> getObjectsOfLinkedProperty(String resourceUri,
String linkUri, String propertyUri) {
List<String> list = new ArrayList<String>();
Selector selector = createSelector(resourceUri, linkUri, null);
StmtIterator stmts = null;
model.enterCriticalSection(Lock.READ);
try {
stmts = model.listStatements(selector);
while (stmts.hasNext()) {
RDFNode objectNode = stmts.next().getObject();
if (objectNode.isResource()) {
log.debug("found authorship for '" + resourceUri + "': "
+ objectNode);
list.addAll(getUrisOfAuthors(objectNode.asResource(),
propertyUri));
}
}
log.debug("Objects of linked properties '" + linkUri + "' ==> '"
+ propertyUri + "' on '" + resourceUri + "': " + list);
return list;
} finally {
if (stmts != null) {
stmts.close();
}
model.leaveCriticalSection();
}
}
/** Note that we must already be in a critical section! */
private List<String> getUrisOfAuthors(Resource authorship,
String propertyUri) {
List<String> list = new ArrayList<String>();
Selector selector = createSelector(authorship, propertyUri, null);
StmtIterator stmts = null;
try {
stmts = model.listStatements(selector);
while (stmts.hasNext()) {
list.add(stmts.next().getObject().toString());
}
return list;
} finally {
if (stmts != null) {
stmts.close();
}
}
}
protected Selector createSelector(String subjectUri, String predicateUri,
String objectUri) {
Resource subject = (subjectUri == null) ? null : model
.getResource(subjectUri);
return createSelector(subject, predicateUri, objectUri);
}
protected Selector createSelector(Resource subject, String predicateUri,
String objectUri) {
Property predicate = (predicateUri == null) ? null : model
.getProperty(predicateUri);
RDFNode object = (objectUri == null) ? null : model
.getResource(objectUri);
return new SimpleSelector(subject, predicate, object);
}
protected boolean anyUrisInCommon(List<String> userUris,
List<String> editorsOrAuthors) {
for (String userUri : userUris) {
if (editorsOrAuthors.contains(userUri)) {
return true;
}
}
return false;
}
protected PolicyDecision cantModifyResource(String uri) {
return inconclusiveDecision("No access to admin resources; cannot modify "
+ uri);
@ -201,10 +59,4 @@ public abstract class AbstractRelationshipPolicy implements PolicyIface {
.getSimpleName() + ": " + message);
}
/** An AUTHORIZED decision with a message like "PolicyClass: message". */
protected PolicyDecision authorizedDecision(String message) {
return new BasicPolicyDecision(Authorization.AUTHORIZED, getClass()
.getSimpleName() + ": " + message);
}
}

View file

@ -0,0 +1,172 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.policy.specialrelationships;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Selector;
import com.hp.hpl.jena.rdf.model.SimpleSelector;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.Lock;
import edu.cornell.mannlib.vitro.webapp.auth.policy.BasicPolicyDecision;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
/**
* Look for relationships within an OntModel. Types of resources, links between
* resources, and links between resources via a context node.
*
* Also provides some convenience methods for test lists of URIs and for
* creating PolicyDecisions.
*/
public class RelationshipChecker {
private static final Log log = LogFactory.getLog(RelationshipChecker.class);
private final OntModel ontModel;
public RelationshipChecker(OntModel ontModel) {
this.ontModel = ontModel;
}
/**
* Are there any URIs that appear in both of these lists?
*/
public boolean anyUrisInCommon(List<String> list1, List<String> list2) {
List<String> urisInCommon = new ArrayList<String>(list1);
urisInCommon.retainAll(list2);
return !urisInCommon.isEmpty();
}
/**
* Is this resource a member of this type? That is, is there an statement of
* the form: <resourceUri> rdfs:type <typeUri>
*/
public boolean isResourceOfType(String resourceUri, String typeUri) {
Selector selector = createSelector(resourceUri,
VitroVocabulary.RDF_TYPE, typeUri);
StmtIterator stmts = null;
ontModel.enterCriticalSection(Lock.READ);
try {
stmts = ontModel.listStatements(selector);
if (stmts.hasNext()) {
log.debug("resource '" + resourceUri + "' is of type '"
+ typeUri + "'");
return true;
} else {
log.debug("resource '" + resourceUri + "' is not of type '"
+ typeUri + "'");
return false;
}
} finally {
if (stmts != null) {
stmts.close();
}
ontModel.leaveCriticalSection();
}
}
/**
* Get a list of the object URIs that satisfy this statement:
*
* <resourceUri> <propertyUri> <objectUri>
*
* May return an empty list, but never returns null.
*/
public List<String> getObjectsOfProperty(String resourceUri,
String propertyUri) {
List<String> list = new ArrayList<String>();
Selector selector = createSelector(resourceUri, propertyUri, null);
StmtIterator stmts = null;
ontModel.enterCriticalSection(Lock.READ);
try {
stmts = ontModel.listStatements(selector);
while (stmts.hasNext()) {
list.add(stmts.next().getObject().toString());
}
log.debug("Objects of property '" + propertyUri + "' on resource '"
+ resourceUri + "': " + list);
return list;
} finally {
if (stmts != null) {
stmts.close();
}
ontModel.leaveCriticalSection();
}
}
/**
* Get a list of the object URIs that satisfy these statements:
*
* <resourceUri> <linkUri> <contextNodeUri>
*
* <contextNodeUri> <propertyUri> <objectUri>
*
* May return an empty list, but never returns null.
*/
public List<String> getObjectsOfLinkedProperty(String resourceUri,
String linkUri, String propertyUri) {
List<String> list = new ArrayList<String>();
Selector selector = createSelector(resourceUri, linkUri, null);
StmtIterator stmts = null;
ontModel.enterCriticalSection(Lock.READ);
try {
stmts = ontModel.listStatements(selector);
while (stmts.hasNext()) {
RDFNode contextNode = stmts.next().getObject();
if (contextNode.isResource()) {
log.debug("found context node for '" + resourceUri + "': "
+ contextNode);
list.addAll(getObjectsOfProperty(contextNode.asResource()
.getURI(), propertyUri));
}
}
log.debug("Objects of linked properties '" + linkUri + "' ==> '"
+ propertyUri + "' on '" + resourceUri + "': " + list);
return list;
} finally {
if (stmts != null) {
stmts.close();
}
ontModel.leaveCriticalSection();
}
}
public Selector createSelector(String subjectUri, String predicateUri,
String objectUri) {
Resource subject = (subjectUri == null) ? null : ontModel
.getResource(subjectUri);
return createSelector(subject, predicateUri, objectUri);
}
public Selector createSelector(Resource subject, String predicateUri,
String objectUri) {
Property predicate = (predicateUri == null) ? null : ontModel
.getProperty(predicateUri);
RDFNode object = (objectUri == null) ? null : ontModel
.getResource(objectUri);
return new SimpleSelector(subject, predicate, object);
}
/** An AUTHORIZED decision with a message like "PolicyClass: message". */
protected PolicyDecision authorizedDecision(String message) {
return new BasicPolicyDecision(Authorization.AUTHORIZED, getClass()
.getSimpleName() + ": " + message);
}
}