diff --git a/dspace-api/src/main/java/org/dspace/app/canvasdimension/CanvasDimensionCLI.java b/dspace-api/src/main/java/org/dspace/app/canvasdimension/CanvasDimensionCLI.java index 6ba204f579..1ea5c2f26f 100644 --- a/dspace-api/src/main/java/org/dspace/app/canvasdimension/CanvasDimensionCLI.java +++ b/dspace-api/src/main/java/org/dspace/app/canvasdimension/CanvasDimensionCLI.java @@ -50,8 +50,7 @@ public class CanvasDimensionCLI { boolean iiifEnabled = configurationService.getBooleanProperty("iiif.enabled"); if (!iiifEnabled) { - System.out.println("IIIF is not enabled on this DSpace server."); - System.exit(0); + System.out.println("WARNING: IIIF is not enabled on this DSpace server."); } // default to not updating existing dimensions diff --git a/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFApiQueryServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFApiQueryServiceImpl.java index 609fa54041..4582b4b235 100644 --- a/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFApiQueryServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFApiQueryServiceImpl.java @@ -17,11 +17,11 @@ import java.net.URL; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.logging.log4j.Logger; import org.dspace.app.canvasdimension.service.IIIFApiQueryService; import org.dspace.content.Bitstream; -import org.dspace.services.ConfigurationService; +import org.dspace.iiif.IIIFSharedUtils; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; /** @@ -32,14 +32,11 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class IIIFApiQueryServiceImpl implements IIIFApiQueryService, InitializingBean { - @Autowired() - protected ConfigurationService configurationService; - - String iiifImageServer; + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(IIIFApiQueryServiceImpl.class); @Override public void afterPropertiesSet() throws Exception { - iiifImageServer = configurationService.getProperty("iiif.image.server"); + // do nothing } @Override @@ -54,29 +51,39 @@ public class IIIFApiQueryServiceImpl implements IIIFApiQueryService, Initializin */ private int[] getIiifImageDimensions(Bitstream bitstream) { int[] arr = new int[2]; - String path = iiifImageServer + bitstream.getID() + "/info.json"; + String path = IIIFSharedUtils.getInfoJsonPath(bitstream); URL url; + BufferedReader in = null; try { url = new URL(path); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); - BufferedReader in = new BufferedReader( + in = new BufferedReader( new InputStreamReader(con.getInputStream())); String inputLine; StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } - in.close(); JsonNode parent = new ObjectMapper().readTree(response.toString()); - arr[0] = parent.get("width").asInt(); - arr[1] = parent.get("height").asInt(); - return checkDimensions(arr); + // return dimensions if found. + if (parent.has("width") && parent.has("height")) { + arr[0] = parent.get("width").asInt(); + arr[1] = parent.get("height").asInt(); + return checkDimensions(arr); + } } catch (IOException e) { - e.printStackTrace(); + log.error(e.getMessage(), e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } } return null; } - } diff --git a/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFCanvasDimensionServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFCanvasDimensionServiceImpl.java index e03e32243d..d56f43684f 100644 --- a/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFCanvasDimensionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/canvasdimension/IIIFCanvasDimensionServiceImpl.java @@ -7,13 +7,21 @@ */ package org.dspace.app.canvasdimension; +import static org.dspace.iiif.IIIFSharedUtils.METADATA_IIIF_HEIGHT; +import static org.dspace.iiif.IIIFSharedUtils.METADATA_IIIF_IMAGE; +import static org.dspace.iiif.IIIFSharedUtils.METADATA_IIIF_SCHEMA; +import static org.dspace.iiif.IIIFSharedUtils.METADATA_IIIF_WIDTH; + +import java.io.IOException; import java.io.InputStream; +import java.sql.SQLException; import java.util.Iterator; import java.util.List; import java.util.Optional; import org.dspace.app.canvasdimension.service.IIIFApiQueryService; import org.dspace.app.canvasdimension.service.IIIFCanvasDimensionService; +import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; @@ -149,9 +157,10 @@ public class IIIFCanvasDimensionServiceImpl implements IIIFCanvasDimensionServic * @return * @throws Exception */ - private boolean processBitstream(Context context, Bitstream bitstream) throws Exception { + private boolean processBitstream(Context context, Bitstream bitstream) throws SQLException, AuthorizeException, + IOException { + boolean processed = false; - boolean isUnsupported = bitstream.getFormat(context).getMIMEType().contains("image/jp2"); boolean isImage = bitstream.getFormat(context).getMIMEType().contains("image/"); if (isImage) { Optional op = bitstream.getMetadata().stream() @@ -162,12 +171,25 @@ public class IIIFCanvasDimensionServiceImpl implements IIIFCanvasDimensionServic System.out.println("Force processing for bitstream: " + bitstream.getID()); } int[] dims; - if (isUnsupported) { - dims = iiifApiQuery.getImageDimensions(bitstream); - } else { - InputStream stream = bitstreamService.retrieve(context, bitstream); - dims = ImageDimensionReader.getImageDimensions(stream); + InputStream stream = null; + try { + stream = bitstreamService.retrieve(context, bitstream); + try { + dims = ImageDimensionReader.getImageDimensions(stream); + if (dims == null) { + // If image dimensions are not available try the iiif image server. + dims = iiifApiQuery.getImageDimensions(bitstream); + } + } catch (IOException e) { + // If an exception was raised by ImageIO, try the iiif image server. + dims = iiifApiQuery.getImageDimensions(bitstream); + } + } finally { + if (stream != null) { + stream.close(); + } } + if (dims != null) { processed = setBitstreamMetadata(context, bitstream, dims); // update the bitstream @@ -185,15 +207,15 @@ public class IIIFCanvasDimensionServiceImpl implements IIIFCanvasDimensionServic * @param dims * @return */ - private boolean setBitstreamMetadata(Context context, Bitstream bitstream, int[] dims) throws Exception { - dSpaceObjectService.clearMetadata(context, bitstream, "iiif", - "image", "width", Item.ANY); - dSpaceObjectService.setMetadataSingleValue(context, bitstream, "iiif", - "image", "width", Item.ANY, String.valueOf(dims[0])); - dSpaceObjectService.clearMetadata(context, bitstream, "iiif", - "image", "height", Item.ANY); - dSpaceObjectService.setMetadataSingleValue(context, bitstream, "iiif", - "image", "height", Item.ANY, String.valueOf(dims[1])); + private boolean setBitstreamMetadata(Context context, Bitstream bitstream, int[] dims) throws SQLException { + dSpaceObjectService.clearMetadata(context, bitstream, METADATA_IIIF_SCHEMA, + METADATA_IIIF_IMAGE, METADATA_IIIF_WIDTH, Item.ANY); + dSpaceObjectService.setMetadataSingleValue(context, bitstream, METADATA_IIIF_SCHEMA, + METADATA_IIIF_IMAGE, METADATA_IIIF_WIDTH, null, String.valueOf(dims[0])); + dSpaceObjectService.clearMetadata(context, bitstream, METADATA_IIIF_SCHEMA, + METADATA_IIIF_IMAGE, METADATA_IIIF_HEIGHT, Item.ANY); + dSpaceObjectService.setMetadataSingleValue(context, bitstream, METADATA_IIIF_SCHEMA, + METADATA_IIIF_IMAGE, METADATA_IIIF_HEIGHT, null, String.valueOf(dims[1])); if (!isQuiet) { System.out.println("Added IIIF canvas metadata to bitstream: " + bitstream.getID()); } diff --git a/dspace-api/src/main/java/org/dspace/app/canvasdimension/ImageDimensionReader.java b/dspace-api/src/main/java/org/dspace/app/canvasdimension/ImageDimensionReader.java index 217f6ef3b8..648d98528c 100644 --- a/dspace-api/src/main/java/org/dspace/app/canvasdimension/ImageDimensionReader.java +++ b/dspace-api/src/main/java/org/dspace/app/canvasdimension/ImageDimensionReader.java @@ -10,6 +10,7 @@ package org.dspace.app.canvasdimension; import static org.dspace.app.canvasdimension.Util.checkDimensions; import java.awt.image.BufferedImage; +import java.io.IOException; import java.io.InputStream; import javax.imageio.ImageIO; @@ -25,18 +26,20 @@ public class ImageDimensionReader { /** * Uses ImageIO to read height and width dimensions. * @param image inputstream for dspace image - * @return image dimensions + * @return image dimensions or null if the image format cannot be read. * @throws Exception */ - public static int[] getImageDimensions(InputStream image) throws Exception { + public static int[] getImageDimensions(InputStream image) throws IOException { int[] dims = new int[2]; BufferedImage buf = ImageIO.read(image); - int width = buf.getWidth(null); - int height = buf.getHeight(null); - if (width > 0 && height > 0) { - dims[0] = width; - dims[1] = height; - return checkDimensions(dims); + if (buf != null) { + int width = buf.getWidth(null); + int height = buf.getHeight(null); + if (width > 0 && height > 0) { + dims[0] = width; + dims[1] = height; + return checkDimensions(dims); + } } return null; } diff --git a/dspace-api/src/main/java/org/dspace/iiif/IIIFSharedUtils.java b/dspace-api/src/main/java/org/dspace/iiif/IIIFSharedUtils.java index 78f72c882c..517b160832 100644 --- a/dspace-api/src/main/java/org/dspace/iiif/IIIFSharedUtils.java +++ b/dspace-api/src/main/java/org/dspace/iiif/IIIFSharedUtils.java @@ -12,10 +12,13 @@ import java.util.List; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; +import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Item; import org.dspace.core.Constants; import org.dspace.license.CreativeCommonsServiceImpl; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; /** * Shared utilities for IIIF processing. @@ -29,6 +32,15 @@ public class IIIFSharedUtils { public static final String METADATA_IIIF_ENABLED = "dspace.iiif.enabled"; // The DSpace bundle for other content related to item. protected static final String OTHER_CONTENT_BUNDLE = "OtherContent"; + // The IIIF image server url from configuration + protected static final String IMAGE_SERVER_PATH = "iiif.image.server"; + public static final String METADATA_IIIF_SCHEMA = "iiif"; + public static final String METADATA_IIIF_IMAGE = "image"; + public static final String METADATA_IIIF_HEIGHT = "height"; + public static final String METADATA_IIIF_WIDTH = "width"; + + protected static final ConfigurationService configurationService + = DSpaceServicesFactory.getInstance().getConfigurationService(); private IIIFSharedUtils() {} @@ -87,4 +99,14 @@ public class IIIFSharedUtils { .filter(m -> m.getMetadataField().toString('.').contentEquals(METADATA_IIIF_ENABLED)) .noneMatch(m -> m.getValue().equalsIgnoreCase("false") || m.getValue().equalsIgnoreCase("no")); } + + /** + * Returns url for retrieving info.json metadata from the image server. + * @param bitstream + * @return + */ + public static String getInfoJsonPath(Bitstream bitstream) { + String iiifImageServer = configurationService.getProperty(IMAGE_SERVER_PATH); + return iiifImageServer + bitstream.getID() + "/info.json"; + } }