/*
* File: AbstractFilter.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.rest.filters;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import melcoe.fedora.pep.ContextHandler;
import melcoe.fedora.pep.ContextHandlerImpl;
import melcoe.fedora.pep.PEPException;
import org.apache.log4j.Logger;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.StringAttribute;
import fedora.common.Constants;
/**
* This is the AbstractFilter class which provides generic functionality for all
* REST filters. All REST filters should extend this class.
*
* @author nishen@melcoe.mq.edu.au
*/
public abstract class AbstractFilter
implements RESTFilter {
private static Logger log =
Logger.getLogger(AbstractFilter.class.getName());
private static ContextHandler contextHandlerImpl;
protected static final String XACML_RESOURCE_ID =
"urn:oasis:names:tc:xacml:1.0:resource:resource-id";
protected static final String SUBJECT_ID =
"urn:oasis:names:tc:xacml:1.0:subject:subject-id";
protected static final String FEDORA_ROLE =
"urn:fedora:names:fedora:2.1:subject:role";
/**
* Default constructor obtains an instance of the Context Handler.
*
* @throws PEPException
*/
public AbstractFilter()
throws PEPException {
contextHandlerImpl = ContextHandlerImpl.getInstance();
}
/**
* @return the ContextHandler instance
*/
public ContextHandler getContextHandler() {
return contextHandlerImpl;
}
/**
* Creates a list of Subjects from a servlet request. If no subject is found
* a subject called 'anonymous' is created.
*
* @param request
* the servlet request
* @return a list of Subjects
* @throws ServletException
*/
protected List<Map<URI, List<AttributeValue>>> getSubjects(HttpServletRequest request)
throws ServletException {
@SuppressWarnings("unchecked")
Map<String, Set<String>> reqAttr =
(Map<String, Set<String>>) request
.getAttribute("FEDORA_AUX_SUBJECT_ATTRIBUTES");
Set<String> fedoraRoles = null;
if (reqAttr != null) {
fedoraRoles = reqAttr.get("fedoraRole");
}
String[] fedoraRole = null;
if (fedoraRoles != null && fedoraRoles.size() > 0) {
fedoraRole = fedoraRoles.toArray(new String[fedoraRoles.size()]);
}
List<Map<URI, List<AttributeValue>>> subjects =
new ArrayList<Map<URI, List<AttributeValue>>>();
String user = request.getRemoteUser();
if (user == null || "".equals(user)) {
user = "anonymous";
}
// setup the id and value for the requesting subject
try {
Map<URI, List<AttributeValue>> subAttr =
new HashMap<URI, List<AttributeValue>>();
List<AttributeValue> attrList = new ArrayList<AttributeValue>();
attrList.add(new StringAttribute(user));
subAttr.put(Constants.SUBJECT.LOGIN_ID.getURI(), attrList);
if (fedoraRole != null && fedoraRole.length > 0) {
attrList = new ArrayList<AttributeValue>();
for (String f : fedoraRole) {
attrList.add(new StringAttribute(f));
}
subAttr.put(new URI(FEDORA_ROLE), attrList);
}
subjects.add(subAttr);
subAttr = new HashMap<URI, List<AttributeValue>>();
attrList = new ArrayList<AttributeValue>();
attrList.add(new StringAttribute(user));
subAttr.put(Constants.SUBJECT.USER_REPRESENTED.getURI(), attrList);
if (fedoraRole != null && fedoraRole.length > 0) {
attrList = new ArrayList<AttributeValue>();
for (String f : fedoraRole) {
attrList.add(new StringAttribute(f));
}
subAttr.put(new URI(FEDORA_ROLE), attrList);
}
subjects.add(subAttr);
subAttr = new HashMap<URI, List<AttributeValue>>();
attrList = new ArrayList<AttributeValue>();
attrList.add(new StringAttribute(user));
subAttr.put(new URI(SUBJECT_ID), attrList);
if (fedoraRole != null && fedoraRole.length > 0) {
attrList = new ArrayList<AttributeValue>();
for (String f : fedoraRole) {
attrList.add(new StringAttribute(f));
}
subAttr.put(new URI(FEDORA_ROLE), attrList);
}
subjects.add(subAttr);
} catch (URISyntaxException use) {
log.error(use.getMessage(), use);
throw new ServletException(use);
}
return subjects;
}
/**
* Returns a list of environment attributes.
*
* @param request
* the servlet request from which to obtain the attributes
* @return a list of environment attributes
*/
protected Map<URI, AttributeValue> getEnvironment(HttpServletRequest request) {
Map<URI, AttributeValue> envAttr = new HashMap<URI, AttributeValue>();
String ip = request.getRemoteAddr();
if (ip != null && !"".equals(ip)) {
envAttr.put(Constants.HTTP_REQUEST.CLIENT_IP_ADDRESS.getURI(),
new StringAttribute(ip));
}
return envAttr;
}
/**
* Function to determine whether a parameter is a PID.
*
* @param item
* the uri parameter
*/
protected boolean isPID(String item) {
if (item == null) {
return false;
}
// Currently, I am assuming that if it has a ':' in it, it's a
// PID.
return item.indexOf(':') > 0;
}
/**
* Function to determine whether a parameter is a datastream or a
* dissemination.
*
* @param item
* the uri parameter
*/
protected boolean isDatastream(String item) {
if (item == null) {
return false;
}
// Currently, I am assuming that if it has a ':' in it, it's a
// dissemination. Otherwise it is a datastream.
return item.indexOf(':') == -1;
}
/**
* Checks whether a parameter fits the date pattern.
*
* @param item
* the date
* @return returns true if the string is a date or else false
*/
protected boolean isDate(String item) {
if (item == null) {
return false;
}
if (item.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{3}Z$")) {
return true;
}
if (item.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$")) {
return true;
}
if (item.matches("^\\d{4}-\\d{2}-\\d{2}$")) {
return true;
}
return false;
}
}