org.fcrepo.server.security.xacml.util.RELSRelationshipResolver Maven / Gradle / Ivy
/**
*
*/
package org.fcrepo.server.security.xacml.util;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.fcrepo.common.Constants;
import org.fcrepo.common.MalformedPIDException;
import org.fcrepo.common.PID;
import org.fcrepo.server.Context;
import org.fcrepo.server.ReadOnlyContext;
import org.fcrepo.server.Server;
import org.fcrepo.server.errors.ObjectNotInLowlevelStorageException;
import org.fcrepo.server.errors.ServerException;
import org.fcrepo.server.management.Management;
import org.fcrepo.server.security.xacml.MelcoeXacmlException;
import org.fcrepo.server.storage.types.RelationshipTuple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A RelationshipResolver that resolves relationships via
* {@link Management#getRelationships(org.fcrepo.server.Context, String, String)}.
*
* @author Edwin Shin
*/
public class RELSRelationshipResolver extends RelationshipResolverBase
implements RelationshipResolver {
private static final Logger logger =
LoggerFactory.getLogger(RELSRelationshipResolver.class);
private Management apim;
private Context fedoraCtx;
public RELSRelationshipResolver() {
this(new HashMap()) ;
}
public RELSRelationshipResolver(Map options) {
super(options);
}
@Override
public Map> getRelationships(String subject,
String relationship)
throws MelcoeXacmlException {
if (subject == null){
logger.warn("Invalid subject argument for getRelationships. Subject cannot be null");
return new HashMap>();
}
String subjectURI;
if ((subjectURI = getFedoraResourceURI(subject)) == null) {
logger.warn("Invalid subject argument for getRelationships: " + subject + ". Should be pid or datastream (URI form optional");
return new HashMap>();
}
RelationshipTuple[] tuples;
try {
tuples =
getApiM().getRelationships(getContext(),
subjectURI,
relationship);
} catch (ServerException e) {
if (e instanceof ObjectNotInLowlevelStorageException) {
// querying a subject that doesn't exist
return new HashMap>();
} else {
throw new MelcoeXacmlException(e.getMessage(), e);
}
}
Map> relationships =
new HashMap>();
for (RelationshipTuple t : tuples) {
String p = t.predicate;
String o = t.object;
Set values = relationships.get(p);
if (values == null) {
values = new HashSet();
}
values.add(o);
relationships.put(p, values);
}
return relationships;
}
private Management getApiM() {
if (apim != null) {
return apim;
}
Server server;
try {
server = Server.getInstance(new File(Constants.FEDORA_HOME), false);
} catch (Exception e) {
logger.error(e.getMessage());
throw new RuntimeException("Failed getting instance of Fedora", e);
}
apim =
(Management) server
.getModule("org.fcrepo.server.management.Management");
return apim;
}
private Context getContext() throws MelcoeXacmlException {
if (fedoraCtx != null) {
return fedoraCtx;
}
try {
fedoraCtx =
ReadOnlyContext.getContext(null,
null,
null,
ReadOnlyContext.DO_OP);
} catch (Exception e) {
throw new MelcoeXacmlException(e.getMessage(), e);
}
return fedoraCtx;
}
@Override
public Map> getRelationships(String subject)
throws MelcoeXacmlException {
return getRelationships(subject, null);
}
@Override
public String buildRESTParentHierarchy(String pid)
throws MelcoeXacmlException {
Set parents = getParents(pid);
if (parents == null || parents.size() == 0) {
return "/" + pid;
}
String[] parentArray = parents.toArray(new String[parents.size()]);
// FIXME: always uses the first parent. If/when we allow multiple hierarchies this needs changing to return all hierarchies
return buildRESTParentHierarchy(parentArray[0]) + "/" + pid;
}
protected Set getParents(String pid) throws MelcoeXacmlException {
logger.debug("Obtaining parents for: {}", pid);
Set parentPIDs = new HashSet();
// repository "object" has no parents
if (pid.equalsIgnoreCase(Constants.FEDORA_REPOSITORY_PID.uri)) {
return parentPIDs;
}
if (childRelationships != null) {
logger.warn("Parent-child relationships have been specified, but the specified relationship resolver is not able to resolve these");
}
// if more than one relationship specified, get all relationships for object in one go
// otherwise constrain on the single relationship
// means object/rels datastreams only get parsed once - a separate
// query for each relationship would mean a separate object parse (and RELS-* parse) for each relationship
Map> allRelationships;
if (parentRelationships.size() == 1) {
allRelationships = getRelationships(pid, parentRelationships.get(0));
} else {
allRelationships = getRelationships(pid);
}
for (String rel : allRelationships.keySet()) {
// is it one of the child-parent relationships?
if (parentRelationships.contains(rel)) {
Set parents = allRelationships.get(rel);
if (parents != null) {
for (String parent : parents) {
try {
PID parentPID = new PID(parent);
// we want the parents in demo:123 form, not info:fedora/demo:123
parentPIDs.add(parentPID.toString());
if (logger.isDebugEnabled()) {
logger.debug("added parent " + parentPID.toString());
}
} catch (MalformedPIDException e) {
// target of relationship isn't a PID
logger.warn("Triple " + pid + " " + rel + " " + parent + " does not have a digital object as its target");
}
}
}
}
}
return parentPIDs;
}
@Override
public Set getAttributesFromQuery(String query,
String queryLang,
String variable)
throws MelcoeXacmlException {
// can't run queries for a RELS relationship resolver
logger.warn("RELS relationship resolver does not support retrieving attributes with an RI query");
return Collections.emptySet();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy