/*
* Copyright (c) 2010 Brasiliana Digital Library (http://brasiliana.usp.br).
* Based on similar source code from Adore Djatoka.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package gov.lanl.adore.djatoka.openurl.plugin.dspace;
import gov.lanl.adore.djatoka.openurl.DjatokaImageMigrator;
import gov.lanl.adore.djatoka.openurl.IReferentMigrator;
import gov.lanl.adore.djatoka.openurl.IReferentResolver;
import gov.lanl.adore.djatoka.openurl.ResolverException;
import gov.lanl.adore.djatoka.util.ImageRecord;
import info.openurl.oom.entities.Referent;
import java.io.File;
import java.net.URI;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
/**
* Alternate IReferentResolver implementation using DSpace bitstream internal ID.
*
* ----- OpenURLJP2KService.properties -----
* OpenURLJP2KService.referentResolverImpl=gov.lanl.adore.djatoka.openurl.plugin.DSpaceResolver
* DSpaceResolver.assetpath=dspace.assetpath
*
* @author Fabio N. Kepler
*/
public class DSpaceResolver implements IReferentResolver {
static Logger log = Logger.getLogger(DSpaceResolver.class.getName());
private static final String DSPACE_ASSETPATH = "DSpaceResolver.assetpath";
private static IReferentMigrator dim = new DjatokaImageMigrator();
private static String dspace_assetpath;
private static Map<String, ImageRecord> imgs;
/**
* Referent Identifier to be resolved from Identifier Resolver. The returned
* ImageRecord need only contain the imageId and image file path.
*
* @param rft
* identifier of the image to be resolved
* @return ImageRecord instance containing resolvable metadata
* @throws ResolverException
*/
@Override
public ImageRecord getImageRecord(Referent rft) throws ResolverException {
String id = ((URI) rft.getDescriptors()[0]).toASCIIString();
return getImageRecord(id);
}
/**
* Referent Identifier to be resolved from Identifier Resolver. The returned
* ImageRecord need only contain the imageId and image file path.
*
* @param rftId
* identifier of the image to be resolved
* @return ImageRecord instance containing resolvable metadata
* @throws ResolverException
*/
@Override
public ImageRecord getImageRecord(String rftId) throws ResolverException {
try {
ImageRecord ir = null;
if (isResolvableURI(rftId)) {
ir = getRemoteImage(rftId);
} else {
ir = getLocalImage(rftId);
}
return ir;
} catch (Exception e) {
log.error(e, e);
throw new ResolverException(e);
}
}
@Override
public IReferentMigrator getReferentMigrator() {
return dim;
}
@Override
public int getStatus(String rftId) {
if (imgs.get(rftId) != null)
return HttpServletResponse.SC_OK;
else if (dim.getProcessingList().contains(rftId))
return HttpServletResponse.SC_ACCEPTED;
else
return HttpServletResponse.SC_NOT_FOUND;
}
/**
* Sets a Properties object that may be used by underlying implementation
*
* @param props
* Properties object for use by implementation
* @throws ResolverException
*/
@Override
public void setProperties(Properties props) throws ResolverException {
String dap = props.getProperty(DSPACE_ASSETPATH);
if (dap != null) {
dspace_assetpath = dap;
imgs = Collections.synchronizedMap(new LinkedHashMap<String, ImageRecord>(16, 0.75f, true));
} else {
throw new ResolverException(DSPACE_ASSETPATH + " is not defined.");
}
}
private static boolean isResolvableURI(String rftId) {
return (rftId.startsWith("http") || rftId.startsWith("file") || rftId.startsWith("ftp"));
}
/**
* Logic for translating the DSpace bitstream's internal identifier to its filesystem path.
* Must be the same logic used inside DSpace!
*/
private ImageRecord getLocalImage(String rftId) throws ResolverException {
String internalId = rftId;
StringBuilder bitstreamPathBuilder = new StringBuilder();
// Get the asset store root path.
bitstreamPathBuilder.append(dspace_assetpath);
// If the specified path does not end with the path separator character, add one.
if (!dspace_assetpath.endsWith(File.separator)) {
bitstreamPathBuilder.append(File.separator);
}
bitstreamPathBuilder.append(internalId.substring(0, 2))
.append(File.separator)
.append(internalId.substring(2, 4))
.append(File.separator)
.append(internalId.substring(4, 6))
.append(File.separator)
.append(internalId).toString();
String bitstreamPath = bitstreamPathBuilder.toString();
File bit = new File(bitstreamPath);
if (!bit.exists())
throw new ResolverException("An error occurred processing file: " + bitstreamPath);
ImageRecord ir = new ImageRecord(rftId, bitstreamPath);
imgs.put(rftId, ir);
return ir;
}
private ImageRecord getRemoteImage(String rftId) throws ResolverException {
throw new ResolverException("No support for remote images processing: " + rftId);
}
}