/*
* File: ContextHandlerImpl.java
*
* Copyright 2007 Macquarie E-Learning Centre Of Excellence
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package melcoe.fedora.pep;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import melcoe.xacml.MelcoeXacmlException;
import melcoe.xacml.util.ContextUtil;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.ResponseCtx;
import fedora.common.Constants;
/**
* @author nishen@melcoe.mq.edu.au
* @see ContextHandler
*/
public class ContextHandlerImpl
implements ContextHandler {
private static Logger log =
Logger.getLogger(ContextHandlerImpl.class.getName());
private ContextUtil contextUtil = null;
private static ContextHandler contextHandler = null;
private PDPClient client = null;
private EvaluationEngine evaluationEngine = null;
private ResponseCache responseCache = null;
/**
* The default constructor that initialises a new ContextHandler instance.
* This is a private constructor as this is a singleton class.
*
* @throws PEPException
*/
private ContextHandlerImpl()
throws PEPException {
super();
init();
}
/**
* @return an instance of a ContextHandler
* @throws PEPException
*/
public static ContextHandler getInstance() throws PEPException {
if (contextHandler == null) {
try {
contextHandler = new ContextHandlerImpl();
} catch (Exception e) {
log.error("Could not initialise ContextHandler.");
throw new PEPException("Could not initialise ContextHandler.",
e);
}
}
return contextHandler;
}
/*
* (non-Javadoc)
* @see melcoe.fedora.pep.ContextHandler#buildRequest(java.util.List,
* java.util.Map, java.util.Map, java.util.Map)
*/
public RequestCtx buildRequest(List<Map<URI, List<AttributeValue>>> subjects,
Map<URI, AttributeValue> actions,
Map<URI, AttributeValue> resources,
Map<URI, AttributeValue> environment)
throws PEPException {
try {
return contextUtil.buildRequest(subjects,
actions,
resources,
environment);
} catch (MelcoeXacmlException e) {
throw new PEPException(e);
}
}
/*
* (non-Javadoc)
* @see
* melcoe.fedora.pep.ContextHandler#evaluate(com.sun.xacml.ctx.RequestCtx)
*/
public ResponseCtx evaluate(RequestCtx reqCtx) throws PEPException {
return evaluationEngine.evaluate(reqCtx);
}
/*
* (non-Javadoc)
* @see melcoe.fedora.pep.ContextHandler#evaluate(java.lang.String)
*/
public String evaluate(String request) throws PEPException {
return evaluationEngine.evaluate(request);
}
/*
* (non-Javadoc)
* @see melcoe.fedora.pep.ContextHandler#evaluateBatch(java.lang.String[])
*/
public String evaluateBatch(String[] requests) throws PEPException {
return evaluationEngine.evaluate(requests);
}
public ResponseCache getResponseCache() {
return responseCache;
}
/**
* Reads a configuration file and configures this instance of the
* ContextHandler. It can instantiate a client (that communicates with the
* PEP), a relationship resolver (that communicates with the risearch REST
* service to determine parental relationships) and a response cache (that
* caches requests/responses for quicker evaluations).
*
* @throws PEPException
*/
private void init() throws PEPException {
try {
// get the PEP configuration
File configPEPFile =
new File(Constants.FEDORA_HOME,
"server/config/config-melcoe-pep.xml");
InputStream is = new FileInputStream(configPEPFile);
if (is == null) {
throw new PEPException("Could not locate config file: config-melcoe-pep.xml");
}
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = factory.newDocumentBuilder();
Document doc = docBuilder.parse(is);
NodeList nodes = null;
if (log.isDebugEnabled()) {
log.debug("Obtained the config file: config-melcoe-pep.xml");
}
String className = null;
Constructor<?> c = null;
Map<String, String> options = new HashMap<String, String>();
// get the PDP Client
nodes = doc.getElementsByTagName("pdp-client");
if (nodes.getLength() != 1) {
throw new PEPException("Config file needs to contain exactly 1 'pdp-client' section.");
}
className =
nodes.item(0).getAttributes().getNamedItem("class")
.getNodeValue();
NodeList optionNodes = nodes.item(0).getChildNodes();
for (int x = 0; x < optionNodes.getLength(); x++) {
Node n = optionNodes.item(x);
if (optionNodes.item(x).getNodeType() == Node.ELEMENT_NODE) {
log.debug("Node [name]: "
+ n.getAttributes().getNamedItem("name")
.getNodeValue());
String key =
n.getAttributes().getNamedItem("name")
.getNodeValue();
String value = n.getFirstChild().getNodeValue();
options.put(key, value);
}
}
c =
Class.forName(className)
.getConstructor(new Class[] {Map.class});
client = (PDPClient) c.newInstance(new Object[] {options});
if (log.isDebugEnabled()) {
log.debug("Instantiated PDPClient: " + className);
}
// get the Response Cache
nodes = doc.getElementsByTagName("response-cache");
if (nodes.getLength() != 1) {
throw new PEPException("Config file needs to contain exactly 1 'response-cache' section.");
}
className =
nodes.item(0).getAttributes().getNamedItem("class")
.getNodeValue();
if ("true".equals(nodes.item(0).getAttributes()
.getNamedItem("active").getNodeValue())) {
int cacheSize = 1000; // default
long cacheTTL = 10000; // default
NodeList children = nodes.item(0).getChildNodes();
for (int x = 0; x < children.getLength(); x++) {
if (children.item(x).getNodeType() == Node.ELEMENT_NODE) {
if ("cache-size".equals(children.item(x).getNodeName())) {
cacheSize =
Integer.parseInt(children.item(x)
.getFirstChild().getNodeValue());
}
if ("cache-item-ttl".equals(children.item(x)
.getNodeName())) {
cacheTTL =
Long.parseLong(children.item(x)
.getFirstChild().getNodeValue());
}
}
}
c =
Class.forName(className).getConstructor(new Class[] {
Integer.class, Long.class});
responseCache =
(ResponseCache) c.newInstance(new Object[] {
new Integer(cacheSize), new Long(cacheTTL)});
if (log.isDebugEnabled()) {
log.debug("Instantiated ResponseCache: " + className);
}
}
// Get the evaluation engine
nodes = doc.getElementsByTagName("evaluation-engine");
if (nodes.getLength() != 1) {
throw new PEPException("Config file needs to contain exactly 1 'evaluation-engine' section.");
}
className =
nodes.item(0).getAttributes().getNamedItem("class")
.getNodeValue();
evaluationEngine =
(EvaluationEngine) Class.forName(className).newInstance();
evaluationEngine.setClient(client);
evaluationEngine.setResponseCache(responseCache);
if (log.isDebugEnabled()) {
log.debug("Instantiated EvaluationEngine: " + className);
}
contextUtil = new ContextUtil();
if (log.isDebugEnabled()) {
log.debug("Instantiated ContextUtil.");
}
} catch (Exception e) {
log.fatal("Failed to initialse the PEP ContextHandler");
log.fatal(e.getMessage(), e);
throw new PEPException(e.getMessage(), e);
}
}
}