/* The contents of this file are subject to the license and copyright terms * detailed in the license directory at the root of the source tree (also * available online at http://fedora-commons.org/license/). */ package fedora.server.rest; import java.io.File; import java.io.StringReader; import java.io.Writer; import java.net.URI; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.xml.transform.Templates; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import net.sf.saxon.FeatureKeys; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; import fedora.common.Constants; import fedora.server.Context; import fedora.server.ReadOnlyContext; import fedora.server.Server; import fedora.server.access.Access; import fedora.server.errors.DatastreamNotFoundException; import fedora.server.errors.ObjectNotInLowlevelStorageException; import fedora.server.errors.authorization.AuthzException; import fedora.server.management.Management; import fedora.server.storage.types.MIMETypedStream; import fedora.server.storage.types.Property; import fedora.server.utilities.DateUtility; /** * A barebone RESTFUL resource implementation. * * @author cuong.tran@yourmediashelf.com * @version $Id$ */ public class BaseRestResource { private final Logger LOG = Logger.getLogger(getClass()); static final String[] EMPTY_STRING_ARRAY = new String[0]; static final String DEFAULT_ENC = "UTF-8"; public static final String XML = "text/xml"; public static final String HTML = "text/html"; public static final String FORM = "multipart/form-data"; public static final MediaType TEXT_XML = new MediaType("text", "xml"); public static final MediaType TEXT_HTML = new MediaType("text", "html"); protected Server fedoraServer; protected Management apiMService; protected Access apiAService; protected String fedoraServerHost; protected DatastreamFilenameHelper datastreamFilenameHelper; @javax.ws.rs.core.Context protected HttpServletRequest servletRequest; @javax.ws.rs.core.Context protected UriInfo uriInfo; @javax.ws.rs.core.Context protected HttpHeaders headers; public BaseRestResource() { try { this.fedoraServer = Server.getInstance(new File(Constants.FEDORA_HOME), false); this.apiMService = (Management) fedoraServer.getModule("fedora.server.management.Management"); this.apiAService = (Access) fedoraServer.getModule("fedora.server.access.Access"); this.fedoraServerHost = fedoraServer.getParameter("fedoraServerHost"); datastreamFilenameHelper = new DatastreamFilenameHelper(fedoraServer, apiMService, apiAService ); } catch (Exception ex) { throw new RestException("Unable to locate Fedora server instance", ex); } } protected Context getContext() { return ReadOnlyContext.getContext(Constants.HTTP_REQUEST.REST.uri, servletRequest); } protected DefaultSerializer getSerializer(Context context) { return new DefaultSerializer(fedoraServerHost, context); } protected void transform(String xml, String xslt, Writer out) throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException { File xslFile = new File(fedoraServer.getHomeDir(), xslt); TransformerFactory factory = TransformerFactory.newInstance(); if (factory.getClass().getName().equals("net.sf.saxon.TransformerFactoryImpl")) { factory.setAttribute(FeatureKeys.VERSION_WARNING, Boolean.FALSE); } Templates template = factory.newTemplates(new StreamSource(xslFile)); Transformer transformer = template.newTransformer(); String appContext = getContext().getEnvironmentValue(Constants.FEDORA_APP_CONTEXT_NAME); transformer.setParameter("fedora", appContext); transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(out)); } protected Response buildResponse(MIMETypedStream result) throws Exception { if (result.MIMEType.equalsIgnoreCase("application/fedora-redirect")) { URI location = URI.create(IOUtils.toString(result.getStream())); return Response.temporaryRedirect(location).build(); } else { ResponseBuilder builder = Response.ok(); if (result.header != null) { for (Property header : result.header) { if (header.name != null && !(header.name.equalsIgnoreCase("transfer-encoding")) && !(header.name.equalsIgnoreCase("content-type"))) { builder.header(header.name, header.value); } } } builder.type(result.MIMEType); builder.entity(result.getStream()); return builder.build(); } } protected Response handleException(Exception ex) { if (ex instanceof ObjectNotInLowlevelStorageException || ex instanceof DatastreamNotFoundException) { LOG.warn("Resource not found: " + ex.getMessage() + "; unable to fulfill REST API request", ex); return Response.status(Status.NOT_FOUND).entity(ex.getMessage()).type("text/plain").build(); } else if (ex instanceof AuthzException) { LOG.warn("Authorization failed; unable to fulfill REST API request", ex); return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).type("text/plain").build(); } else if (ex instanceof IllegalArgumentException) { LOG.warn("Bad request; unable to fulfill REST API request", ex); return Response.status(Status.BAD_REQUEST).entity(ex.getMessage()).type("text/plain").build(); } else { LOG.error("Unexpected error fulfilling REST API request", ex); throw new WebApplicationException(ex); } } protected static Date parseDate(String dTime) throws IllegalArgumentException { Date date = null; if (dTime != null) { date = DateUtility.convertStringToDate(dTime); if (date == null) { throw new IllegalArgumentException( "Illegal date syntax: " + dTime); } } return date; } }