
org.dspace.sword.SWORDUrlManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dspace-sword Show documentation
Show all versions of dspace-sword Show documentation
DSpace SWORD Deposit Service Provider Extension
The newest version!
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.sword;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamService;
import org.dspace.core.Context;
import org.dspace.handle.factory.HandleServiceFactory;
import org.dspace.handle.service.HandleService;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.purl.sword.base.SWORDErrorException;
/**
* @author Richard Jones
*
* Class responsible for constructing and de-constructing sword url space
* urls
*/
public class SWORDUrlManager {
/**
* the SWORD configuration
*/
private final SWORDConfiguration config;
/**
* the active DSpace context
*/
private final Context context;
protected HandleService handleService =
HandleServiceFactory.getInstance().getHandleService();
protected BitstreamService bitstreamService =
ContentServiceFactory.getInstance().getBitstreamService();
private final ConfigurationService configurationService
= DSpaceServicesFactory.getInstance().getConfigurationService();
private String swordPath = configurationService.getProperty(
"sword-server.path", "sword");
private String dspaceUrl = configurationService.getProperty(
"dspace.server.url");
public SWORDUrlManager(SWORDConfiguration config, Context context) {
this.config = config;
this.context = context;
}
/**
* Get the generator URL for ATOM entry documents. This can be
* overridden from the default in configuration.
*
* @return the generator URL for ATOM entry documents
*/
public String getGeneratorUrl() {
String cfg = configurationService.getProperty(
"sword-server.generator.url");
if (cfg == null || "".equals(cfg)) {
return SWORDProperties.SOFTWARE_URI;
}
return cfg;
}
/**
* Obtain the deposit URL for the given collection. These URLs
* should not be considered persistent, but will remain consistent
* unless configuration changes are made to DSpace
*
* @param collection the collection to query
* @return The Deposit URL
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getDepositLocation(Collection collection)
throws DSpaceSWORDException {
return this.getBaseDepositUrl() + "/" + collection.getHandle();
}
/**
* Obtain the deposit URL for the given item. These URLs
* should not be considered persistent, but will remain consistent
* unless configuration changes are made to DSpace
*
* @param item the item to query
* @return The Deposit URL
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getDepositLocation(Item item)
throws DSpaceSWORDException {
return this.getBaseDepositUrl() + "/" + item.getHandle();
}
/**
* Obtain the deposit URL for the given community. These URLs
* should not be considered persistent, but will remain consistent
* unless configuration changes are made to DSpace
*
* @param community the community to query
* @return The Deposit URL
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getDepositLocation(Community community)
throws DSpaceSWORDException {
// FIXME: there is no deposit url for communities yet, so this could
// be misleading
return this.getBaseDepositUrl() + "/" + community.getHandle();
}
/**
* Obtain the collection which is represented by the given
* URL
*
* @param context the DSpace context
* @param location the URL to resolve to a collection
* @return The collection to which the url resolves
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
* @throws SWORDErrorException on generic SWORD exception
*/
// FIXME: we need to generalise this to DSpaceObjects, so that we can support
// Communities, Collections and Items separately
public Collection getCollection(Context context, String location)
throws DSpaceSWORDException, SWORDErrorException {
try {
String baseUrl = this.getBaseDepositUrl();
if (baseUrl.length() == location.length()) {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"The deposit URL is incomplete");
}
String handle = location.substring(baseUrl.length());
if (handle.startsWith("/")) {
handle = handle.substring(1);
}
if ("".equals(handle)) {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"The deposit URL is incomplete");
}
DSpaceObject dso = handleService.resolveToObject(context, handle);
if (!(dso instanceof Collection)) {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"The deposit URL does not resolve to a valid collection");
}
return (Collection) dso;
} catch (SQLException e) {
// log.error("Caught exception:", e);
throw new DSpaceSWORDException(
"There was a problem resolving the collection", e);
}
}
/**
* Obtain the collection which is represented by the given
* URL
*
* @param context the DSpace context
* @param location the URL to resolve to a collection
* @return The collection to which the url resolves
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
* @throws SWORDErrorException on generic SWORD exception
*/
public DSpaceObject getDSpaceObject(Context context, String location)
throws DSpaceSWORDException, SWORDErrorException {
try {
String baseUrl = this.getBaseDepositUrl();
if (baseUrl.length() == location.length()) {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"The deposit URL is incomplete");
}
String handle = location.substring(baseUrl.length());
if (handle.startsWith("/")) {
handle = handle.substring(1);
}
if ("".equals(handle)) {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"The deposit URL is incomplete");
}
DSpaceObject dso = handleService.resolveToObject(context, handle);
if (!(dso instanceof Collection) && !(dso instanceof Item)) {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"The deposit URL does not resolve to a valid deposit target");
}
return dso;
} catch (SQLException e) {
// log.error("Caught exception:", e);
throw new DSpaceSWORDException(
"There was a problem resolving the collection", e);
}
}
/**
* Construct the service document URL for the given object, which will
* be supplied in the sword:service element of other service document
* entries.
*
* @param community target community
* @return service document URL for the given object
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String constructSubServiceUrl(Community community)
throws DSpaceSWORDException {
String base = this.getBaseServiceDocumentUrl();
String handle = community.getHandle();
return base + "/" + handle;
}
/**
* Construct the service document URL for the given object, which will
* be supplied in the sword:service element of other service document
* entries.
*
* @param collection target collection
* @return service document URL for the given object
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String constructSubServiceUrl(Collection collection)
throws DSpaceSWORDException {
String base = this.getBaseServiceDocumentUrl();
String handle = collection.getHandle();
return base + "/" + handle;
}
/**
* Extract a DSpaceObject from the given URL. If this method is unable to
* locate a meaningful and appropriate DSpace object it will throw the
* appropriate SWORD error.
*
* @param url URL to get DSpace object from
* @return DSpace object corresponding to given URL
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
* @throws SWORDErrorException on generic SWORD exception
*/
public DSpaceObject extractDSpaceObject(String url)
throws DSpaceSWORDException, SWORDErrorException {
try {
String sdBase = this.getBaseServiceDocumentUrl();
String mlBase = this.getBaseMediaLinkUrl();
if (url.startsWith(sdBase)) {
// we are dealing with a service document request
// first, let's find the beginning of the handle
url = url.substring(sdBase.length());
if (url.startsWith("/")) {
url = url.substring(1);
}
if (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
DSpaceObject dso = handleService.resolveToObject(context, url);
if (dso instanceof Collection || dso instanceof Community) {
return dso;
} else {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"Service Document request does not refer to a DSpace Collection or " +
"Community");
}
} else if (url.startsWith(mlBase)) {
// we are dealing with a bitstream media link
// find the index of the "/bitstream/" segment of the url
int bsi = url.indexOf("/bitstream/");
// subtsring the url from the end of this "/bitstream/" string, to get the bitstream id
String bsid = url.substring(bsi + 11);
// strip off extraneous slashes
if (bsid.endsWith("/")) {
bsid = bsid.substring(0, url.length() - 1);
}
return bitstreamService.findByIdOrLegacyId(context, bsid);
} else {
throw new SWORDErrorException(DSpaceSWORDErrorCodes.BAD_URL,
"Unable to recognise URL as a valid service document: " +
url);
}
} catch (SQLException e) {
throw new DSpaceSWORDException(e);
}
}
/**
* Get the base URL for service document requests.
*
* @return the base URL for service document requests
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getBaseServiceDocumentUrl()
throws DSpaceSWORDException {
String depositUrl = configurationService.getProperty(
"sword-server.servicedocument.url");
if (depositUrl == null || "".equals(depositUrl)) {
if (dspaceUrl == null || "".equals(dspaceUrl)) {
throw new DSpaceSWORDException(
"Unable to construct service document urls, due to missing/invalid " +
"config in sword.servicedocument.url and/or dspace.server.url");
}
depositUrl = buildSWORDUrl("servicedocument");
}
return depositUrl;
}
/**
* Get the base deposit URL for the DSpace SWORD implementation. This
* is effectively the URL of the servlet which deals with deposit
* requests, and is used as the basis for the individual Collection
* URLs
*
* If the configuration sword.deposit.url is set, this will be returned,
* but if not, it will construct the url as follows:
*
* [dspace.server.url]/sword/deposit
*
* where dspace.server.url is also in the configuration file.
*
* @return the base URL for SWORD deposit
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getBaseDepositUrl()
throws DSpaceSWORDException {
String depositUrl = configurationService.getProperty(
"sword-server.deposit.url");
if (depositUrl == null || "".equals(depositUrl)) {
if (dspaceUrl == null || "".equals(dspaceUrl)) {
throw new DSpaceSWORDException(
"Unable to construct deposit urls, due to missing/invalid config in " +
"sword.deposit.url and/or dspace.server.url");
}
depositUrl = buildSWORDUrl("deposit");
}
return depositUrl;
}
/**
* Is the given URL the base service document URL?
*
* @param url URL to check
* @return true if the given URL the base service document URL
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public boolean isBaseServiceDocumentUrl(String url)
throws DSpaceSWORDException {
return this.getBaseServiceDocumentUrl().equals(url);
}
/**
* Is the given URL the base media link URL?
*
* @param url URL to check
* @return true if the given URL the base media link URL
* @throws DSpaceSWORDException passed through.
*/
public boolean isBaseMediaLinkUrl(String url)
throws DSpaceSWORDException {
return this.getBaseMediaLinkUrl().equals(url);
}
/**
* Central location for constructing usable URLs for DSpace bitstreams.
* There is no place in the main DSpace code base for doing this.
*
* @param bitstream target bitstream
* @return a URL to the given Bitstream.
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getBitstreamUrl(Bitstream bitstream)
throws DSpaceSWORDException {
try {
List bundles = bitstream.getBundles();
Bundle parent = null;
if (!bundles.isEmpty()) {
parent = bundles.get(0);
} else {
throw new DSpaceSWORDException(
"Encountered orphaned bitstream");
}
List- items = parent.getItems();
Item item;
if (!items.isEmpty()) {
item = items.get(0);
} else {
throw new DSpaceSWORDException("Encountered orphaned bundle");
}
String handle = item.getHandle();
String bsLink = configurationService.getProperty("dspace.ui.url");
if (handle != null && !"".equals(handle)) {
bsLink = bsLink + "/bitstream/" + handle + "/" +
bitstream.getSequenceID() + "/" + bitstream.getName();
} else {
bsLink = bsLink + "/retrieve/" + bitstream.getID();
}
return bsLink;
} catch (SQLException e) {
throw new DSpaceSWORDException(e);
}
}
/**
* Get the base media link URL. It can be configured using
* {@code sword-server.media-link.url}. If not configured, it will be
* calculated using {@code dspace.server.url} and the constant path
* {@code /sword/media-link}.
*
* @return that URL.
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getBaseMediaLinkUrl()
throws DSpaceSWORDException {
String mlUrl = configurationService.getProperty("sword-server.media-link.url");
if (StringUtils.isBlank(mlUrl)) {
if (dspaceUrl == null || "".equals(dspaceUrl)) {
throw new DSpaceSWORDException(
"Unable to construct media-link urls, due to missing/invalid config in " +
"media-link.url and/or dspace.server.url");
}
mlUrl = buildSWORDUrl("media-link");
}
return mlUrl;
}
/**
* get the media link URL for the given item
*
* @param dso target DSpace object
* @return media link URL for the given item
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
private String getMediaLink(Item dso)
throws DSpaceSWORDException {
String ml = this.getBaseMediaLinkUrl();
String handle = dso.getHandle();
if (handle != null) {
ml = ml + "/" + dso.getHandle();
}
return ml;
}
/**
* Get the media link URL for the given bitstream.
*
* @param bitstream target bitstream
* @return media link URL for the given bitstream
* @throws DSpaceSWORDException can be thrown by the internals of the DSpace SWORD implementation
*/
public String getMediaLink(Bitstream bitstream)
throws DSpaceSWORDException {
try {
List
bundles = bitstream.getBundles();
Bundle parent = null;
if (!bundles.isEmpty()) {
parent = bundles.get(0);
} else {
throw new DSpaceSWORDException(
"Encountered orphaned bitstream");
}
List- items = parent.getItems();
Item item;
if (!items.isEmpty()) {
item = items.get(0);
} else {
throw new DSpaceSWORDException("Encountered orphaned bundle");
}
String itemUrl = this.getMediaLink(item);
if (itemUrl.equals(this.getBaseMediaLinkUrl())) {
return itemUrl;
}
return itemUrl + "/bitstream/" + bitstream.getID();
} catch (SQLException e) {
throw new DSpaceSWORDException(e);
}
}
/**
* Return configured server path for SWORD url
*
* @param path the target SWORD endpoint
* @return a sword URL
*/
private String buildSWORDUrl(String path) {
return dspaceUrl + "/" + swordPath + "/" + path;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy