mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Compare commits
19 Commits
6ac823d29a
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2a4ac311c2 | ||
![]() |
5723ea1297 | ||
![]() |
fa2a639615 | ||
![]() |
a6699f3c43 | ||
![]() |
5fe6f9f1d0 | ||
![]() |
97782fae6e | ||
![]() |
8fc191e9cb | ||
![]() |
b5501981ab | ||
![]() |
61f2695b83 | ||
![]() |
8643888d68 | ||
![]() |
d8fbe16ede | ||
![]() |
29e13b77fc | ||
![]() |
fc74a7ffdf | ||
![]() |
dd6b3b4a55 | ||
![]() |
fa9df3a4ca | ||
![]() |
5bc41cb8ab | ||
![]() |
ccd3d12ad8 | ||
![]() |
82d04061c0 | ||
![]() |
08e330c1c0 |
@@ -738,7 +738,7 @@
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>1.12.791</version>
|
||||
<version>1.12.792</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -905,7 +905,7 @@
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-core</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<version>2.10.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@@ -7,9 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
@@ -63,27 +61,20 @@ public class BrandedPreviewJPEGFilter extends MediaFilter {
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
// read in bitstream's image
|
||||
BufferedImage buf = ImageIO.read(source);
|
||||
|
||||
// get config params
|
||||
ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
float xmax = (float) configurationService
|
||||
.getIntProperty("webui.preview.maxwidth");
|
||||
float ymax = (float) configurationService
|
||||
.getIntProperty("webui.preview.maxheight");
|
||||
boolean blurring = (boolean) configurationService
|
||||
.getBooleanProperty("webui.preview.blurring");
|
||||
boolean hqscaling = (boolean) configurationService
|
||||
.getBooleanProperty("webui.preview.hqscaling");
|
||||
int xmax = configurationService.getIntProperty("webui.preview.maxwidth");
|
||||
int ymax = configurationService.getIntProperty("webui.preview.maxheight");
|
||||
boolean blurring = configurationService.getBooleanProperty("webui.preview.blurring");
|
||||
boolean hqscaling = configurationService.getBooleanProperty("webui.preview.hqscaling");
|
||||
int brandHeight = configurationService.getIntProperty("webui.preview.brand.height");
|
||||
String brandFont = configurationService.getProperty("webui.preview.brand.font");
|
||||
int brandFontPoint = configurationService.getIntProperty("webui.preview.brand.fontpoint");
|
||||
|
||||
JPEGFilter jpegFilter = new JPEGFilter();
|
||||
return jpegFilter
|
||||
.getThumbDim(currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, brandHeight, brandFontPoint,
|
||||
brandFont);
|
||||
return jpegFilter.getThumb(
|
||||
currentItem, source, verbose, xmax, ymax, blurring, hqscaling, brandHeight, brandFontPoint, brandFont
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -8,19 +8,32 @@
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.Kernel;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.drew.imaging.ImageMetadataReader;
|
||||
import com.drew.imaging.ImageProcessingException;
|
||||
import com.drew.metadata.Metadata;
|
||||
import com.drew.metadata.MetadataException;
|
||||
import com.drew.metadata.exif.ExifIFD0Directory;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
@@ -33,6 +46,8 @@ import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
* @author Jason Sherman jsherman@usao.edu
|
||||
*/
|
||||
public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats {
|
||||
private static final Logger log = LogManager.getLogger(JPEGFilter.class);
|
||||
|
||||
@Override
|
||||
public String getFilteredName(String oldFilename) {
|
||||
return oldFilename + ".jpg";
|
||||
@@ -62,6 +77,115 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats
|
||||
return "Generated Thumbnail";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotation angle from image's metadata using ImageReader.
|
||||
* This method consumes the InputStream, so you need to be careful to don't reuse the same InputStream after
|
||||
* computing the rotation angle.
|
||||
*
|
||||
* @param buf InputStream of the image file
|
||||
* @return Rotation angle in degrees (0, 90, 180, or 270)
|
||||
*/
|
||||
public static int getImageRotationUsingImageReader(InputStream buf) {
|
||||
try {
|
||||
Metadata metadata = ImageMetadataReader.readMetadata(buf);
|
||||
ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
|
||||
if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
|
||||
return convertRotationToDegrees(directory.getInt(ExifIFD0Directory.TAG_ORIENTATION));
|
||||
}
|
||||
} catch (MetadataException | ImageProcessingException | IOException e) {
|
||||
log.error("Error reading image metadata", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int convertRotationToDegrees(int valueNode) {
|
||||
// Common orientation values:
|
||||
// 1 = Normal (0°)
|
||||
// 6 = Rotated 90° CW
|
||||
// 3 = Rotated 180°
|
||||
// 8 = Rotated 270° CW
|
||||
switch (valueNode) {
|
||||
case 6:
|
||||
return 90;
|
||||
case 3:
|
||||
return 180;
|
||||
case 8:
|
||||
return 270;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates an image by the specified angle
|
||||
*
|
||||
* @param image The original image
|
||||
* @param angle The rotation angle in degrees
|
||||
* @return Rotated image
|
||||
*/
|
||||
public static BufferedImage rotateImage(BufferedImage image, int angle) {
|
||||
if (angle == 0) {
|
||||
return image;
|
||||
}
|
||||
|
||||
double radians = Math.toRadians(angle);
|
||||
double sin = Math.abs(Math.sin(radians));
|
||||
double cos = Math.abs(Math.cos(radians));
|
||||
|
||||
int newWidth = (int) Math.round(image.getWidth() * cos + image.getHeight() * sin);
|
||||
int newHeight = (int) Math.round(image.getWidth() * sin + image.getHeight() * cos);
|
||||
|
||||
BufferedImage rotated = new BufferedImage(newWidth, newHeight, image.getType());
|
||||
Graphics2D g2d = rotated.createGraphics();
|
||||
AffineTransform at = new AffineTransform();
|
||||
|
||||
at.translate(newWidth / 2, newHeight / 2);
|
||||
at.rotate(radians);
|
||||
at.translate(-image.getWidth() / 2, -image.getHeight() / 2);
|
||||
|
||||
g2d.setTransform(at);
|
||||
g2d.drawImage(image, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
return rotated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates scaled dimension while maintaining aspect ratio
|
||||
*
|
||||
* @param imgSize Original image dimensions
|
||||
* @param boundary Maximum allowed dimensions
|
||||
* @return New dimensions that fit within boundary while preserving aspect ratio
|
||||
*/
|
||||
private Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
|
||||
|
||||
int originalWidth = imgSize.width;
|
||||
int originalHeight = imgSize.height;
|
||||
int boundWidth = boundary.width;
|
||||
int boundHeight = boundary.height;
|
||||
int newWidth = originalWidth;
|
||||
int newHeight = originalHeight;
|
||||
|
||||
|
||||
// First check if we need to scale width
|
||||
if (originalWidth > boundWidth) {
|
||||
// Scale width to fit
|
||||
newWidth = boundWidth;
|
||||
// Scale height to maintain aspect ratio
|
||||
newHeight = (newWidth * originalHeight) / originalWidth;
|
||||
}
|
||||
|
||||
// Then check if we need to scale even with the new height
|
||||
if (newHeight > boundHeight) {
|
||||
// Scale height to fit instead
|
||||
newHeight = boundHeight;
|
||||
newWidth = (newHeight * originalWidth) / originalHeight;
|
||||
}
|
||||
|
||||
return new Dimension(newWidth, newHeight);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param currentItem item
|
||||
* @param source source input stream
|
||||
@@ -72,10 +196,65 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats
|
||||
@Override
|
||||
public InputStream getDestinationStream(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
// read in bitstream's image
|
||||
BufferedImage buf = ImageIO.read(source);
|
||||
return getThumb(currentItem, source, verbose);
|
||||
}
|
||||
|
||||
return getThumb(currentItem, buf, verbose);
|
||||
public InputStream getThumb(Item currentItem, InputStream source, boolean verbose)
|
||||
throws Exception {
|
||||
// get config params
|
||||
final ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
int xmax = configurationService
|
||||
.getIntProperty("thumbnail.maxwidth");
|
||||
int ymax = configurationService
|
||||
.getIntProperty("thumbnail.maxheight");
|
||||
boolean blurring = (boolean) configurationService
|
||||
.getBooleanProperty("thumbnail.blurring");
|
||||
boolean hqscaling = (boolean) configurationService
|
||||
.getBooleanProperty("thumbnail.hqscaling");
|
||||
|
||||
return getThumb(currentItem, source, verbose, xmax, ymax, blurring, hqscaling, 0, 0, null);
|
||||
}
|
||||
|
||||
protected InputStream getThumb(
|
||||
Item currentItem,
|
||||
InputStream source,
|
||||
boolean verbose,
|
||||
int xmax,
|
||||
int ymax,
|
||||
boolean blurring,
|
||||
boolean hqscaling,
|
||||
int brandHeight,
|
||||
int brandFontPoint,
|
||||
String brandFont
|
||||
) throws Exception {
|
||||
|
||||
File tempFile = File.createTempFile("temp", ".tmp");
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
// Write to temp file
|
||||
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int len;
|
||||
while ((len = source.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
int rotation = 0;
|
||||
try (FileInputStream fis = new FileInputStream(tempFile)) {
|
||||
rotation = getImageRotationUsingImageReader(fis);
|
||||
}
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(tempFile)) {
|
||||
// read in bitstream's image
|
||||
BufferedImage buf = ImageIO.read(fis);
|
||||
|
||||
return getThumbDim(
|
||||
currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, brandHeight, brandFontPoint, rotation,
|
||||
brandFont
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getThumb(Item currentItem, BufferedImage buf, boolean verbose)
|
||||
@@ -83,25 +262,28 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats
|
||||
// get config params
|
||||
final ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
float xmax = (float) configurationService
|
||||
int xmax = configurationService
|
||||
.getIntProperty("thumbnail.maxwidth");
|
||||
float ymax = (float) configurationService
|
||||
int ymax = configurationService
|
||||
.getIntProperty("thumbnail.maxheight");
|
||||
boolean blurring = (boolean) configurationService
|
||||
.getBooleanProperty("thumbnail.blurring");
|
||||
boolean hqscaling = (boolean) configurationService
|
||||
.getBooleanProperty("thumbnail.hqscaling");
|
||||
|
||||
return getThumbDim(currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, 0, 0, null);
|
||||
return getThumbDim(currentItem, buf, verbose, xmax, ymax, blurring, hqscaling, 0, 0, 0, null);
|
||||
}
|
||||
|
||||
public InputStream getThumbDim(Item currentItem, BufferedImage buf, boolean verbose, float xmax, float ymax,
|
||||
public InputStream getThumbDim(Item currentItem, BufferedImage buf, boolean verbose, int xmax, int ymax,
|
||||
boolean blurring, boolean hqscaling, int brandHeight, int brandFontPoint,
|
||||
String brandFont)
|
||||
int rotation, String brandFont)
|
||||
throws Exception {
|
||||
// now get the image dimensions
|
||||
float xsize = (float) buf.getWidth(null);
|
||||
float ysize = (float) buf.getHeight(null);
|
||||
|
||||
// Rotate the image if needed
|
||||
BufferedImage correctedImage = rotateImage(buf, rotation);
|
||||
|
||||
int xsize = correctedImage.getWidth();
|
||||
int ysize = correctedImage.getHeight();
|
||||
|
||||
// if verbose flag is set, print out dimensions
|
||||
// to STDOUT
|
||||
@@ -109,86 +291,63 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats
|
||||
System.out.println("original size: " + xsize + "," + ysize);
|
||||
}
|
||||
|
||||
// scale by x first if needed
|
||||
if (xsize > xmax) {
|
||||
// calculate scaling factor so that xsize * scale = new size (max)
|
||||
float scale_factor = xmax / xsize;
|
||||
// Calculate new dimensions while maintaining aspect ratio
|
||||
Dimension newDimension = getScaledDimension(
|
||||
new Dimension(xsize, ysize),
|
||||
new Dimension(xmax, ymax)
|
||||
);
|
||||
|
||||
// if verbose flag is set, print out extracted text
|
||||
// to STDOUT
|
||||
if (verbose) {
|
||||
System.out.println("x scale factor: " + scale_factor);
|
||||
}
|
||||
|
||||
// now reduce x size
|
||||
// and y size
|
||||
xsize = xsize * scale_factor;
|
||||
ysize = ysize * scale_factor;
|
||||
|
||||
// if verbose flag is set, print out extracted text
|
||||
// to STDOUT
|
||||
if (verbose) {
|
||||
System.out.println("size after fitting to maximum width: " + xsize + "," + ysize);
|
||||
}
|
||||
}
|
||||
|
||||
// scale by y if needed
|
||||
if (ysize > ymax) {
|
||||
float scale_factor = ymax / ysize;
|
||||
|
||||
// now reduce x size
|
||||
// and y size
|
||||
xsize = xsize * scale_factor;
|
||||
ysize = ysize * scale_factor;
|
||||
}
|
||||
|
||||
// if verbose flag is set, print details to STDOUT
|
||||
if (verbose) {
|
||||
System.out.println("size after fitting to maximum height: " + xsize + ", "
|
||||
+ ysize);
|
||||
System.out.println("size after fitting to maximum height: " + newDimension.width + ", "
|
||||
+ newDimension.height);
|
||||
}
|
||||
|
||||
xsize = newDimension.width;
|
||||
ysize = newDimension.height;
|
||||
|
||||
// create an image buffer for the thumbnail with the new xsize, ysize
|
||||
BufferedImage thumbnail = new BufferedImage((int) xsize, (int) ysize,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
BufferedImage thumbnail = new BufferedImage(xsize, ysize, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// Use blurring if selected in config.
|
||||
// a little blur before scaling does wonders for keeping moire in check.
|
||||
if (blurring) {
|
||||
// send the buffered image off to get blurred.
|
||||
buf = getBlurredInstance((BufferedImage) buf);
|
||||
correctedImage = getBlurredInstance(correctedImage);
|
||||
}
|
||||
|
||||
// Use high quality scaling method if selected in config.
|
||||
// this has a definite performance penalty.
|
||||
if (hqscaling) {
|
||||
// send the buffered image off to get an HQ downscale.
|
||||
buf = getScaledInstance((BufferedImage) buf, (int) xsize, (int) ysize,
|
||||
(Object) RenderingHints.VALUE_INTERPOLATION_BICUBIC, (boolean) true);
|
||||
correctedImage = getScaledInstance(correctedImage, xsize, ysize,
|
||||
RenderingHints.VALUE_INTERPOLATION_BICUBIC, true);
|
||||
}
|
||||
|
||||
// now render the image into the thumbnail buffer
|
||||
Graphics2D g2d = thumbnail.createGraphics();
|
||||
g2d.drawImage(buf, 0, 0, (int) xsize, (int) ysize, null);
|
||||
g2d.drawImage(correctedImage, 0, 0, xsize, ysize, null);
|
||||
|
||||
if (brandHeight != 0) {
|
||||
ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
Brand brand = new Brand((int) xsize, brandHeight, new Font(brandFont, Font.PLAIN, brandFontPoint), 5);
|
||||
Brand brand = new Brand(xsize, brandHeight, new Font(brandFont, Font.PLAIN, brandFontPoint), 5);
|
||||
BufferedImage brandImage = brand.create(configurationService.getProperty("webui.preview.brand"),
|
||||
configurationService.getProperty("webui.preview.brand.abbrev"),
|
||||
currentItem == null ? "" : "hdl:" + currentItem.getHandle());
|
||||
|
||||
g2d.drawImage(brandImage, (int) 0, (int) ysize, (int) xsize, (int) 20, null);
|
||||
g2d.drawImage(brandImage, 0, ysize, xsize, 20, null);
|
||||
}
|
||||
|
||||
|
||||
ByteArrayInputStream bais;
|
||||
// now create an input stream for the thumbnail buffer and return it
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
ImageIO.write(thumbnail, "jpeg", baos);
|
||||
|
||||
// now get the array
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
}
|
||||
|
||||
return bais; // hope this gets written out before its garbage collected!
|
||||
}
|
||||
|
@@ -81,6 +81,7 @@ public class PDFBoxThumbnail extends MediaFilter {
|
||||
|
||||
// Generate thumbnail derivative and return as IO stream.
|
||||
JPEGFilter jpegFilter = new JPEGFilter();
|
||||
|
||||
return jpegFilter.getThumb(currentItem, buf, verbose);
|
||||
}
|
||||
}
|
||||
|
@@ -152,7 +152,7 @@ public class BitstreamDAOImpl extends AbstractHibernateDSODAO<Bitstream> impleme
|
||||
@Override
|
||||
public int countWithNoPolicy(Context context) throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"SELECT count(bit.id) from Bitstream bit where bit.deleted<>true and bit.id not in" +
|
||||
"SELECT count(bit.id) from Bitstream bit where bit.deleted<>true and bit not in" +
|
||||
" (select res.dSpaceObject from ResourcePolicy res where res.resourceTypeId = " +
|
||||
":typeId )");
|
||||
query.setParameter("typeId", Constants.BITSTREAM);
|
||||
|
@@ -12,6 +12,7 @@ import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
@@ -19,6 +20,7 @@ import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.authorize.ResourcePolicy_;
|
||||
import org.dspace.content.Collection;
|
||||
@@ -40,6 +42,11 @@ import org.dspace.eperson.Group;
|
||||
* @author kevinvandevelde at atmire.com
|
||||
*/
|
||||
public class CollectionDAOImpl extends AbstractHibernateDSODAO<Collection> implements CollectionDAO {
|
||||
/**
|
||||
* log4j logger
|
||||
*/
|
||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(CollectionDAOImpl.class);
|
||||
|
||||
protected CollectionDAOImpl() {
|
||||
super();
|
||||
}
|
||||
@@ -172,14 +179,25 @@ public class CollectionDAOImpl extends AbstractHibernateDSODAO<Collection> imple
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Map.Entry<Collection, Long>> getCollectionsWithBitstreamSizesTotal(Context context)
|
||||
throws SQLException {
|
||||
String q = "select col as collection, sum(bit.sizeBytes) as totalBytes from Item i join i.collections col " +
|
||||
"join i.bundles bun join bun.bitstreams bit group by col";
|
||||
String q = "select col.id, sum(bit.sizeBytes) as totalBytes from Item i join i.collections col " +
|
||||
"join i.bundles bun join bun.bitstreams bit group by col.id";
|
||||
Query query = createQuery(context, q);
|
||||
|
||||
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||
|
||||
List<Object[]> list = query.getResultList();
|
||||
List<Map.Entry<Collection, Long>> returnList = new ArrayList<>(list.size());
|
||||
for (Object[] o : list) {
|
||||
returnList.add(new AbstractMap.SimpleEntry<>((Collection) o[0], (Long) o[1]));
|
||||
CriteriaQuery<Collection> criteriaQuery = criteriaBuilder.createQuery(Collection.class);
|
||||
Root<Collection> collectionRoot = criteriaQuery.from(Collection.class);
|
||||
criteriaQuery.select(collectionRoot).where(criteriaBuilder.equal(collectionRoot.get("id"), (UUID) o[0]));
|
||||
Query collectionQuery = createQuery(context, criteriaQuery);
|
||||
Collection collection = (Collection) collectionQuery.getSingleResult();
|
||||
if (collection != null) {
|
||||
returnList.add(new AbstractMap.SimpleEntry<>(collection, (Long) o[1]));
|
||||
} else {
|
||||
log.warn("Unable to find Collection with UUID: {}", o[0]);
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
@@ -464,4 +464,14 @@ public abstract class AbstractHibernateDAO<T> implements GenericDAO<T> {
|
||||
return executeCriteriaQuery(context, criteria, cacheable, maxResults, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Query object from a CriteriaQuery
|
||||
* @param context current Context
|
||||
* @param criteriaQuery CriteriaQuery built via CriteriaBuilder
|
||||
* @return corresponding Query
|
||||
* @throws SQLException if error occurs
|
||||
*/
|
||||
public Query createQuery(Context context, CriteriaQuery criteriaQuery) throws SQLException {
|
||||
return this.getHibernateSession(context).createQuery(criteriaQuery);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
* 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.app.mediafilter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import org.dspace.AbstractUnitTest;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
|
||||
public class JPEGFilterTest extends AbstractUnitTest {
|
||||
|
||||
@Mock
|
||||
private ConfigurationService mockConfigurationService;
|
||||
|
||||
@Mock
|
||||
private DSpaceServicesFactory mockDSpaceServicesFactory;
|
||||
|
||||
@Mock
|
||||
private InputStream mockInputStream;
|
||||
|
||||
@Mock
|
||||
private Item mockItem;
|
||||
|
||||
/**
|
||||
* Tests that the convertRotationToDegrees method returns 0 for an input value
|
||||
* that doesn't match any of the defined rotation cases.
|
||||
*/
|
||||
@Test
|
||||
public void testConvertRotationToDegrees_UnknownValue_ReturnsZero() {
|
||||
int result = JPEGFilter.convertRotationToDegrees(5);
|
||||
assertEquals(0, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getNormalizedInstance method with a null input.
|
||||
* This tests the edge case of passing a null BufferedImage to the method.
|
||||
* The method should throw a NullPointerException when given a null input.
|
||||
*/
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testGetNormalizedInstanceWithNullInput() {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
filter.getNormalizedInstance(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getThumbDim method with a null BufferedImage input.
|
||||
* This tests the edge case where the input image is null, which should result in an exception.
|
||||
*/
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testGetThumbDimWithNullBufferedImage() throws Exception {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
Item currentItem = null;
|
||||
BufferedImage buf = null;
|
||||
boolean verbose = false;
|
||||
int xmax = 100;
|
||||
int ymax = 100;
|
||||
boolean blurring = false;
|
||||
boolean hqscaling = false;
|
||||
int brandHeight = 0;
|
||||
int brandFontPoint = 0;
|
||||
int rotation = 0;
|
||||
String brandFont = null;
|
||||
|
||||
filter.getThumbDim(
|
||||
currentItem, buf, verbose, xmax, ymax, blurring, hqscaling,
|
||||
brandHeight, brandFontPoint, rotation, brandFont
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the rotateImage method returns the original image when the rotation angle is 0.
|
||||
* This is an edge case explicitly handled in the method implementation.
|
||||
*/
|
||||
@Test
|
||||
public void testRotateImageWithZeroAngle() {
|
||||
BufferedImage originalImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||
BufferedImage rotatedImage = JPEGFilter.rotateImage(originalImage, 0);
|
||||
assertSame(
|
||||
"When rotation angle is 0, the original image should be returned",
|
||||
originalImage, rotatedImage
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for convertRotationToDegrees method when input is 6.
|
||||
* Expected to return 90 degrees for the rotation value of 6.
|
||||
*/
|
||||
@Test
|
||||
public void test_convertRotationToDegrees_whenInputIs6_returns90() {
|
||||
int input = 6;
|
||||
int expected = 90;
|
||||
int result = JPEGFilter.convertRotationToDegrees(input);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that getBlurredInstance method applies a blur effect to the input image.
|
||||
* It verifies that the returned image is not null, has the same dimensions as the input,
|
||||
* and is different from the original image (indicating that blurring has occurred).
|
||||
*/
|
||||
@Test
|
||||
public void test_getBlurredInstance_appliesBlurEffect() {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
BufferedImage original = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
BufferedImage blurred = filter.getBlurredInstance(original);
|
||||
|
||||
assertNotNull("Blurred image should not be null", blurred);
|
||||
assertEquals("Width should be the same", original.getWidth(), blurred.getWidth());
|
||||
assertEquals("Height should be the same", original.getHeight(), blurred.getHeight());
|
||||
assertNotEquals("Blurred image should be different from original", original, blurred);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for getBundleName method of JPEGFilter class.
|
||||
* This test verifies that the getBundleName method returns the expected string "THUMBNAIL".
|
||||
*/
|
||||
@Test
|
||||
public void test_getBundleName_returnsExpectedString() {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
String result = filter.getBundleName();
|
||||
assertEquals("THUMBNAIL", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the getDescription method returns the expected string "Generated Thumbnail".
|
||||
* This verifies that the method correctly provides the description for the JPEG filter.
|
||||
*/
|
||||
@Test
|
||||
public void test_getDescription_1() {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
String description = filter.getDescription();
|
||||
assertEquals("Generated Thumbnail", description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that getFilteredName method appends ".jpg" to the input filename.
|
||||
*/
|
||||
@Test
|
||||
public void test_getFilteredName_appendsJpgExtension() {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
String oldFilename = "testimage";
|
||||
String expectedResult = "testimage.jpg";
|
||||
String actualResult = filter.getFilteredName(oldFilename);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for getFormatString method of JPEGFilter class.
|
||||
* Verifies that the method returns the expected string "JPEG".
|
||||
*/
|
||||
@Test
|
||||
public void test_getFormatString_returnsJPEG() {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
String result = filter.getFormatString();
|
||||
assertEquals("JPEG", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of getImageRotationUsingImageReader when an ImageProcessingException occurs.
|
||||
* This test verifies that the method handles an ImageProcessingException by logging the error
|
||||
* and returning 0 degrees rotation.
|
||||
*/
|
||||
@Test
|
||||
public void test_getImageRotationUsingImageReader_imageProcessingException() {
|
||||
InputStream errorStream = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
throw new IOException("Simulated image processing error");
|
||||
}
|
||||
};
|
||||
int result = JPEGFilter.getImageRotationUsingImageReader(errorStream);
|
||||
assertEquals(0, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase for getImageRotationUsingImageReader when the image doesn't contain orientation metadata.
|
||||
* This test verifies that the method returns 0 when there's no ExifIFD0Directory
|
||||
* or when it doesn't contain the TAG_ORIENTATION.
|
||||
*/
|
||||
@Test
|
||||
public void test_getImageRotationUsingImageReader_noOrientationMetadata() throws IOException {
|
||||
URL resource = this.getClass().getResource("cat.jpg");
|
||||
int rotationAngle = -1;
|
||||
try (InputStream inputStream = new FileInputStream(resource.getFile())) {
|
||||
// Call the method under test
|
||||
rotationAngle = JPEGFilter.getImageRotationUsingImageReader(inputStream);
|
||||
}
|
||||
assertEquals(0, rotationAngle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getImageRotationUsingImageReader method when the image contains
|
||||
* valid EXIF orientation metadata.
|
||||
*
|
||||
* This test verifies that the method correctly reads the orientation tag
|
||||
* from the EXIF metadata and returns the appropriate rotation angle in degrees.
|
||||
*/
|
||||
@Test
|
||||
public void test_getImageRotationUsingImageReader_withValidExifOrientation() throws Exception {
|
||||
// Create a mock InputStream with EXIF metadata containing orientation information
|
||||
URL resource = this.getClass().getResource("cat-rotated-90.jpg");
|
||||
int rotationAngle = -1;
|
||||
try (InputStream inputStream = new FileInputStream(resource.getFile())) {
|
||||
// Call the method under test
|
||||
rotationAngle = JPEGFilter.getImageRotationUsingImageReader(inputStream);
|
||||
}
|
||||
|
||||
// Assert the expected rotation angle
|
||||
// Note: The expected value should be adjusted based on the mock data
|
||||
assertEquals(90, rotationAngle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getScaledInstance method of JPEGFilter class with higher quality scaling.
|
||||
* This test verifies that the method correctly scales down an image in multiple passes
|
||||
* when higherQuality is true and the image dimensions are larger than the target dimensions.
|
||||
*/
|
||||
@Test
|
||||
public void test_getScaledInstance() {
|
||||
JPEGFilter filter = new JPEGFilter();
|
||||
BufferedImage originalImage = new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);
|
||||
int targetWidth = 100;
|
||||
int targetHeight = 75;
|
||||
Object hint = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
|
||||
boolean higherQuality = true;
|
||||
|
||||
BufferedImage result = filter.getScaledInstance(originalImage, targetWidth, targetHeight, hint, higherQuality);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(targetWidth, result.getWidth());
|
||||
assertEquals(targetHeight, result.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the rotateImage method with a non-zero angle.
|
||||
* This test verifies that the image is rotated correctly when given a non-zero angle.
|
||||
*/
|
||||
@Test
|
||||
public void test_rotateImage_nonZeroAngle() {
|
||||
BufferedImage originalImage = new BufferedImage(100, 50, BufferedImage.TYPE_INT_RGB);
|
||||
int angle = 90;
|
||||
|
||||
BufferedImage rotatedImage = JPEGFilter.rotateImage(originalImage, angle);
|
||||
|
||||
assertNotNull(rotatedImage);
|
||||
assertEquals(50, rotatedImage.getWidth());
|
||||
assertEquals(100, rotatedImage.getHeight());
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
dspace-api/src/test/resources/org/dspace/app/mediafilter/cat.jpg
Normal file
BIN
dspace-api/src/test/resources/org/dspace/app/mediafilter/cat.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
@@ -16,6 +16,7 @@ import java.util.List;
|
||||
import com.lyncode.xoai.dataprovider.xml.xoai.Element;
|
||||
import com.lyncode.xoai.dataprovider.xml.xoai.Metadata;
|
||||
import com.lyncode.xoai.util.Base64Utils;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.factory.UtilServiceFactory;
|
||||
@@ -159,6 +160,19 @@ public class ItemUtils {
|
||||
return bundles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a string to remove characters that are invalid
|
||||
* in XML 1.0 using the Apache Commons Text library.
|
||||
* @param value The string to sanitize.
|
||||
* @return A sanitized string, or null if the input was null.
|
||||
*/
|
||||
private static String sanitize(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return StringEscapeUtils.escapeXml10(value);
|
||||
}
|
||||
|
||||
private static Element createLicenseElement(Context context, Item item)
|
||||
throws SQLException, AuthorizeException, IOException {
|
||||
Element license = create("license");
|
||||
@@ -232,7 +246,7 @@ public class ItemUtils {
|
||||
valueElem = language;
|
||||
}
|
||||
|
||||
valueElem.getField().add(createValue("value", val.getValue()));
|
||||
valueElem.getField().add(createValue("value", sanitize(val.getValue())));
|
||||
if (val.getAuthority() != null) {
|
||||
valueElem.getField().add(createValue("authority", val.getAuthority()));
|
||||
if (val.getConfidence() != Choices.CF_NOVALUE) {
|
||||
|
@@ -18,6 +18,7 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.security.BitstreamMetadataReadPermissionEvaluatorPlugin;
|
||||
import org.dspace.app.rest.signposting.model.LinksetNode;
|
||||
import org.dspace.app.rest.signposting.processor.bitstream.BitstreamSignpostingProcessor;
|
||||
import org.dspace.app.rest.signposting.processor.item.ItemLinksetProcessor;
|
||||
import org.dspace.app.rest.signposting.processor.item.ItemSignpostingProcessor;
|
||||
import org.dspace.app.rest.signposting.processor.metadata.MetadataSignpostingProcessor;
|
||||
import org.dspace.app.rest.signposting.service.LinksetService;
|
||||
@@ -28,6 +29,7 @@ import org.dspace.content.Item;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -40,12 +42,18 @@ public class LinksetServiceImpl implements LinksetService {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(LinksetServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
protected ItemService itemService;
|
||||
|
||||
@Autowired
|
||||
private BitstreamMetadataReadPermissionEvaluatorPlugin bitstreamMetadataReadPermissionEvaluatorPlugin;
|
||||
|
||||
@Autowired
|
||||
ItemLinksetProcessor itemLinksetProcessor;
|
||||
|
||||
private final List<BitstreamSignpostingProcessor> bitstreamProcessors = new DSpace().getServiceManager()
|
||||
.getServicesByType(BitstreamSignpostingProcessor.class);
|
||||
|
||||
@@ -74,11 +82,21 @@ public class LinksetServiceImpl implements LinksetService {
|
||||
Context context,
|
||||
DSpaceObject object
|
||||
) {
|
||||
int itemBitstreamsLimit = configurationService.getIntProperty("signposting.item.bitstreams.limit", 10);
|
||||
|
||||
List<LinksetNode> linksetNodes = new ArrayList<>();
|
||||
if (object.getType() == Constants.ITEM) {
|
||||
int itemBitstreamsCount = countItemBitstreams((Item) object);
|
||||
|
||||
// Do not include individual bitstream typed links if their number exceeds
|
||||
// the limit in the configuration.
|
||||
if (itemBitstreamsCount < itemBitstreamsLimit) {
|
||||
for (ItemSignpostingProcessor processor : itemProcessors) {
|
||||
processor.addLinkSetNodes(context, request, (Item) object, linksetNodes);
|
||||
}
|
||||
} else {
|
||||
itemLinksetProcessor.addLinkSetNodes(context, request, (Item) object, linksetNodes);
|
||||
}
|
||||
} else if (object.getType() == Constants.BITSTREAM) {
|
||||
for (BitstreamSignpostingProcessor processor : bitstreamProcessors) {
|
||||
processor.addLinkSetNodes(context, request, (Bitstream) object, linksetNodes);
|
||||
@@ -151,4 +169,17 @@ public class LinksetServiceImpl implements LinksetService {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int countItemBitstreams(Item item) {
|
||||
try {
|
||||
int countBitstreams = 0;
|
||||
List<Bundle> bundles = itemService.getBundles(item, Constants.DEFAULT_BUNDLE_NAME);
|
||||
for (Bundle bundle: bundles) {
|
||||
countBitstreams += bundle.getBitstreams().size();
|
||||
}
|
||||
return countBitstreams;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
package org.dspace.app.rest.signposting.controller;
|
||||
|
||||
import static org.dspace.content.MetadataSchemaEnum.PERSON;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
@@ -18,7 +19,9 @@ import java.io.InputStream;
|
||||
import java.text.DateFormat;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.codec.CharEncoding;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -691,6 +694,61 @@ public class LinksetRestControllerIT extends AbstractControllerIntegrationTest {
|
||||
"&& @.type == 'application/linkset+json')]").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showTypedLinksMissingForItemWithMoreBitstreamsThanLimit() throws Exception {
|
||||
String bitstreamContent = "ThisIsSomeDummyText";
|
||||
String bitstreamMimeType = "text/plain";
|
||||
|
||||
int itemBitstreamsLimit = configurationService.getIntProperty("signposting.item.bitstreams.limit", 10);
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
Item item = ItemBuilder.createItem(context, collection)
|
||||
.withTitle("Item Test")
|
||||
.withMetadata("dc", "identifier", "doi", doi)
|
||||
.build();
|
||||
|
||||
// Add more bitstreams than the configured limit
|
||||
ArrayList<UUID> bitstreamIDs = new ArrayList<>();
|
||||
for (int i = 0; i <= itemBitstreamsLimit; i++) {
|
||||
Bitstream bitstream = null;
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream = BitstreamBuilder.createBitstream(context, item, is)
|
||||
.withName("Bitstream " + i)
|
||||
.withDescription("description")
|
||||
.withMimeType(bitstreamMimeType)
|
||||
.build();
|
||||
|
||||
if (bitstream != null) {
|
||||
bitstreamIDs.add(bitstream.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// Make sure the bitstreams were successfully added.
|
||||
assertTrue("There was a problem ingesting bitstreams.", bitstreamIDs.size() > itemBitstreamsLimit);
|
||||
|
||||
String url = configurationService.getProperty("dspace.ui.url");
|
||||
String signpostingUrl = configurationService.getProperty("signposting.path");
|
||||
|
||||
// There should be typed links to the Link Sets but no typed links to the Bitstreams in the response.
|
||||
// We only need to check for one of the Bitstream UUIDs, since all of them should be absent.
|
||||
UUID firstBitstreamId = bitstreamIDs.get(0);
|
||||
getClient().perform(get("/signposting/links/" + item.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[?(@.href == '" + url + "/" + signpostingUrl + "/linksets/" +
|
||||
item.getID().toString() + "' " +
|
||||
"&& @.rel == 'linkset' " +
|
||||
"&& @.type == 'application/linkset')]").exists())
|
||||
.andExpect(jsonPath("$[?(@.href == '" + url + "/" + signpostingUrl + "/linksets/" +
|
||||
item.getID().toString() + "/json' " +
|
||||
"&& @.rel == 'linkset' " +
|
||||
"&& @.type == 'application/linkset+json')]").exists())
|
||||
.andExpect(jsonPath("$[?(@.href == '" + url + "/bitstreams/" + firstBitstreamId + "/download' " +
|
||||
"&& @.rel == 'item' " +
|
||||
"&& @.type == 'text/plain')]").doesNotExist());;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findTypedLinkForBitstream() throws Exception {
|
||||
String bitstreamContent = "ThisIsSomeDummyText";
|
||||
|
@@ -33,3 +33,8 @@ signposting.describedby.crosswalk-name = DataCite
|
||||
|
||||
# Mime-type of response of handling of 'describedby' links.
|
||||
signposting.describedby.mime-type = application/vnd.datacite.datacite+xml
|
||||
|
||||
# Limit to the number of an item's bitstreams to return as typed links.
|
||||
# If there are more bitstreams than this limit then only the typed links to the Link Sets are added to the header.
|
||||
# Defaults to 10 if the value is unspecified
|
||||
# signposting.item.bitstreams.limit = 10
|
18
pom.xml
18
pom.xml
@@ -38,7 +38,7 @@
|
||||
<jcache-version>1.1.1</jcache-version>
|
||||
<!-- NOTE: Jetty needed for Solr, Handle Server & tests -->
|
||||
<jetty.version>9.4.58.v20250814</jetty.version>
|
||||
<log4j.version>2.25.1</log4j.version>
|
||||
<log4j.version>2.25.2</log4j.version>
|
||||
<pdfbox-version>2.0.34</pdfbox-version>
|
||||
<rome.version>1.19.0</rome.version>
|
||||
<slf4j.version>1.7.36</slf4j.version>
|
||||
@@ -140,7 +140,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.14.0</version>
|
||||
<version>3.14.1</version>
|
||||
<configuration>
|
||||
<release>11</release>
|
||||
<!-- Turn on http://errorprone.info (requires fork=true & below compilerArgs)-->
|
||||
@@ -295,7 +295,7 @@
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<version>4.9.4.2</version>
|
||||
<version>4.9.6.0</version>
|
||||
<configuration>
|
||||
<effort>Max</effort>
|
||||
<threshold>Low</threshold>
|
||||
@@ -305,7 +305,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs</artifactId>
|
||||
<version>4.9.4</version>
|
||||
<version>4.9.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -357,13 +357,13 @@
|
||||
<plugin>
|
||||
<groupId>org.sonatype.central</groupId>
|
||||
<artifactId>central-publishing-maven-plugin</artifactId>
|
||||
<version>0.8.0</version>
|
||||
<version>0.9.0</version>
|
||||
</plugin>
|
||||
<!-- Used to generate JavaDocs for new releases (see release profile). -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.11.3</version>
|
||||
<version>3.12.0</version>
|
||||
<configuration>
|
||||
<!-- Never fail a build based on Javadoc errors -->
|
||||
<failOnError>false</failOnError>
|
||||
@@ -680,7 +680,7 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>2.6.0</version>
|
||||
<version>2.7.0</version>
|
||||
<!-- This plugin only needs to be run on the Parent POM
|
||||
as it aggregates results from all child POMs. -->
|
||||
<inherited>false</inherited>
|
||||
@@ -1503,7 +1503,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.18.0</version>
|
||||
<version>3.19.0</version>
|
||||
</dependency>
|
||||
<!-- NOTE: We don't use commons-logging or commons-compress directly,
|
||||
but many dependencies rely on them. Only here specified to avoid dependency convergence issues. -->
|
||||
@@ -1684,7 +1684,7 @@
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>2.3.232</version>
|
||||
<version>2.4.240</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Google Analytics -->
|
||||
|
Reference in New Issue
Block a user