/*
* File: ObjectsFilter.java
*
* Copyright 2009 2DC
*
* 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.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import melcoe.fedora.pep.PEPException;
import melcoe.fedora.pep.rest.objectshandlers.Handlers;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.xacml.ctx.RequestCtx;
import fedora.common.Constants;
/**
* Handles the get operations.
*
* @author nish.naidoo@gmail.com
*/
public class ObjectsFilter
extends AbstractFilter {
private static Logger log = Logger.getLogger(ObjectsFilter.class.getName());
private Map<String, RESTFilter> objectsHandlers = null;
/**
* Default constructor.
*
* @throws PEPException
*/
public ObjectsFilter()
throws PEPException {
super();
try {
loadObjectsHandlers();
} catch (ServletException se) {
throw new PEPException(se);
}
}
/*
* (non-Javadoc)
* @see
* melcoe.fedora.pep.rest.filters.RESTFilter#handleRequest(javax.servlet
* .http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public RequestCtx handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
RESTFilter objectsHandler = getObjectsHandler(request);
if (objectsHandler == null) {
return null;
}
return objectsHandler.handleRequest(request, response);
}
/*
* (non-Javadoc)
* @see
* melcoe.fedora.pep.rest.filters.RESTFilter#handleResponse(javax.servlet
* .http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public RequestCtx handleResponse(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
RESTFilter objectsHandler = getObjectsHandler(request);
if (objectsHandler == null) {
return null;
}
return objectsHandler.handleResponse(request, response);
}
public RESTFilter getObjectsHandler(HttpServletRequest request)
throws ServletException {
String uri = request.getRequestURI();
String path = request.getPathInfo();
// need to handle this special case due to the way the RestServlet is mapped.
if (uri.endsWith("nextPID")) {
path = "/nextPID";
} else if (path == null) {
path = "";
}
if (log.isDebugEnabled()) {
log.debug("objectsHandler path: " + path);
}
// The method override header. Takes precedence over the HTTP method
String method = request.getHeader("X-HTTP-Method-Override");
if (method == null || "".equals(method)) {
method = request.getMethod();
}
if (method == null) {
throw new ServletException("Request Method was NULL");
}
method = method.toUpperCase();
if (log.isDebugEnabled()) {
log.debug("objectsHandler method: " + method);
}
String[] parts = path.split("/");
if (log.isDebugEnabled()) {
for (String p : parts) {
log.debug("objectsHandler part: " + p);
}
}
if (parts.length < 1) {
log.info("Not enough components on the URI.");
throw new ServletException("Not enough components on the URI.");
}
String handlerName = null;
// ascertain the correct handler based on uri pattern.
if (parts.length == 1) {
if (request.getParameterMap().containsKey("sessionToken")) {
handlerName = Handlers.RESUMEFINDOBJECTS;
} else if (request.getParameterMap().containsKey("terms")
|| request.getParameterMap().containsKey("query")) {
handlerName = Handlers.FINDOBJECTS;
}
} else if (parts.length == 2
&& (isPID(parts[1]) || "new".equals(parts[1]))) {
if ("GET".equals(method)) {
handlerName = Handlers.GETOBJECTPROFILE;
} else if ("PUT".equals(method)) {
handlerName = Handlers.MODIFYOBJECT;
} else if ("DELETE".equals(method)) {
handlerName = Handlers.PURGEOBJECT;
} else if ("POST".equals(method) && "new".equals(parts[1])) {
handlerName = Handlers.INGEST;
}
} else if (parts.length == 2 && parts[1].equals("nextPID")) {
handlerName = Handlers.GETNEXTPID;
} else if (parts.length == 3 && isPID(parts[1]) && "GET".equals(method)) {
if ("datastreams".equals(parts[2])) {
handlerName = Handlers.LISTDATASTREAMS;
} else if ("export".equals(parts[2])) {
handlerName = Handlers.EXPORT;
} else if ("methods".equals(parts[2])) {
handlerName = Handlers.LISTMETHODS;
} else if ("objectXML".equals(parts[2])) {
handlerName = Handlers.GETOBJECTXML;
} else if ("versions".equals(parts[2])) {
handlerName = Handlers.GETOBJECTHISTORY;
}
} else if (parts.length == 4 && isPID(parts[1])
&& "datastreams".equals(parts[2]) && isDatastream(parts[3])) {
if ("PUT".equals(method)
&& request.getParameterMap().containsKey("dsState")) {
handlerName = Handlers.SETDATASTREAMSTATE;
} else if ("PUT".equals(method)
&& request.getParameterMap().containsKey("versionable")) {
handlerName = Handlers.SETDATASTREAMVERSIONABLE;
} else if ("PUT".equals(method)) {
handlerName = Handlers.MODIFYDATASTREAM;
} else if ("POST".equals(method)) {
handlerName = Handlers.ADDDATASTREAM;
} else if ("GET".equals(method)) {
handlerName = Handlers.GETDATASTREAM;
} else if ("DELETE".equals(method)) {
handlerName = Handlers.PURGEDATASTREAM;
}
} else if (parts.length == 5 && isPID(parts[1])
&& "datastreams".equals(parts[2]) && isDatastream(parts[3])
&& "content".equals(parts[4])) {
handlerName = Handlers.GETDATASTREAMDISSEMINATION;
}
if (log.isDebugEnabled()) {
log.debug("activating handler: " + handlerName);
}
return objectsHandlers.get(handlerName);
}
private void loadObjectsHandlers() throws ServletException {
objectsHandlers = new HashMap<String, RESTFilter>();
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);
Node node = doc.getElementsByTagName("handlers-objects").item(0);
NodeList nodes = node.getChildNodes();
for (int x = 0; x < nodes.getLength(); x++) {
Node n = nodes.item(x);
if (n.getNodeType() == Node.ELEMENT_NODE
&& "handler".equals(n.getNodeName())) {
String opn =
n.getAttributes().getNamedItem("operation")
.getNodeValue();
String cls =
n.getAttributes().getNamedItem("class")
.getNodeValue();
if (opn == null || "".equals(opn)) {
throw new PEPException("Cannot have a missing or empty operation attribute");
}
if (cls == null || "".equals(cls)) {
throw new PEPException("Cannot have a missing or empty class attribute");
}
try {
Class<?> filterClass = Class.forName(cls);
RESTFilter filter =
(RESTFilter) filterClass.newInstance();
objectsHandlers.put(opn, filter);
if (log.isDebugEnabled()) {
log.debug("objects handler added to map: " + opn
+ "/" + cls);
}
} catch (ClassNotFoundException e) {
if (log.isDebugEnabled()) {
log.debug("filterClass not found for: " + cls);
}
} catch (InstantiationException ie) {
log.error("Could not instantiate filter: " + cls);
throw new ServletException(ie.getMessage(), ie);
} catch (IllegalAccessException iae) {
log.error("Could not instantiate filter: " + cls);
throw new ServletException(iae.getMessage(), iae);
}
}
}
} catch (Exception e) {
log.fatal("Failed to initialse the PEP for REST");
log.fatal(e.getMessage(), e);
throw new ServletException(e.getMessage(), e);
}
}
}