diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96b1019306..5ffce68264 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: ports: - 46380:6379 fedora: - image: fcrepo/fcrepo:5.1.1 + image: fcrepo/fcrepo:5.1.1-multiplatform ports: - 48085:8080 volumes: @@ -38,7 +38,7 @@ jobs: - name: Get Container ID of fedora service id: get_container_id run: | - CONTAINER_ID=$(docker ps --format "{{.ID}}" -f "ancestor=fcrepo/fcrepo:5.1.1") + CONTAINER_ID=$(docker ps --format "{{.ID}}" -f "ancestor=fcrepo/fcrepo:5.1.1-multiplatform") echo "CONTAINER_ID=$CONTAINER_ID" >> $GITHUB_ENV - name: Restart fedora now that the repository has been checked out so config files are available run: docker restart ${{ env.CONTAINER_ID }} diff --git a/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java b/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java index 81a72d3da0..5c1aa25431 100644 --- a/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java +++ b/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java @@ -30,8 +30,6 @@ public class DatastreamPermissionUtil { DS_PERMISSION_MAP.put(DatastreamType.ORIGINAL_FILE, Permission.viewOriginal); DS_PERMISSION_MAP.put(DatastreamType.TECHNICAL_METADATA, Permission.viewHidden); DS_PERMISSION_MAP.put(DatastreamType.TECHNICAL_METADATA_HISTORY, Permission.viewHidden); - DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_SMALL, Permission.viewAccessCopies); - DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_LARGE, Permission.viewAccessCopies); } private DatastreamPermissionUtil() { diff --git a/docker-compose.yml b/docker-compose.yml index c54da4f291..06ea2ba4e4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: fedora: - image: fcrepo/fcrepo:5.1.1 + image: fcrepo/fcrepo:5.1.1-multiplatform ports: - "48085:8080" volumes: @@ -27,8 +27,8 @@ services: ports: - "48983:8983" volumes: - - ./etc/solr-config:/solr_config/config + - ./etc/solr-config:/var/solr/data/access/conf command: - solr-precreate - access - - /solr_config/config \ No newline at end of file + - /var/solr/data/access/conf \ No newline at end of file diff --git a/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java b/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java index e2b2772c3c..9b2440d3bf 100644 --- a/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java +++ b/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java @@ -55,7 +55,7 @@ public class SetDatastreamFilter implements IndexDocumentFilter { private DerivativeService derivativeService; private TechnicalMetadataService technicalMetadataService; private Jp2InfoService jp2InfoService; - private static final List THUMBNAIL_DS_TYPES = Arrays.asList(DatastreamType.THUMBNAIL_SMALL, DatastreamType.THUMBNAIL_LARGE); + // Check for hours, minutes, seconds. Plus a check for optional milliseconds separated from seconds // by a "." or a ":" via a non-capturing block followed by a capture group for the milliseconds. private final Pattern TIMING_REGEX = Pattern.compile("(\\d+):(\\d+):(\\d+)(?:[.:](\\d+))?"); @@ -87,7 +87,7 @@ public void filter(DocumentIndexingPackage dip) throws IndexingException { } if (contentObj instanceof WorkObject) { - addThumbnailDerivatives((WorkObject) contentObj, datastreams); + addThumbnailDerivative((WorkObject) contentObj, datastreams); } // Add in metadata datastreams @@ -288,6 +288,20 @@ private boolean needsExtent(String name, String mimetype) { || mimetype.startsWith("audio")); } + /** + * Used to selectively add the JP2 thumbnail datastream + * + * @param workObject the work object with the thumbnail relation + * @param datastreams work object's datastreams to add thumbnail streams to + */ + private void addThumbnailDerivative(WorkObject workObject, List datastreams) { + FileObject thumbnailObject = workObject.getThumbnailObject(); + + if (thumbnailObject != null) { + addDerivatives(datastreams, thumbnailObject.getPid(), true, List.of(JP2_ACCESS_COPY)); + } + } + private String getFirstChecksum(Resource resc) { Statement prop = resc.getProperty(Premis.hasMessageDigest); if (prop == null) { @@ -334,7 +348,8 @@ private long getFilesize(FileObject fileObject, List datastreams) th } private void addDerivatives(List dsList, PID pid, boolean ownedByOtherObject, List types) { - derivativeService.getDerivatives(pid).forEach(deriv -> { + var derivatives = derivativeService.getDerivatives(pid); + derivatives.forEach(deriv -> { DatastreamType type = deriv.getType(); // only add derivatives of types listed if ((types != null) && !types.contains(type)) { @@ -352,33 +367,6 @@ private void addDerivatives(List dsList, PID pid, boolean ownedByOth }); } - /** - * Used to selectively add only thumbnail datastreams - * - * @param workObject the work object with the thumbnail relation - * @param datastreams work object's datastreams to add thumbnail streams to - */ - private void addThumbnailDerivatives(WorkObject workObject, List datastreams) { - FileObject thumbnailObject = workObject.getThumbnailObject(); - - if (thumbnailObject != null) { - var updatedDatastreams = clearPreviousThumbnailDatastreams(datastreams); - addDerivatives(updatedDatastreams, thumbnailObject.getPid(), true, THUMBNAIL_DS_TYPES); - } - } - - /** - * There may be thumbnail streams from the primary object, so we'll clear those - * before adding the assigned thumbnail datastreams - * - * @param datastreams full list of datastreams to index for the work object - * @return modified list of datastreams without thumbnail datastreams - */ - private List clearPreviousThumbnailDatastreams(List datastreams) { - datastreams.removeIf(ds -> THUMBNAIL_DS_TYPES.contains(DatastreamType.getByIdentifier(ds.getName()))); - return datastreams; - } - private DatastreamImpl createDatastream(DerivativeService.Derivative derivative, String owner, String extent) { DatastreamType type = derivative.getType(); String name = type.getId(); diff --git a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java index 8e84ece0ae..5fc205886d 100644 --- a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java +++ b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java @@ -48,12 +48,9 @@ import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; import static edu.unc.lib.boxc.model.api.DatastreamType.TECHNICAL_METADATA; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_LARGE; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_SMALL; import static edu.unc.lib.boxc.model.fcrepo.ids.DatastreamPids.getOriginalFilePid; import static org.apache.jena.rdf.model.ResourceFactory.createResource; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -83,11 +80,8 @@ public class SetDatastreamFilterTest { private static final String FILE2_DIGEST = "urn:sha1:afbf62faf8a82d00969e0d4d965d62a45bb8c69b"; private static final long FILE2_SIZE = 7231l; - private static final String FILE3_MIMETYPE = "image/png"; - private static final String FILE3_NAME = "image.png"; - private static final String FILE3_DIGEST = "urn:sha1:280f5922b6487c39d6d01a5a8e93bfa07b8f1740"; - private static final long FILE3_SIZE = 17136l; - private static final String FILE3_EXTENT = "375x250"; + private static final String PNG_MIMETYPE = "image/png"; + private static final String IMAGE_EXTENT = "375x250"; private static final String FILE_MP3_MIMETYPE = "audio/mpeg"; private static final String FILE_MP3_NAME = "audio.mp3"; @@ -123,6 +117,8 @@ public class SetDatastreamFilterTest { private static final String PREMIS_DIGEST = "urn:sha1:da39a3ee5e6b4b0d3255bfef95601890afd80709"; private static final long PREMIS_SIZE = 893l; + private static final long JP2_SIZE = 11; + private AutoCloseable closeable; @TempDir @@ -201,12 +197,7 @@ public void fileObjectMultipleBinariesTest() throws Exception { fileResource(TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST)); when(binObj2.getBinaryStream()).thenReturn(getClass().getResourceAsStream("/datastream/techmd.xml")); - BinaryObject binObj3 = mock(BinaryObject.class); - when(binObj3.getPid()).thenReturn(PIDs.get(pid.getId() + "/" + THUMBNAIL_LARGE.getId())); - when(binObj3.getResource()).thenReturn( - fileResource(THUMBNAIL_LARGE.getId(), FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST)); - - when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2, binObj3)); + when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); dip.setContentObject(fileObj); filter.filter(dip); @@ -215,17 +206,15 @@ public void fileObjectMultipleBinariesTest() throws Exception { FILE_SIZE, FILE_MIMETYPE, FILE_NAME, FILE_DIGEST, null, null); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST, null, null); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); - assertEquals(FILE_SIZE + FILE2_SIZE + FILE3_SIZE, (long) idb.getFilesizeTotal()); + assertEquals(FILE_SIZE + FILE2_SIZE, (long) idb.getFilesizeTotal()); } @Test public void fileObjectImageBinaryTest() throws Exception { when(binObj.getResource()).thenReturn( - fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST)); + fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST)); BinaryObject binObj2 = mock(BinaryObject.class); when(binObj2.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -233,32 +222,26 @@ public void fileObjectImageBinaryTest() throws Exception { fileResource(TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST)); when(binObj2.getBinaryStream()).thenReturn(getClass().getResourceAsStream("/datastream/techmd.xml")); - BinaryObject binObj3 = mock(BinaryObject.class); - when(binObj3.getPid()).thenReturn(PIDs.get(pid.getId() + "/" + JP2_ACCESS_COPY.getId())); - when(binObj3.getResource()).thenReturn( - fileResource(THUMBNAIL_LARGE.getId(), FILE3_SIZE, JP2_ACCESS_COPY.getMimetype(), - JP2_ACCESS_COPY.getDefaultFilename(), FILE3_DIGEST)); + List derivs = makeJP2Derivative(); + var pid = PIDs.get(PID_STRING); + when(derivativeService.getDerivatives(pid)).thenReturn(derivs); - BinaryObject binObj4 = mock(BinaryObject.class); - when(binObj4.getPid()).thenReturn(PIDs.get(pid.getId() + "/" + THUMBNAIL_LARGE.getId())); - when(binObj4.getResource()).thenReturn( - fileResource(THUMBNAIL_LARGE.getId(), FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST)); - when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2, binObj3, binObj4)); + when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); dip.setContentObject(fileObj); filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), - FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST, null, FILE3_EXTENT); + FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST, null, IMAGE_EXTENT); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST, null, null); + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, null); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); // JP2 and thumbnail set to same size - assertEquals(FILE_SIZE + FILE2_SIZE + (FILE3_SIZE * 2), (long) idb.getFilesizeTotal()); + assertEquals(FILE_SIZE + FILE2_SIZE + JP2_SIZE, (long) idb.getFilesizeTotal()); } @Test @@ -465,7 +448,7 @@ public void fileObjectVideoNoHeightWidthBinaryTest() throws Exception { @Test public void fileObjectImageBinaryNoDimensionsTest() throws Exception { when(binObj.getResource()).thenReturn( - fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST)); + fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST)); BinaryObject binObj2 = mock(BinaryObject.class); when(binObj2.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -479,7 +462,7 @@ public void fileObjectImageBinaryNoDimensionsTest() throws Exception { filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), - FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST, null, null); + FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST, null, null); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); @@ -491,7 +474,7 @@ public void fileObjectImageBinaryNoDimensionsTest() throws Exception { @Test public void fileObjectImageBinaryWithJp2DimensionsTest() throws Exception { when(binObj.getResource()).thenReturn( - fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST)); + fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST)); BinaryObject binObj2 = mock(BinaryObject.class); when(binObj2.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -504,18 +487,7 @@ public void fileObjectImageBinaryWithJp2DimensionsTest() throws Exception { when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); dip.setContentObject(fileObj); - File smallFile = derivDir.resolve("small.png").toFile(); - FileUtils.write(smallFile, "content", "UTF-8"); - - File largeFile = derivDir.resolve("large.png").toFile(); - FileUtils.write(largeFile, "large content", "UTF-8"); - - File jp2File = derivDir.resolve("access.jp2").toFile(); - FileUtils.write(jp2File, "jp2 content", "UTF-8"); - - List derivs = Arrays.asList(new Derivative(THUMBNAIL_SMALL, smallFile), - new Derivative(THUMBNAIL_LARGE, largeFile), - new Derivative(JP2_ACCESS_COPY, jp2File)); + List derivs = makeJP2Derivative(); when(derivativeService.getDerivatives(filePid)).thenReturn(derivs); var mockJp2InfoService = mock(Jp2InfoService.class); @@ -525,11 +497,11 @@ public void fileObjectImageBinaryWithJp2DimensionsTest() throws Exception { filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), - FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST, null, FILE3_EXTENT); + FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST, null, IMAGE_EXTENT); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), - 11, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, "1000x600"); + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, "1000x600"); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); } @@ -604,7 +576,7 @@ public void workObjectTest() throws Exception { } @Test - public void workObjectWithoutPrimaryObjectTest() throws Exception { + public void workObjectWithoutPrimaryObjectTest() { WorkObject workObj = mock(WorkObject.class); dip.setContentObject(workObj); @@ -625,7 +597,8 @@ public void workObjectWithThumbnailNoPrimaryObjectTest() throws Exception { PID filePid = PIDs.get(fileId); when(fileObj.getPid()).thenReturn(filePid); when(binObj.getPid()).thenReturn(getOriginalFilePid(filePid)); - setUpDerivatives(filePid); + var derivs = makeJP2Derivative(); + when(derivativeService.getDerivatives(filePid)).thenReturn(derivs); dip.setContentObject(workObj); filter.filter(dip); @@ -633,7 +606,9 @@ public void workObjectWithThumbnailNoPrimaryObjectTest() throws Exception { assertNotNull(idb.getDatastream()); assertNull(idb.getFilesizeSort()); assertNotNull(idb.getFilesizeTotal()); - assertThumbnailDatastreams(fileId); + + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, fileId, null); } @Test @@ -649,7 +624,6 @@ public void workObjectTestWithPrimaryAndThumbnailObjects() throws Exception { PID filePid = PIDs.get(fileId); when(fileObj.getPid()).thenReturn(filePid); when(binObj.getPid()).thenReturn(getOriginalFilePid(filePid)); - setUpDerivatives(filePid); // set up thumbnail file object FileObject thumbnailObj = mock(FileObject.class); @@ -657,13 +631,13 @@ public void workObjectTestWithPrimaryAndThumbnailObjects() throws Exception { String thumbnailId = "066ed112-f548-479e-ab4b-bf1aad40d678"; PID thumbnailPid = PIDs.get(thumbnailId); when(thumbnailObj.getPid()).thenReturn(thumbnailPid); - setUpDerivatives(thumbnailPid); + var derivs = makeJP2Derivative(); + when(derivativeService.getDerivatives(thumbnailPid)).thenReturn(derivs); filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), FILE_SIZE, FILE_MIMETYPE, FILE_NAME, FILE_DIGEST, fileId, null); - assertThumbnailDatastreams(thumbnailId); assertContainsMetadataDatastreams(idb.getDatastream()); // Sort size is based off primary object's size @@ -671,10 +645,8 @@ public void workObjectTestWithPrimaryAndThumbnailObjects() throws Exception { // Work has no datastreams of its own assertEquals(FILE2_SIZE + MODS_SIZE + PREMIS_SIZE, (long) idb.getFilesizeTotal()); - assertDoesNotContainDatastream(idb.getDatastream(), THUMBNAIL_SMALL.getId(), - 7l, THUMBNAIL_SMALL.getMimetype(), "small.png", null, fileId, null); - assertDoesNotContainDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - 13l, THUMBNAIL_LARGE.getMimetype(), "large.png", null, fileId, null); + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, thumbnailId, null); } @Test @@ -691,28 +663,40 @@ public void folderObjectWithMetadataTest() throws Exception { assertEquals(FILE2_SIZE + MODS_SIZE + PREMIS_SIZE, (long) idb.getFilesizeTotal()); } + @Test + public void folderObjectWithJP2Test() throws Exception { + FolderObject folderObj = mock(FolderObject.class); + when(folderObj.getPid()).thenReturn(pid); + + List derivs = makeJP2Derivative(); + when(derivativeService.getDerivatives(pid)).thenReturn(derivs); + + dip.setContentObject(folderObj); + + filter.filter(dip); + + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, null); + } + @Test public void fileObjectWithDerivativeTest() throws Exception { when(fileObj.getPid()).thenReturn(pid); - when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj)); + when(fileObj.getBinaryObjects()).thenReturn(List.of(binObj)); dip.setContentObject(fileObj); - File derivFile = derivDir.resolve("deriv.png").toFile(); - FileUtils.write(derivFile, "content", "UTF-8"); - long derivSize = 7l; - - List derivs = Arrays.asList(new Derivative(THUMBNAIL_SMALL, derivFile)); + List derivs = makeJP2Derivative(); when(derivativeService.getDerivatives(pid)).thenReturn(derivs); filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), FILE_SIZE, FILE_MIMETYPE, FILE_NAME, FILE_DIGEST, null, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_SMALL.getId(), - derivSize, THUMBNAIL_SMALL.getMimetype(), derivFile.getName(), null, null, null); + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, null); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); - assertEquals(FILE_SIZE + derivSize, (long) idb.getFilesizeTotal()); + assertEquals(FILE_SIZE + JP2_SIZE, (long) idb.getFilesizeTotal()); } @Test @@ -751,17 +735,6 @@ private void assertContainsDatastream(List values, String name, long fil assertTrue(values.contains(joined), "Did not contain datastream " + name); } - private void assertDoesNotContainDatastream(List values, String name, long filesize, String mimetype, - String filename, String digest, String owner, String extent) { - String extension = filename.substring(filename.lastIndexOf('.') + 1); - List components = Arrays.asList( - name, mimetype, filename, extension, filesize, digest, owner, extent); - String joined = components.stream() - .map(c -> c == null ? "" : c.toString()) - .collect(Collectors.joining("|")); - assertFalse(values.contains(joined), "Contains datastream " + name); - } - private void addMetadataDatastreams(ContentObject obj) throws Exception { BinaryObject fitsBin = mock(BinaryObject.class); when(fitsBin.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -789,22 +762,10 @@ private void assertContainsMetadataDatastreams(List values) { PREMIS_SIZE, PREMIS_MIMETYPE, PREMIS_NAME, PREMIS_DIGEST, null, null); } - private void setUpDerivatives(PID filePid) throws IOException { - File smallFile = derivDir.resolve("small.png").toFile(); - FileUtils.write(smallFile, "content", "UTF-8"); - - File largeFile = derivDir.resolve("large.png").toFile(); - FileUtils.write(largeFile, "large content", "UTF-8"); - - List derivs = Arrays.asList(new Derivative(THUMBNAIL_SMALL, smallFile), - new Derivative(THUMBNAIL_LARGE, largeFile)); - when(derivativeService.getDerivatives(filePid)).thenReturn(derivs); - } + private List makeJP2Derivative() throws IOException { + File jp2File = derivDir.resolve("access.jp2").toFile(); + FileUtils.write(jp2File, "jp2 content", "UTF-8"); - private void assertThumbnailDatastreams(String thumbnailId) { - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_SMALL.getId(), - 7l, THUMBNAIL_SMALL.getMimetype(), "small.png", null, thumbnailId, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - 13l, THUMBNAIL_LARGE.getMimetype(), "large.png", null, thumbnailId, null); + return List.of(new Derivative(JP2_ACCESS_COPY, jp2File)); } } diff --git a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java index 91a7a099c9..a82ec3e103 100644 --- a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java +++ b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java @@ -78,6 +78,9 @@ public List populate() { newDoc.addField("ancestorIds", makeAncestorIds(pid1, pid2)); newDoc.addField("ancestorPath", makeAncestorPath(pid1)); newDoc.addField("resourceType", "Collection"); + List collectionDatastream = List.of( + DatastreamType.JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||" + pid2.getId() + "|1200x1200"); + newDoc.addField(SearchFieldKey.DATASTREAM.getSolrField(), collectionDatastream); docs.add(newDoc); newDoc = new SolrInputDocument(); @@ -115,8 +118,8 @@ public List populate() { newDoc.addField("ancestorPath", makeAncestorPath(pid1, pid2, pid6)); newDoc.addField("resourceType", ResourceType.File.name()); List imgDatastreams = Arrays.asList( - ORIGINAL_FILE.getId() + "|image/png|file.png|png|766|urn:sha1:checksum|1200x1200", - DatastreamType.JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||1200x1200"); + ORIGINAL_FILE.getId() + "|image/png|file.png|png|766|urn:sha1:checksum||1200x1200", + DatastreamType.JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||" + pid6File.getId() + "|1200x1200"); newDoc.addField(SearchFieldKey.DATASTREAM.getSolrField(), imgDatastreams); newDoc.addField(SearchFieldKey.FILE_FORMAT_CATEGORY.getSolrField(), ContentCategory.image.getDisplayName()); newDoc.addField(SearchFieldKey.FILE_FORMAT_TYPE.getSolrField(), "png"); diff --git a/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java b/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java index 8ee8e90108..4ce2fb2d07 100644 --- a/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java +++ b/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java @@ -62,7 +62,7 @@ public Map validateOptions(Map options) { } protected void addThumbnail(ContentObject object) throws IOException { - var derivativePath = derivativeService.getDerivativePath(object.getPid(), DatastreamType.THUMBNAIL_LARGE); + var derivativePath = derivativeService.getDerivativePath(object.getPid(), DatastreamType.JP2_ACCESS_COPY); FileUtils.write(derivativePath.toFile(), "image", "UTF-8"); } diff --git a/it_config/allowed_external_paths.txt b/it_config/allowed_external_paths.txt index c3cad514a5..13697b76ee 100644 --- a/it_config/allowed_external_paths.txt +++ b/it_config/allowed_external_paths.txt @@ -1 +1 @@ -file:/tmp/boxc_test_storage/ \ No newline at end of file +file:/tmp/boxc_test_storage/ diff --git a/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java b/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java index 55f0c503ba..a71eb53275 100644 --- a/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java +++ b/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java @@ -20,9 +20,7 @@ public enum DatastreamType { MD_EVENTS("event_log", "application/n-triples", "nt", METADATA_CONTAINER, INTERNAL), ORIGINAL_FILE("original_file", null, null, DATA_FILE_FILESET, INTERNAL), TECHNICAL_METADATA("techmd_fits", "text/xml", "xml", DATA_FILE_FILESET, INTERNAL), - TECHNICAL_METADATA_HISTORY("techmd_fits_history", "text/xml", "xml", DATA_FILE_FILESET, INTERNAL), - THUMBNAIL_SMALL("thumbnail_small", "image/png", "png", null, EXTERNAL), - THUMBNAIL_LARGE("thumbnail_large", "image/png", "png", null, EXTERNAL); + TECHNICAL_METADATA_HISTORY("techmd_fits_history", "text/xml", "xml", DATA_FILE_FILESET, INTERNAL); private final String id; private final String mimetype; diff --git a/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java b/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java index 75672ef760..4aec2ace4a 100644 --- a/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java +++ b/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java @@ -1,27 +1,25 @@ package edu.unc.lib.boxc.model.fcrepo.services; -import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; -import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_SMALL; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import edu.unc.lib.boxc.model.api.DatastreamType; +import edu.unc.lib.boxc.model.api.ids.PID; +import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; +import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService.Derivative; +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import edu.unc.lib.boxc.model.api.DatastreamType; -import edu.unc.lib.boxc.model.api.ids.PID; -import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; -import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService; -import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService.Derivative; +import static edu.unc.lib.boxc.model.api.DatastreamType.FULLTEXT_EXTRACTION; +import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; +import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; /** * @@ -56,48 +54,48 @@ public void init() throws Exception { @Test public void testGetDerivative() throws Exception { - File originalDerivFile = createDerivative(pid, THUMBNAIL_SMALL); + File originalDerivFile = createDerivative(pid, JP2_ACCESS_COPY); - Derivative deriv = derivativeService.getDerivative(pid, THUMBNAIL_SMALL); + Derivative deriv = derivativeService.getDerivative(pid, JP2_ACCESS_COPY); assertEquals(originalDerivFile, deriv.getFile()); - assertEquals(THUMBNAIL_SMALL, deriv.getType()); + assertEquals(JP2_ACCESS_COPY, deriv.getType()); } @Test public void testGetDerivativeNotExist() throws Exception { - Derivative deriv = derivativeService.getDerivative(pid, THUMBNAIL_SMALL); + Derivative deriv = derivativeService.getDerivative(pid, JP2_ACCESS_COPY); assertNull(deriv); } @Test public void testGetDerivatives() throws Exception { - File originalDerivFile1 = createDerivative(pid, THUMBNAIL_SMALL); + File originalDerivFile1 = createDerivative(pid, FULLTEXT_EXTRACTION); File originalDerivFil21 = createDerivative(pid, JP2_ACCESS_COPY); List derivs = derivativeService.getDerivatives(pid); assertEquals(2, derivs.size()); - Derivative thumbDeriv = findDerivative(derivs, THUMBNAIL_SMALL); + Derivative textDeriv = findDerivative(derivs, FULLTEXT_EXTRACTION); Derivative jp2Deriv = findDerivative(derivs, JP2_ACCESS_COPY); - assertNotNull(thumbDeriv); + assertNotNull(textDeriv); assertNotNull(jp2Deriv); - assertEquals(originalDerivFile1, thumbDeriv.getFile()); + assertEquals(originalDerivFile1, textDeriv.getFile()); assertEquals(originalDerivFil21, jp2Deriv.getFile()); } @Test public void testGetDerivativesIgnoreNonDerivatives() throws Exception { - File originalDerivFile1 = createDerivative(pid, THUMBNAIL_SMALL); + File originalDerivFile1 = createDerivative(pid, JP2_ACCESS_COPY); createDerivative(pid, ORIGINAL_FILE); List derivs = derivativeService.getDerivatives(pid); assertEquals(1, derivs.size()); - Derivative thumbDeriv = findDerivative(derivs, THUMBNAIL_SMALL); + Derivative thumbDeriv = findDerivative(derivs, JP2_ACCESS_COPY); assertEquals(originalDerivFile1, thumbDeriv.getFile()); } diff --git a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequest.java b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequest.java new file mode 100644 index 0000000000..ccf35de18d --- /dev/null +++ b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequest.java @@ -0,0 +1,52 @@ +package edu.unc.lib.boxc.operations.jms.thumbnails; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; +import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; + +import java.nio.file.Path; + +/** + * Request object for importing an image as thumbnail for a collection, folder, or admin unit + * + * @author snluong + */ +public class ImportThumbnailRequest { + @JsonDeserialize(as = AgentPrincipalsImpl.class) + private AgentPrincipals agent; + private String mimetype; + private Path storagePath; + private String pidString; + + public String getPidString() { + return pidString; + } + + public void setPidString(String pidString) { + this.pidString = pidString; + } + + public AgentPrincipals getAgent() { + return agent; + } + + public void setAgent(AgentPrincipals agent) { + this.agent = agent; + } + + public String getMimetype() { + return mimetype; + } + + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + public Path getStoragePath() { + return storagePath; + } + + public void setStoragePath(Path storagePath) { + this.storagePath = storagePath; + } +} diff --git a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequestSerializationHelper.java b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequestSerializationHelper.java new file mode 100644 index 0000000000..a7712a2e5a --- /dev/null +++ b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequestSerializationHelper.java @@ -0,0 +1,46 @@ +package edu.unc.lib.boxc.operations.jms.thumbnails; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; + +import java.io.IOException; + +/** + * Helper methods for serializing and deserializing import thumbnail requests + * + * @author snluong + */ +public class ImportThumbnailRequestSerializationHelper { + private static final ObjectWriter REQUEST_WRITER; + private static final ObjectReader REQUEST_READER; + static { + ObjectMapper mapper = new ObjectMapper(); + REQUEST_WRITER = mapper.writerFor(ImportThumbnailRequest.class); + REQUEST_READER = mapper.readerFor(ImportThumbnailRequest.class); + } + + private ImportThumbnailRequestSerializationHelper() { + } + + /** + * Transform request into a JSON string + * @param request + * @return + * @throws IOException + */ + public static String toJson(ImportThumbnailRequest request) throws IOException { + return REQUEST_WRITER.writeValueAsString(request); + } + + /** + * Transform JSON string to an ImportThumbnailRequest + * @param json + * @return + * @throws IOException + */ + public static ImportThumbnailRequest toRequest(String json) throws IOException { + return REQUEST_READER.readValue(json); + } +} + diff --git a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java index 80862ea0fc..43ff7cf568 100644 --- a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java +++ b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java @@ -16,6 +16,8 @@ public class ThumbnailRequestSender extends MessageSender { private static final Logger log = LoggerFactory.getLogger(ThumbnailRequestSender.class); private static final ObjectWriter MAPPER = new ObjectMapper().writerFor(ThumbnailRequest.class); + private static final ObjectWriter IMPORT_MAPPER = new ObjectMapper().writerFor(ImportThumbnailRequest.class); + private String importDestinationName; /** * Send a ThumbnailRequest to the configured JMS queue @@ -28,4 +30,30 @@ public void sendToQueue(ThumbnailRequest request) throws IOException { log.info("Job to {} thumbnail has been queued for {} with file {}", request.getAction(), request.getAgent().getUsername(), request.getFilePidString()); } + + /** + * Send an ImportThumbnailRequest to the appropriate JMS queue + * @param request + * @throws IOException + */ + public void sendToImportQueue(ImportThumbnailRequest request) throws IOException { + String messageBody = IMPORT_MAPPER.writeValueAsString(request); + sendImportMessage(messageBody); + log.info("Job to import thumbnail has been queued for {} with object {}", + request.getAgent().getUsername(), request.getPidString()); + } + + public void sendImportMessage(String msgStr) { + jmsTemplate.send(importDestinationName, (session -> { + // Committing the session to flush changes in long-running threads + if (session.getTransacted()) { + session.commit(); + } + return session.createTextMessage(msgStr); + })); + } + + public void setImportDestinationName(String importDestinationName) { + this.importDestinationName = importDestinationName; + } } diff --git a/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java b/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java index 77aea3793a..93edaa2c6a 100644 --- a/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java +++ b/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java @@ -8,13 +8,16 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.Mock; import org.springframework.jms.core.JmsTemplate; import java.io.IOException; +import java.nio.file.Path; import java.util.UUID; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.openMocks; @@ -24,15 +27,19 @@ public class ThumbnailRequestSenderTest { @Mock private JmsTemplate jmsTemplate; + @TempDir + private Path storagePath; private ThumbnailRequestSender thumbnailRequestSender; private AutoCloseable closeable; private final AgentPrincipals agent = new AgentPrincipalsImpl("user", new AccessGroupSetImpl("agroup")); + private String importQueue = "import.queue"; @BeforeEach public void setup() { closeable = openMocks(this); thumbnailRequestSender = new ThumbnailRequestSender(); thumbnailRequestSender.setJmsTemplate(jmsTemplate); + thumbnailRequestSender.setImportDestinationName(importQueue); } @AfterEach @@ -52,6 +59,19 @@ public void sendToQueueTest() throws IOException { verify(jmsTemplate).send(any()); } + @Test + public void sendToImportQueueTest() throws IOException { + var pidString = makePid().toString(); + var request = new ImportThumbnailRequest(); + request.setAgent(agent); + request.setPidString(pidString); + request.setStoragePath(storagePath); + request.setMimetype("image/jpeg"); + + thumbnailRequestSender.sendToImportQueue(request); + verify(jmsTemplate).send(eq(importQueue), any()); + } + public static PID makePid() { return PIDs.get(UUID.randomUUID().toString()); } diff --git a/pom.xml b/pom.xml index b3da161ff3..c2017d42b0 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ 4.5.13 1.26.0 1.17.1 - 2.7 + 2.17.0 1.6 3.8.1 1.5 @@ -1063,4 +1063,4 @@ - \ No newline at end of file + diff --git a/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java b/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java index c3d8d1709b..528a9cd260 100644 --- a/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java +++ b/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java @@ -7,7 +7,7 @@ import java.util.HashSet; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; /** * @author lfarrell @@ -15,22 +15,22 @@ public class QueryFilterFactoryTest { @Test public void NamedDatastreamFilterTest() { - var filter = QueryFilterFactory.createFilter(SearchFieldKey.DATASTREAM, DatastreamType.THUMBNAIL_LARGE); - assertTrue(filter instanceof NamedDatastreamFilter); + var filter = QueryFilterFactory.createFilter(SearchFieldKey.DATASTREAM, DatastreamType.JP2_ACCESS_COPY); + assertInstanceOf(NamedDatastreamFilter.class, filter); } @Test public void MultipleDirectlyOwnedDatastreamsFilterTest() { var datastreamTypes = new HashSet(); - datastreamTypes.add(DatastreamType.THUMBNAIL_LARGE); - datastreamTypes.add(DatastreamType.THUMBNAIL_SMALL); + datastreamTypes.add(DatastreamType.JP2_ACCESS_COPY); + datastreamTypes.add(DatastreamType.FULLTEXT_EXTRACTION); var filter = QueryFilterFactory.createFilter(SearchFieldKey.DATASTREAM, datastreamTypes); - assertTrue(filter instanceof MultipleDirectlyOwnedDatastreamsFilter); + assertInstanceOf(MultipleDirectlyOwnedDatastreamsFilter.class, filter); } @Test public void HasPopulatedFieldFilterTest() { var filter = QueryFilterFactory.createFilter(SearchFieldKey.STREAMING_TYPE); - assertTrue(filter instanceof HasPopulatedFieldFilter); + assertInstanceOf(HasPopulatedFieldFilter.class, filter); } } diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessor.java deleted file mode 100644 index 255cba281e..0000000000 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessor.java +++ /dev/null @@ -1,51 +0,0 @@ -package edu.unc.lib.boxc.services.camel; - -import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_DEPTH; -import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_SIZE; -import static edu.unc.lib.boxc.model.fcrepo.ids.RepositoryPaths.idToPath; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; -import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.camel.Processor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; - -/** - * Processor to add headers to create display thumbnails for non-file objects - * - * @author lfarrell - */ -public class NonBinaryEnhancementProcessor implements Processor { - private static final Logger log = LoggerFactory.getLogger(NonBinaryEnhancementProcessor.class); - - private String sourceImagesDir; - - @Override - public void process(final Exchange exchange) throws Exception { - final Message in = exchange.getIn(); - - String uri = (String) in.getHeader(FCREPO_URI); - String uuid = PIDs.get(uri).getUUID(); - String objBasePath = idToPath(uuid, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - - Path imgFile = Paths.get(sourceImagesDir, objBasePath, uuid); - - if (Files.isRegularFile(imgFile)) { - in.setHeader(CdrBinaryPath, imgFile.toAbsolutePath().toString()); - in.setHeader(CdrBinaryMimeType, "image/*"); - } - } - - public void setSourceImagesDir(String sourceImagesDir) { - this.sourceImagesDir = sourceImagesDir; - } -} diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java index fcbc2b4f54..b65a8752c1 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java @@ -1,17 +1,14 @@ package edu.unc.lib.boxc.services.camel.destroyDerivatives; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrObjectType; -import static org.slf4j.LoggerFactory.getLogger; - +import edu.unc.lib.boxc.services.camel.fulltext.FulltextProcessor; +import edu.unc.lib.boxc.services.camel.images.ImageDerivativeProcessor; import org.apache.camel.BeanInject; import org.apache.camel.LoggingLevel; import org.apache.camel.PropertyInject; import org.apache.camel.builder.RouteBuilder; import org.slf4j.Logger; -import edu.unc.lib.boxc.model.api.rdf.Cdr; -import edu.unc.lib.boxc.services.camel.fulltext.FulltextProcessor; -import edu.unc.lib.boxc.services.camel.images.ImageDerivativeProcessor; +import static org.slf4j.LoggerFactory.getLogger; /** * Router to process requests to destroy derivatives for an object @@ -25,15 +22,6 @@ public class DestroyDerivativesRouter extends RouteBuilder { @BeanInject(value = "destroyedMsgProcessor") private DestroyedMsgProcessor destroyedMsgProcessor; - @BeanInject(value = "destroyCollectionSrcImgProcessor") - private DestroyDerivativesProcessor destroyCollectionSrcImgProcessor; - - @BeanInject(value = "destroySmallThumbnailProcessor") - private DestroyDerivativesProcessor destroySmallThumbnailProcessor; - - @BeanInject(value = "destroyLargeThumbnailProcessor") - private DestroyDerivativesProcessor destroyLargeThumbnailProcessor; - @BeanInject(value = "destroyAccessCopyProcessor") private DestroyDerivativesProcessor destroyAccessCopyProcessor; @@ -74,45 +62,14 @@ public void configure() throws Exception { from("direct:image.derivatives.destroy") .routeId("CdrDestroyImage") .startupOrder(202) - .log(LoggingLevel.DEBUG, log, "Destroying derivative thumbnails") - .bean(destroySmallThumbnailProcessor) - .bean(destroyLargeThumbnailProcessor) - .choice() - .when(simple("${headers['" + CdrObjectType + "']} == '" + Cdr.FileObject.getURI() + "'")) - .to("direct:image.access.destroy") - .when(simple("${headers['CollectionThumb']} != null")) - .to("direct:image.collection.destroy") - .end(); - - from("direct:image.access.destroy") - .routeId("CdrDestroyAccessCopy") - .startupOrder(201) - .log(LoggingLevel.DEBUG, log, "Destroying access copy") + .log(LoggingLevel.DEBUG, log, "Destroying access copy derivatives") .bean(destroyAccessCopyProcessor); - - from("direct:image.collection.destroy") - .routeId("CdrDestroyCollectionUpload") - .startupOrder(200) - .log(LoggingLevel.DEBUG, log, "Destroying collection image upload") - .bean(destroyCollectionSrcImgProcessor); } public void setDestroyedMsgProcessor(DestroyedMsgProcessor destroyedMsgProcessor) { this.destroyedMsgProcessor = destroyedMsgProcessor; } - public void setDestroyCollectionSrcImgProcessor(DestroyDerivativesProcessor destroyCollectionSrcImgProcessor) { - this.destroyCollectionSrcImgProcessor = destroyCollectionSrcImgProcessor; - } - - public void setDestroySmallThumbnailProcessor(DestroyDerivativesProcessor destroySmallThumbnailProcessor) { - this.destroySmallThumbnailProcessor = destroySmallThumbnailProcessor; - } - - public void setDestroyLargeThumbnailProcessor(DestroyDerivativesProcessor destroyLargeThumbnailProcessor) { - this.destroyLargeThumbnailProcessor = destroyLargeThumbnailProcessor; - } - public void setDestroyAccessCopyProcessor(DestroyDerivativesProcessor destroyAccessCopyProcessor) { this.destroyAccessCopyProcessor = destroyAccessCopyProcessor; } diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java index 85dd4fa15b..b466bd1391 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java @@ -32,12 +32,8 @@ * */ public class DestroyedMsgProcessor implements Processor { - private final String srcBasePath; private static final Logger log = LoggerFactory.getLogger(DestroyedMsgProcessor.class); - - public DestroyedMsgProcessor(String srcBasePath) { - this.srcBasePath = srcBasePath; - } + private String jp2BasePath; @Override public void process(Exchange exchange) throws Exception { @@ -56,14 +52,13 @@ public void process(Exchange exchange) throws Exception { String pidId = content.getChildTextTrim("pidId", JDOMNamespaceUtil.CDR_MESSAGE_NS); String binaryPath = content.getChildTextTrim("contentUri", JDOMNamespaceUtil.CDR_MESSAGE_NS); - if (objType.equals(Cdr.Collection.getURI()) || objType.equals(Cdr.AdminUnit.getURI())) { + if (!objType.equals(Cdr.FileObject.getURI())) { String uuid = PIDs.get(pidId).getId(); String binarySubPath = idToPath(uuid, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - Path srcPath = Paths.get(srcBasePath, binarySubPath, uuid); + Path jp2Path = Paths.get(jp2BasePath, binarySubPath, uuid + ".jp2"); - if (Files.exists(srcPath)) { - mimeType = "image/*"; - in.setHeader("CollectionThumb", true); + if (Files.exists(jp2Path)) { + mimeType = "image/jp2"; } } @@ -79,4 +74,8 @@ public void process(Exchange exchange) throws Exception { in.setHeader(CdrBinaryPath, binaryPath); in.setHeader(CdrObjectType, objType); } + + public void setJp2BasePath(String jp2BasePath) { + this.jp2BasePath = jp2BasePath; + } } diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java index ee5881c3b7..7f11f96f25 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java @@ -17,7 +17,6 @@ import edu.unc.lib.boxc.model.api.rdf.Cdr; import edu.unc.lib.boxc.services.camel.BinaryEnhancementProcessor; import edu.unc.lib.boxc.services.camel.BinaryMetadataProcessor; -import edu.unc.lib.boxc.services.camel.NonBinaryEnhancementProcessor; /** * Router which queues and triggers enhancement services. @@ -35,14 +34,10 @@ public class EnhancementRouter extends RouteBuilder { @BeanInject(value = "binaryMetadataProcessor") private BinaryMetadataProcessor mdProcessor; - @BeanInject(value = "nonBinaryEnhancementProcessor") - private NonBinaryEnhancementProcessor nbProcessor; - @PropertyInject(value = "cdr.enhancement.processingThreads") private Integer enhancementThreads; - private static final String DEFAULT_ENHANCEMENTS = "thumbnails,imageAccessCopy,extractFulltext"; - private static final String THUMBNAIL_ENHANCEMENTS = "thumbnails"; + private static final String DEFAULT_ENHANCEMENTS = "imageAccessCopy,extractFulltext"; @Override public void configure() throws Exception { @@ -68,9 +63,7 @@ public void configure() throws Exception { + " || ${headers[org.fcrepo.jms.resourceType]} contains '" + Cdr.ContentRoot.getURI() + "'" )) .log(DEBUG, log, "Processing enhancements for non-binary ${headers[CamelFcrepoUri]}") - .process(nbProcessor) - .setHeader(CdrEnhancementSet, constant(THUMBNAIL_ENHANCEMENTS)) - .to("{{cdr.enhancement.perform.camel}}") + .to("direct:solrIndexing") .otherwise() .log(DEBUG, log, "Ignoring resource ${headers[CamelFcrepoUri]}") .end(); @@ -84,21 +77,15 @@ public void configure() throws Exception { .filter(header(CdrBinaryPath).isNotNull()) .to("{{cdr.enhancement.perform.camel}}"); - // Queue for executing enhancnement operations + // Queue for executing enhancement operations from("{{cdr.enhancement.perform.camel}}") .routeId("PerformEnhancementsQueue") .startupOrder(107) - .choice() - .when(simple("${headers[" + CdrBinaryPath + "]} == null")) - .log(INFO, log, "Indexing queued resource without binary path ${headers[CamelFcrepoUri]}") - .to("direct:solrIndexing") - .otherwise() - .log(INFO, log, "Processing queued enhancements ${headers[CdrEnhancementSet]}" + - "for ${headers[CamelFcrepoUri]}") - .multicast() - // trigger enhancements sequentially followed by indexing - .to("direct:process.enhancements", "direct:solrIndexing") - .end(); + .log(INFO, log, "Processing queued enhancements ${headers[CdrEnhancementSet]}" + + "for ${headers[CamelFcrepoUri]}") + .multicast() + // trigger enhancements sequentially followed by indexing + .to("direct:process.enhancements", "direct:solrIndexing"); // Expands enhancement requests into individual services from("direct:process.enhancements") diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java index f49052e2e8..2b5d916b04 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java @@ -1,14 +1,13 @@ package edu.unc.lib.boxc.services.camel.images; -import java.util.regex.Pattern; - +import edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders; +import java.util.regex.Pattern; /** * Processor which validates and prepares image objects for producing derivatives diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java index c9b4ca057a..f763bb6b74 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java @@ -21,12 +21,6 @@ public class ImageEnhancementsRouter extends RouteBuilder { private static final Logger log = getLogger(ImageEnhancementsRouter.class); - @BeanInject(value = "addSmallThumbnailProcessor") - private AddDerivativeProcessor addSmallThumbnailProcessor; - - @BeanInject(value = "addLargeThumbnailProcessor") - private AddDerivativeProcessor addLargeThumbProcessor; - @BeanInject(value = "addAccessCopyProcessor") private AddDerivativeProcessor addAccessCopyProcessor; @@ -50,52 +44,6 @@ public void configure() throws Exception { .backOffMultiplier("{{error.backOffMultiplier}}") .retryAttemptedLogLevel(LoggingLevel.WARN); - from("direct:process.enhancement.thumbnails") - .routeId("ProcessThumbnails") - .startupOrder(23) - .log(LoggingLevel.INFO, log, "Thumbs ${headers[CdrBinaryPath]} with ${headers[CdrMimeType]}") - .filter().method(imageDerivProcessor, "allowedImageType") - .log(LoggingLevel.INFO, log, "Generating thumbnails for ${headers[org.fcrepo.jms.identifier]}" - + " of type ${headers[CdrMimeType]}") - .bean(imageDerivProcessor) - // Generate an random identifier to avoid derivative collisions - .setBody(exchange -> uuidGenerator.generateUuid()) - .multicast() - .shareUnitOfWork() - .to("direct:small.thumbnail", "direct:large.thumbnail"); - - from("direct:small.thumbnail") - .routeId("SmallThumbnail") - .startupOrder(22) - .log(LoggingLevel.INFO, log, "Creating/Updating Small Thumbnail for ${headers[CdrImagePath]}") - .filter().method(addSmallThumbnailProcessor, "needsRun") - .setHeader(CdrFcrepoHeaders.CdrTempPath, simple("${properties:services.tempDirectory}/${body}-small")) - .doTry() - .recipientList(simple("exec:/bin/sh?args=${properties:cdr.enhancement.bin}/convertScaleStage.sh " - + "${headers[CdrImagePath]} png 64 64 ${headers[CdrTempPath]}")) - .bean(addSmallThumbnailProcessor) - .endDoTry() - .doFinally() - // Ensure temp files get cleaned up in case of failure - .bean(addSmallThumbnailProcessor, "cleanupTempFile") - .end(); - - - from("direct:large.thumbnail") - .routeId("LargeThumbnail") - .startupOrder(21) - .log(LoggingLevel.INFO, log, "Creating/Updating Large Thumbnail for ${headers[CdrImagePath]}") - .filter().method(addLargeThumbProcessor, "needsRun") - .setHeader(CdrFcrepoHeaders.CdrTempPath, simple("${properties:services.tempDirectory}/${body}-large")) - .doTry() - .recipientList(simple("exec:/bin/sh?args=${properties:cdr.enhancement.bin}/convertScaleStage.sh " - + "${headers[CdrImagePath]} png 128 128 ${headers[CdrTempPath]}")) - .bean(addLargeThumbProcessor) - .endDoTry() - .doFinally() - .bean(addLargeThumbProcessor, "cleanupTempFile") - .end(); - from("direct:process.enhancement.imageAccessCopy") .routeId("AccessCopy") .startupOrder(20) diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailRequestProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailRequestProcessor.java new file mode 100644 index 0000000000..589da47484 --- /dev/null +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailRequestProcessor.java @@ -0,0 +1,33 @@ +package edu.unc.lib.boxc.services.camel.thumbnails; + +import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequestSerializationHelper; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; + +import java.io.IOException; + +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; +import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; + +/** + * Processing requests to import images to use as a thumbnail for a non-work Repository object + * + * @author snluong + */ +public class ImportThumbnailRequestProcessor implements Processor { + @Override + public void process(Exchange exchange) throws IOException { + var in = exchange.getIn(); + var request = ImportThumbnailRequestSerializationHelper.toRequest(in.getBody(String.class)); + var mimetype = request.getMimetype(); + var storagePath = request.getStoragePath(); + var pidString = request.getPidString(); + var repoPath = PIDs.get(pidString).getRepositoryPath(); + + in.setHeader(CdrBinaryPath, storagePath.toString()); + in.setHeader(CdrBinaryMimeType, mimetype); + in.setHeader(FCREPO_URI, repoPath); + } +} diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java index 130de4fb2c..6c68957820 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java @@ -8,7 +8,9 @@ import static org.slf4j.LoggerFactory.getLogger; /** - * Router for processing assigning thumbnails for works + * Router for processing thumbnails: + * Importing thumbnails for collections, folders, and admin units + * Assigning thumbnails for works * * @author snluong */ @@ -16,12 +18,23 @@ public class ThumbnailRouter extends RouteBuilder { private static final Logger log = getLogger(ThumbnailRouter.class); @BeanInject(value = "thumbnailRequestProcessor") private ThumbnailRequestProcessor thumbnailRequestProcessor; + @BeanInject(value = "importThumbnailRequestProcessor") + private ImportThumbnailRequestProcessor importThumbnailRequestProcessor; @Override public void configure() throws Exception { from("{{cdr.thumbnails.stream.camel}}") - .routeId("DcrThumbnails") - .log(DEBUG, log, "Received thumbnail request") - .bean(thumbnailRequestProcessor); + .routeId("DcrThumbnails") + .log(DEBUG, log, + "Received thumbnail request: assigning thumbnail for ${headers[CamelFcrepoUri]}") + .bean(thumbnailRequestProcessor); + + from("{{cdr.import.thumbnails.stream.camel}}") + .routeId("DcrImportThumbnails") + .process(importThumbnailRequestProcessor) + .log(DEBUG, log, + "Received thumbnail request: importing thumbnail for ${headers[CamelFcrepoUri]}") + // trigger JP2 generation sequentially followed by indexing + .to("direct:process.enhancement.imageAccessCopy", "direct:solrIndexing"); } } diff --git a/services-camel-app/src/main/webapp/WEB-INF/service-context.xml b/services-camel-app/src/main/webapp/WEB-INF/service-context.xml index f27cf80e0b..ad70ec2706 100644 --- a/services-camel-app/src/main/webapp/WEB-INF/service-context.xml +++ b/services-camel-app/src/main/webapp/WEB-INF/service-context.xml @@ -193,10 +193,6 @@ - - - - @@ -210,16 +206,6 @@ - - - - - - - - - - @@ -236,7 +222,7 @@ - + @@ -244,16 +230,6 @@ - - - - - - - - - - @@ -517,6 +493,9 @@ + + + diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessorTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessorTest.java deleted file mode 100644 index 42be4aa503..0000000000 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessorTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package edu.unc.lib.boxc.services.camel; - -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; -import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; - -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import org.mockito.Mock; - -import edu.unc.lib.boxc.model.fcrepo.test.TestHelper; - -/** - * @author lfarrell - */ -public class NonBinaryEnhancementProcessorTest { - private NonBinaryEnhancementProcessor processor; - private AutoCloseable closeable; - - @TempDir - public Path tmpFolder; - - private static final String FEDORA_BASE = "http://example.com/rest/"; - - private static final String RESC_ID = "de75d811-9e0f-4b1f-8631-2060ab3580cc"; - private static final String RESC_URI = FEDORA_BASE + "content/de/75/d8/11/" + RESC_ID; - - @Mock - private Exchange exchange; - @Mock - private Message message; - private File imgFile; - private String dataDir; - - @BeforeEach - public void init() throws Exception { - closeable = openMocks(this); - dataDir = tmpFolder.toString(); - - TestHelper.setContentBase(FEDORA_BASE); - processor = new NonBinaryEnhancementProcessor(); - processor.setSourceImagesDir(dataDir); - - when(exchange.getIn()).thenReturn(message); - when(message.getHeader(FCREPO_URI)).thenReturn(RESC_URI); - } - - @AfterEach - void closeService() throws Exception { - closeable.close(); - } - - @Test - public void testCollectionWithImage() throws Exception { - String derivativeFinalPath = "de/75/d8/11/" + RESC_ID; - Path uploadedFilePath = Paths.get(dataDir, derivativeFinalPath); - Files.createDirectories(uploadedFilePath.getParent()); - - imgFile = new File(uploadedFilePath.toString()); - FileUtils.writeStringToFile(imgFile, "image file", StandardCharsets.UTF_8); - - processor.process(exchange); - - verify(message).setHeader(CdrBinaryMimeType, "image/*"); - verify(message).setHeader(CdrBinaryPath, imgFile.getAbsolutePath()); - } - - @Test - public void testCollectionWithoutImage() throws Exception { - imgFile = new File(dataDir + "/1234"); - - processor.process(exchange); - - verify(message, never()).setHeader(CdrBinaryMimeType, "image/*"); - verify(message, never()).setHeader(CdrBinaryPath, imgFile.getAbsolutePath()); - } -} diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java index e5ba3ce9ca..d171194432 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java @@ -2,7 +2,6 @@ import static edu.unc.lib.boxc.model.api.DatastreamType.FULLTEXT_EXTRACTION; import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_LARGE; import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPidId; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -97,60 +96,6 @@ public void deleteFulltextTest() throws Exception { assertTrue(derivativeTypeBaseDir.exists()); } - @Test - public void deleteThumbnailTest() throws Exception { - derivativeTypeDir = THUMBNAIL_LARGE.getId(); - derivativeFinalDir = Files.createDirectories(tmpFolder.resolve(derivativeTypeDir + "/de/75/d8/11")).toFile(); - file = new File(derivativeFinalDir, pathId + ".png"); - - FileUtils.writeStringToFile(file, "fake image", StandardCharsets.UTF_8); - - derivativeTypeBaseDir = new File(derivativeDirBase, derivativeTypeDir); - processor = new DestroyDerivativesProcessor("png", derivativeTypeBaseDir.getAbsolutePath()); - - when(message.getHeader(eq(CdrBinaryMimeType))) - .thenReturn("image/png"); - - processor.process(exchange); - - // Deleted file - assertFalse(file.exists()); - // Deleted parent dirs - assertFalse(new File(derivativeTypeBaseDir, "de").exists()); - // Didn't delete root derivative type dir - assertTrue(derivativeTypeBaseDir.exists()); - } - - @Test - public void deleteCollectionSrcImgTest() throws Exception { - String srcDirBase = "srcDir"; - File srcDir = Files.createDirectories(tmpFolder.resolve(srcDirBase + "/de/75/d8/11")).toFile(); - File srcFile = new File(srcDir, pathId); - FileUtils.writeStringToFile(srcFile, "fake image src", StandardCharsets.UTF_8); - - derivativeTypeBaseDir = new File(derivativeDirBase, srcDirBase); - - processor = new DestroyDerivativesProcessor("", derivativeTypeBaseDir.getAbsolutePath()); - - when(message.getHeader(eq(CdrBinaryMimeType))) - .thenReturn("image/*"); - - when(message.getHeader(eq("CollectionThumb"))) - .thenReturn(true); - - assertTrue(srcFile.exists()); - assertTrue(srcDir.exists()); - - processor.process(exchange); - - // Make sure src image is removed - assertFalse(srcFile.exists()); - assertFalse(srcDir.exists()); - - // Didn't delete root derivative type dir - assertTrue(derivativeTypeBaseDir.exists()); - } - @Test public void deleteJp2Test() throws Exception { derivativeTypeDir = JP2_ACCESS_COPY.getId(); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java index b1f7a6c235..babaa31b81 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java @@ -40,11 +40,13 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.Mock; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.File; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -90,13 +92,10 @@ public class DestroyDerivativesRouterIT extends CamelSpringTestSupport { @Mock private MemberOrderRequestSender memberOrderRequestSender; - private DestroyedMsgProcessor destroyedMsgProcessor; - - private DestroyDerivativesProcessor destroyCollectionSrcImgProcessor; + @TempDir + public Path tmpFolder; - private DestroyDerivativesProcessor destroySmallThumbnailProcessor; - - private DestroyDerivativesProcessor destroyLargeThumbnailProcessor; + private DestroyedMsgProcessor destroyedMsgProcessor; private DestroyDerivativesProcessor destroyAccessCopyProcessor; @@ -145,9 +144,6 @@ public void init() { indexingMessageSender = applicationContext.getBean(IndexingMessageSender.class); binaryDestroyedMessageSender = applicationContext.getBean("binaryDestroyedMessageSender", MessageSender.class); destroyedMsgProcessor = applicationContext.getBean(DestroyedMsgProcessor.class); - destroyCollectionSrcImgProcessor = applicationContext.getBean("destroyCollectionSrcImgProcessor", DestroyDerivativesProcessor.class); - destroySmallThumbnailProcessor = applicationContext.getBean("destroySmallThumbnailProcessor", DestroyDerivativesProcessor.class); - destroyLargeThumbnailProcessor = applicationContext.getBean("destroyLargeThumbnailProcessor", DestroyDerivativesProcessor.class); destroyAccessCopyProcessor = applicationContext.getBean("destroyAccessCopyProcessor", DestroyDerivativesProcessor.class); destroyFulltextProcessor = applicationContext.getBean("destroyFulltextProcessor", DestroyDerivativesProcessor.class); @@ -165,6 +161,7 @@ public void init() { .model); collection = repoObjectFactory.createCollectionObject(null); + destroyedMsgProcessor.setJp2BasePath(tmpFolder.toString()); contentRoot.addMember(adminUnit); adminUnit.addMember(collection); @@ -195,9 +192,6 @@ public void destroyImageTest() throws Exception { initializeDestroyJob(Collections.singletonList(fileObj.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); } @@ -209,23 +203,21 @@ public void destroyCollectionImageTest() throws Exception { treeIndexer.indexAll(baseAddress); - // Create collection thumbnail + // Create collection thumbnail jp2 PID collPid = collectionWithImg.getPid(); String uuid = collPid.getId(); String binarySubPath = idToPath(uuid, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - Path existingFileDirs = Files.createDirectories(new File("target/" + binarySubPath).toPath()); - File existingFile = new File(existingFileDirs.toString(), uuid); - FileUtils.writeStringToFile(existingFile, "thumbnail", "UTF-8"); + var derivativeFinalDir = Files.createDirectories(tmpFolder.resolve( binarySubPath)).toFile(); + var file = new File(derivativeFinalDir, uuid + ".jp2"); + FileUtils.writeStringToFile(file, "fake jp2", StandardCharsets.UTF_8); - markForDeletion(collPid); + new MarkForDeletionJob(collPid, "", agent, repoObjLoader, + sparqlUpdateService, aclService, premisLoggerFactory).run(); initializeDestroyJob(Collections.singletonList(collPid)); destroyJob.run(); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor).process(any(Exchange.class)); - verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); + verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); } @@ -240,9 +232,6 @@ public void destroyCollectionNoImageTest() throws Exception { initializeDestroyJob(Collections.singletonList(collectionWithImg.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); } @@ -260,9 +249,6 @@ public void destroyTextTest() throws Exception { initializeDestroyJob(Collections.singletonList(fileObj.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyFulltextProcessor).process(any(Exchange.class)); } @@ -279,9 +265,6 @@ public void invalidTypeTest() throws Exception { initializeDestroyJob(Collections.singletonList(fileObj.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); } diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java index a935539fa2..7751b8912d 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java @@ -16,7 +16,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.nio.file.Files; import java.nio.file.Path; import java.util.concurrent.TimeUnit; @@ -30,7 +29,6 @@ public class DestroyDerivativesRouterTest extends CamelTestSupport { private static final String DESTROY_DERIVATIVES_ROUTE = "CdrDestroyDerivatives"; private static final String DESTROY_FULLTEXT_ROUTE = "CdrDestroyFullText"; private static final String DESTROY_IMAGE_ROUTE = "CdrDestroyImage"; - private static final String DESTROY_ACCESS_COPY_ROUTE = "CdrDestroyAccessCopy"; private static final String TEST_ID = "dee2614c-8a4b-4ac2-baf2-4b4afc11af87"; @Produce("direct:start") @@ -41,12 +39,6 @@ public class DestroyDerivativesRouterTest extends CamelTestSupport { @Mock private DestroyDerivativesProcessor destroyCollectionSrcImgProcessor; - @Mock - private DestroyDerivativesProcessor destroySmallThumbnailProcessor; - - @Mock - private DestroyDerivativesProcessor destroyLargeThumbnailProcessor; - @Mock private DestroyDerivativesProcessor destroyAccessCopyProcessor; @@ -58,12 +50,9 @@ public class DestroyDerivativesRouterTest extends CamelTestSupport { @Override protected RouteBuilder createRouteBuilder() throws Exception { - destroyedMsgProcessor = new DestroyedMsgProcessor(tmpFolder.toAbsolutePath().toString()); + destroyedMsgProcessor = new DestroyedMsgProcessor(); var router = new DestroyDerivativesRouter(); router.setDestroyedMsgProcessor(destroyedMsgProcessor); - router.setDestroyCollectionSrcImgProcessor(destroyCollectionSrcImgProcessor); - router.setDestroySmallThumbnailProcessor(destroySmallThumbnailProcessor); - router.setDestroyLargeThumbnailProcessor(destroyLargeThumbnailProcessor); router.setDestroyAccessCopyProcessor(destroyAccessCopyProcessor); router.setDestroyFulltextProcessor(destroyFulltextProcessor); router.setDestroyDerivativesStreamCamel("direct:destroy.derivatives.stream"); @@ -137,9 +126,7 @@ public void destroyTextDerivative() throws Exception { template.sendBody(body); verify(destroyFulltextProcessor).process(any(Exchange.class)); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); } @@ -151,20 +138,12 @@ public void destroyImageThumbnailDerivative() throws Exception { var body = createMessage(Cdr.FileObject, "image/png", TEST_ID, contentPath); template.sendBody(body); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); - verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); + verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); } @Test public void destroyImageThumbnailDerivativeCollection() throws Exception { - // Create the thumbnail file for the collection - var thumbPath = tmpFolder.resolve("de/e2/61/4c").resolve(TEST_ID); - Files.createDirectories(thumbPath.getParent()); - Files.createFile(thumbPath); - AdviceWith.adviceWith(context, DESTROY_DERIVATIVES_ROUTE, a -> { a.replaceFromWith("direct:start"); }); @@ -173,10 +152,7 @@ public void destroyImageThumbnailDerivativeCollection() throws Exception { var body = createMessage(Cdr.Collection, "image/*", TEST_ID, contentPath); template.sendBody(body); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor).process(any(Exchange.class)); - verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); + verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); } @@ -199,7 +175,7 @@ public void destroyImageThumbnailNoDerivativeCollection() throws Exception { @Test public void destroyImageAccessDerivative() throws Exception { - createContext(DESTROY_ACCESS_COPY_ROUTE); + createContext(DESTROY_IMAGE_ROUTE); Path contentPath = tmpFolder.resolve("content"); var body = createMessage(Cdr.FileObject, "image/png", TEST_ID, contentPath); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java index 61025eada1..91af35f93f 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java @@ -15,7 +15,6 @@ import edu.unc.lib.boxc.operations.impl.edit.UpdateDescriptionService; import edu.unc.lib.boxc.operations.impl.edit.UpdateDescriptionService.UpdateDescriptionRequest; import edu.unc.lib.boxc.persist.impl.storage.StorageLocationTestHelper; -import edu.unc.lib.boxc.services.camel.NonBinaryEnhancementProcessor; import edu.unc.lib.boxc.services.camel.fulltext.FulltextProcessor; import edu.unc.lib.boxc.services.camel.images.AddDerivativeProcessor; import edu.unc.lib.boxc.services.camel.solr.SolrIngestProcessor; @@ -84,10 +83,6 @@ public class EnhancementRouterIT extends CamelSpringTestSupport { @Produce("{{cdr.enhancement.stream.camel}}") private ProducerTemplate template; - private AddDerivativeProcessor addSmallThumbnailProcessor; - - private AddDerivativeProcessor addLargeThumbnailProcessor; - private AddDerivativeProcessor addAccessCopyProcessor; private SolrIngestProcessor solrIngestProcessor; @@ -101,7 +96,6 @@ public class EnhancementRouterIT extends CamelSpringTestSupport { private File tempDir; - private NonBinaryEnhancementProcessor nbh; @Override protected AbstractApplicationContext createApplicationContext() { @@ -119,25 +113,14 @@ public void init() throws Exception { storageLocationTestHelper = applicationContext.getBean(StorageLocationTestHelper.class); fcrepoClient = applicationContext.getBean(FcrepoClient.class); cdrEnhancements = applicationContext.getBean(CamelContext.class); - addSmallThumbnailProcessor = applicationContext.getBean("addSmallThumbnailProcessor", AddDerivativeProcessor.class); - addLargeThumbnailProcessor = applicationContext.getBean("addLargeThumbnailProcessor", AddDerivativeProcessor.class); addAccessCopyProcessor = applicationContext.getBean("addAccessCopyProcessor", AddDerivativeProcessor.class); solrIngestProcessor = applicationContext.getBean("solrIngestProcessor", SolrIngestProcessor.class); fulltextProcessor = applicationContext.getBean("fulltextProcessor", FulltextProcessor.class); updateDescriptionService = applicationContext.getBean(UpdateDescriptionService.class); - nbh = applicationContext.getBean(NonBinaryEnhancementProcessor.class); - when(addSmallThumbnailProcessor.needsRun(any(Exchange.class))).thenReturn(true); - when(addLargeThumbnailProcessor.needsRun(any(Exchange.class))).thenReturn(true); when(addAccessCopyProcessor.needsRun(any(Exchange.class))).thenReturn(true); - TestHelper.setContentBase(baseAddress); tempDir = Files.createDirectory(tmpFolder.resolve("target")).toFile(); - nbh.setSourceImagesDir(tempDir.getAbsolutePath()); - - File thumbScriptFile = new File("target/convertScaleStage.sh"); - FileUtils.writeStringToFile(thumbScriptFile, "exit 0", "utf-8"); - thumbScriptFile.deleteOnExit(); File jp2ScriptFile = new File("target/convertJp2.sh"); FileUtils.writeStringToFile(jp2ScriptFile, "exit 0", "utf-8"); @@ -166,9 +149,6 @@ public void nonBinaryWithSourceImages() throws Exception { Cdr.Collection.getURI(), Container.getURI()); template.sendBodyAndHeaders("", headers); - verify(addSmallThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addAccessCopyProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); } @@ -180,8 +160,6 @@ public void nonBinaryNoSourceImages() throws Exception { template.sendBodyAndHeaders("", headers); verify(solrIngestProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); } @Test @@ -194,7 +172,7 @@ public void testBinaryImageFile() throws Exception { // Separate exchanges when multicasting NotifyBuilder notify1 = new NotifyBuilder(cdrEnhancements) - .whenCompleted(12) + .whenCompleted(7) .create(); final Map headers = createEvent(binObj.getPid(), Binary.getURI()); @@ -203,8 +181,6 @@ public void testBinaryImageFile() throws Exception { boolean result1 = notify1.matches(5L, TimeUnit.SECONDS); assertTrue(result1, "Enhancement route not satisfied"); - verify(addSmallThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); verify(addAccessCopyProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); // Indexing triggered for binary parent verify(solrIngestProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); @@ -232,8 +208,6 @@ public void testBinaryMetadataFile() throws Exception { assertTrue(result, "Processing message did not match expectations"); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(addAccessCopyProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, never()).process(any(Exchange.class)); } @@ -258,7 +232,6 @@ public void testInvalidFile() throws Exception { assertTrue(result, "Processing message did not match expectations"); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); verify(fulltextProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, never()).process(any(Exchange.class)); } @@ -306,8 +279,6 @@ public void testDepositManifestFileMetadata() throws Exception { assertTrue(result, "Processing message did not match expectations"); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(addAccessCopyProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, never()).process(any(Exchange.class)); } diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java index c51899118f..3d45798f4a 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java @@ -52,10 +52,7 @@ public class ImageEnhancementsRouterTest extends CamelSpringTestSupport { private static final String userAgent = "curl/7.37.1"; private static final String fileID = "343b3da4-8876-42f5-8821-7aabb65e0f19"; private final String eventTypes = EVENT_NS + "ResourceCreation"; - private final String thumbnailRoute = "ProcessThumbnails"; private final String accessCopyRoute = "AccessCopy"; - private final String smallThumbRoute = "SmallThumbnail"; - private final String largeThumbRoute = "LargeThumbnail"; @PropertyInject(value = "fcrepo.baseUrl") private static String baseUri; @@ -66,12 +63,6 @@ public class ImageEnhancementsRouterTest extends CamelSpringTestSupport { @Produce("direct:process.binary.original") protected ProducerTemplate template; - @BeanInject(value = "addSmallThumbnailProcessor") - private AddDerivativeProcessor addSmallThumbnailProcessor; - - @BeanInject(value = "addLargeThumbnailProcessor") - private AddDerivativeProcessor addLargeThumbnailProcessor; - @BeanInject(value = "addAccessCopyProcessor") private AddDerivativeProcessor addAccessCopyProcessor; @@ -88,260 +79,6 @@ public void cleanup() throws IOException { FileUtils.deleteDirectory(new File("target/34")); } - @Test - public void testThumbnailMulticast() throws Exception { - createContext(thumbnailRoute); - - var smallEndpoint = getMockEndpoint("mock:direct:small.thumbnail"); - smallEndpoint.expectedMessageCount(1); - var largeEndpoint = getMockEndpoint("mock:direct:large.thumbnail"); - largeEndpoint.expectedMessageCount(1); - template.sendBodyAndHeaders("", createEvent(fileID, eventTypes, "false")); - - smallEndpoint.assertIsSatisfied(); - largeEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbMulticastFilter() throws Exception { - createContext(thumbnailRoute); - - var smallEndpoint = getMockEndpoint("mock:direct:small.thumbnail"); - smallEndpoint.expectedMessageCount(0); - var largeEndpoint = getMockEndpoint("mock:direct:large.thumbnail"); - largeEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - headers.put(CdrBinaryMimeType, "plain/text"); - - template.sendBodyAndHeaders("", headers); - - smallEndpoint.assertIsSatisfied(); - largeEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbDisallowedImageType() throws Exception { - createContext(thumbnailRoute); - - var smallEndpoint = getMockEndpoint("mock:direct:small.thumbnail"); - smallEndpoint.expectedMessageCount(0); - var largeEndpoint = getMockEndpoint("mock:direct:large.thumbnail"); - largeEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - headers.put(CdrBinaryMimeType, "image/vnd.fpx"); - - template.sendBodyAndHeaders("", headers); - - smallEndpoint.assertIsSatisfied(); - largeEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteNoForceNoFileExists() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "false"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteScriptFails() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - shEndpoint.whenAnyExchangeReceived(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - throw new IllegalStateException("Failing run of exec"); - } - }); - - Map headers = createEvent(fileID, eventTypes, "false"); - try { - template.sendBodyAndHeaders("", headers); - fail("Exception expected to be thrown"); - } catch (CamelExecutionException e) { - assertTrue(e.getCause() instanceof IllegalStateException); - } - - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteForceNoFileExists() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteNoForceFileExists() throws Exception { - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor, never()).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteForceFileExists() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor).process(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteNoForceNoFileExists() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "false"); - - template.sendBodyAndHeaders("", headers); - - doNothing().when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteScriptFails() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(largeThumbRoute); - - MockEndpoint shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - shEndpoint.whenAnyExchangeReceived(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - throw new IllegalStateException("Failing run of exec"); - } - }); - - Map headers = createEvent(fileID, eventTypes, "false"); - try { - template.sendBodyAndHeaders("", headers); - fail("Exception expected to be thrown"); - } catch (CamelExecutionException e) { - assertTrue(e.getCause() instanceof IllegalStateException); - } - - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteForceNoFileExists() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - - template.sendBodyAndHeaders("", headers); - - doNothing().when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteNoForceFileExists() throws Exception { - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - - template.sendBodyAndHeaders("", headers); - - doNothing().when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteForceFileExists() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - - template.sendBodyAndHeaders("", headers); - - doThrow(Exception.class).when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor).process(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - @Test public void testAccessCopyRouteNoForceNoFileExists() throws Exception { when(addAccessCopyProcessor.needsRun(any())).thenReturn(true); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailProcessorTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailProcessorTest.java new file mode 100644 index 0000000000..c04c27a2eb --- /dev/null +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailProcessorTest.java @@ -0,0 +1,64 @@ +package edu.unc.lib.boxc.services.camel.thumbnails; + +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; +import edu.unc.lib.boxc.auth.fcrepo.models.AccessGroupSetImpl; +import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequest; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequestSerializationHelper; +import edu.unc.lib.boxc.services.camel.TestHelper; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Mock; + +import java.io.IOException; +import java.nio.file.Path; + +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; +import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.openMocks; + +public class ImportThumbnailProcessorTest { + private ImportThumbnailRequestProcessor processor; + + @TempDir + private Path path; + private final AgentPrincipals agent = new AgentPrincipalsImpl("user", new AccessGroupSetImpl("agroup")); + private AutoCloseable closeable; + + @BeforeEach + public void init() throws IOException { + closeable = openMocks(this); + processor = new ImportThumbnailRequestProcessor(); + } + + @AfterEach + void closeService() throws Exception { + closeable.close(); + } + + @Test + public void testImportThumbnail() throws IOException { + var pid = TestHelper.makePid(); + var mimetype = "image/jpeg"; + var request = new ImportThumbnailRequest(); + request.setMimetype(mimetype); + request.setAgent(agent); + request.setStoragePath(path); + request.setPidString(pid.getId()); + + var exchange = TestHelper.mockExchange(ImportThumbnailRequestSerializationHelper.toJson(request)); + var message = exchange.getIn(); + + processor.process(exchange); + + verify(message).setHeader(FCREPO_URI, pid.getRepositoryPath()); + verify(message).setHeader(CdrBinaryMimeType, mimetype); + verify(message).setHeader(CdrBinaryPath, path.toString()); + } +} diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java index d798ee1d49..bb849fe838 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java @@ -3,9 +3,11 @@ import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; import edu.unc.lib.boxc.auth.fcrepo.models.AccessGroupSetImpl; import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; -import edu.unc.lib.boxc.services.camel.TestHelper; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequest; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequestSerializationHelper; import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequest; import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequestSerializationHelper; +import edu.unc.lib.boxc.services.camel.TestHelper; import org.apache.camel.BeanInject; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; @@ -27,10 +29,14 @@ public class ThumbnailRouterTest extends CamelSpringTestSupport { protected ProducerTemplate template; @BeanInject(value = "thumbnailRequestProcessor") private ThumbnailRequestProcessor processor; + + @BeanInject(value = "importThumbnailRequestProcessor") + private ImportThumbnailRequestProcessor importProcessor; @Override protected AbstractApplicationContext createApplicationContext() { return new ClassPathXmlApplicationContext("/service-context.xml", "/thumbnails-context.xml"); } + @Test public void requestSentTest() throws Exception { createContext("DcrThumbnails"); @@ -45,6 +51,27 @@ public void requestSentTest() throws Exception { verify(processor).process(any()); } + @Test + public void importRequestSentTest() throws Exception { + createContext("DcrImportThumbnails"); + var pid = TestHelper.makePid(); + + var request = new ImportThumbnailRequest(); + request.setAgent(agent); + request.setPidString(pid.toString()); + + var body = ImportThumbnailRequestSerializationHelper.toJson(request); + var solrEndpoint = getMockEndpoint("mock:direct:solrIndexing"); + solrEndpoint.expectedMessageCount(1); + var imageAccessCopyEndpoint = getMockEndpoint("mock:direct:process.enhancement.imageAccessCopy"); + imageAccessCopyEndpoint.expectedMessageCount(1); + template.sendBody(body); + + verify(importProcessor).process(any()); + solrEndpoint.assertIsSatisfied(); + imageAccessCopyEndpoint.assertIsSatisfied(); + } + private void createContext(String routeName) throws Exception { AdviceWith.adviceWith(context, routeName, a -> { a.replaceFromWith("direct:start"); diff --git a/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties b/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties index 7737d0e7a8..01383a5409 100644 --- a/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties +++ b/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties @@ -7,8 +7,6 @@ fcrepo.authUsername= fcrepo.authPassword= fcrepo.authHost= -cdr.enhancement.thumbnail.fileExtension=PNG -cdr.enhancement.thumbnail.mimetype=image/png cdr.enhancement.fulltext.fileName=full_text.txt cdr.enhancement.jp2.fileExtension=JP2 cdr.enhancement.jp2.mimetype=image/jp2 diff --git a/services-camel-app/src/test/resources/config.properties b/services-camel-app/src/test/resources/config.properties index ddb0602c3d..6ddf93df0c 100644 --- a/services-camel-app/src/test/resources/config.properties +++ b/services-camel-app/src/test/resources/config.properties @@ -7,8 +7,6 @@ fcrepo.authUsername= fcrepo.authPassword= fcrepo.authHost= -cdr.enhancement.thumbnail.fileExtension=PNG -cdr.enhancement.thumbnail.mimetype=image/png cdr.enhancement.jp2.fileExtension=JP2 cdr.enhancement.jp2.mimetype=image/jp2 cdr.enhancement.postIndexingDelay=500 diff --git a/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties b/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties index b28f70bb5b..8f3127b07a 100644 --- a/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties +++ b/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties @@ -3,8 +3,6 @@ error.retryDelay=0 error.maxRedeliveries=2 error.backOffMultiplier=1 -sourceImages.dir=target - cdr.stream=activemq:queue:repository.events cdr.stream.camel=activemq://activemq:queue:repository.events diff --git a/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml b/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml index 9aff556c78..017f26efd9 100644 --- a/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml +++ b/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml @@ -22,19 +22,6 @@ - - - - - - - - - - - - - diff --git a/services-camel-app/src/test/resources/enhancement-router-it-config.properties b/services-camel-app/src/test/resources/enhancement-router-it-config.properties index e9e082a55f..ac5fb6c6d6 100644 --- a/services-camel-app/src/test/resources/enhancement-router-it-config.properties +++ b/services-camel-app/src/test/resources/enhancement-router-it-config.properties @@ -5,8 +5,6 @@ fcrepo.authUsername= fcrepo.authPassword= fcrepo.authHost= -cdr.enhancement.thumbnail.fileExtension=PNG -cdr.enhancement.thumbnail.mimetype=image/png cdr.enhancement.fulltext.fileName=full_text.txt cdr.enhancement.jp2.fileExtension=JP2 cdr.enhancement.jp2.mimetype=image/jp2 diff --git a/services-camel-app/src/test/resources/enhancement-router-it-context.xml b/services-camel-app/src/test/resources/enhancement-router-it-context.xml index 209ba3f364..14e1c9cf9d 100644 --- a/services-camel-app/src/test/resources/enhancement-router-it-context.xml +++ b/services-camel-app/src/test/resources/enhancement-router-it-context.xml @@ -28,14 +28,6 @@ - - - - - - - - @@ -53,9 +45,6 @@ - - - diff --git a/services-camel-app/src/test/resources/images-context.xml b/services-camel-app/src/test/resources/images-context.xml index 8acfba3584..8d86ef9f60 100644 --- a/services-camel-app/src/test/resources/images-context.xml +++ b/services-camel-app/src/test/resources/images-context.xml @@ -13,14 +13,6 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - - - - - - diff --git a/services-camel-app/src/test/resources/metaservices-context.xml b/services-camel-app/src/test/resources/metaservices-context.xml index 5afcb06891..a7fb4b4e2a 100644 --- a/services-camel-app/src/test/resources/metaservices-context.xml +++ b/services-camel-app/src/test/resources/metaservices-context.xml @@ -28,10 +28,6 @@ - - - - diff --git a/services-camel-app/src/test/resources/thumbnails-config.properties b/services-camel-app/src/test/resources/thumbnails-config.properties index 6a2ea9b4c3..c95155de67 100644 --- a/services-camel-app/src/test/resources/thumbnails-config.properties +++ b/services-camel-app/src/test/resources/thumbnails-config.properties @@ -1,2 +1,5 @@ -cdr.thumbnails.stream=direct:start -cdr.thumbnails.stream.camel=direct:start \ No newline at end of file +cdr.thumbnails.stream=direct:startThumbnail +cdr.thumbnails.stream.camel=direct:startThumbnail + +cdr.import.thumbnails.stream=direct:startImport +cdr.import.thumbnails.stream.camel=direct:startImport \ No newline at end of file diff --git a/services-camel-app/src/test/resources/thumbnails-context.xml b/services-camel-app/src/test/resources/thumbnails-context.xml index a8d16b021d..f7390dbcdc 100644 --- a/services-camel-app/src/test/resources/thumbnails-context.xml +++ b/services-camel-app/src/test/resources/thumbnails-context.xml @@ -11,6 +11,10 @@ + + + + diff --git a/static/js/admin/src/action/RunEnhancementsBatchAction.js b/static/js/admin/src/action/RunEnhancementsBatchAction.js index 73fd29d075..9140bcdcc6 100644 --- a/static/js/admin/src/action/RunEnhancementsBatchAction.js +++ b/static/js/admin/src/action/RunEnhancementsBatchAction.js @@ -30,8 +30,12 @@ define('RunEnhancementsBatchAction', [ 'jquery', 'AbstractBatchAction', "tpl!../ } else { title = "Run enhancements on " + this.targets.length + " objects"; } - - var form = runEnhancementsTemplate(); + + var targetIds = ""; + for (var index in this.targets) { + targetIds += this.targets[index].getPid() + "\n"; + } + var form = runEnhancementsTemplate({ targetIds : targetIds }); this.dialog = $("
" + form + "
"); this.dialog.dialog({ autoOpen: true, @@ -44,12 +48,11 @@ define('RunEnhancementsBatchAction', [ 'jquery', 'AbstractBatchAction', "tpl!../ this.$form.submit(function(e){ var force = document.getElementById('run_enhancements_force').checked; + var recursive = document.getElementById('run_enhancements_recursive').checked; + var targetIdsString = document.getElementById('run_enhancements_ids').value; + + var pids = targetIdsString.split("\n").map((id) => id.trim()).filter((id) => id.length > 0); - var pids = []; - for (var index in self.targets) { - pids.push(self.targets[index].getPid()); - } - $.ajax({ url : "/services/api/runEnhancements", type : "POST", @@ -57,11 +60,12 @@ define('RunEnhancementsBatchAction', [ 'jquery', 'AbstractBatchAction', "tpl!../ dataType: "json", data : JSON.stringify({ force : force, - pids : pids + pids : pids, + recursive : recursive }) }).done(function(response) { self.context.view.$alertHandler.alertHandler("message", response.message); - self.dialog.remove(); + self.dialog.dialog("destroy"); }).fail(function() { self.context.view.$alertHandler.alertHandler("error", "Failed to run enhancements for " + self.targets.length + " objects"); }); diff --git a/static/js/admin/vue-permissions-editor/package-lock.json b/static/js/admin/vue-permissions-editor/package-lock.json index 3649262eb3..8369c9a78e 100644 --- a/static/js/admin/vue-permissions-editor/package-lock.json +++ b/static/js/admin/vue-permissions-editor/package-lock.json @@ -7578,9 +7578,9 @@ } }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, "bin": { "rollup": "dist/bin/rollup" diff --git a/static/js/vue-cdr-access/package-lock.json b/static/js/vue-cdr-access/package-lock.json index d0c1743274..4d52b6321c 100644 --- a/static/js/vue-cdr-access/package-lock.json +++ b/static/js/vue-cdr-access/package-lock.json @@ -8951,9 +8951,9 @@ } }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, "bin": { "rollup": "dist/bin/rollup" diff --git a/static/js/vue-cdr-access/tests/fixtures/displayWrapperFixtures.js b/static/js/vue-cdr-access/tests/fixtures/displayWrapperFixtures.js index e2d77a522f..8b2290c971 100644 --- a/static/js/vue-cdr-access/tests/fixtures/displayWrapperFixtures.js +++ b/static/js/vue-cdr-access/tests/fixtures/displayWrapperFixtures.js @@ -71,8 +71,7 @@ export const briefObjectData = { } ], datastream: [ - "thumbnail_small|image/png|fc77a9be-b49d-4f4e-b656-1644c9e964fc.png|png|6768|||", - "thumbnail_large|image/png|fc77a9be-b49d-4f4e-b656-1644c9e964fc.png|png|23535|||", + "jp2|image/jp2|fc77a9be-b49d-4f4e-b656-1644c9e964fc.jp2|jp2|2189901|||", "event_log|application/n-triples|event_log.nt|nt|8206|urn:sha1:54fe67d57b965651e813eea1777c7f0332253168||", "md_descriptive_history|text/xml|||916|urn:sha1:efb4f2b6226d2932229f0e2b89128ec9a651de71||", "md_descriptive|text/xml|md_descriptive.xml|xml|283|urn:sha1:97f7dbdb806f724f9301445820ff1e0c9691cd6b||" diff --git a/static/js/vue-cdr-access/tests/fixtures/recordListFixture.js b/static/js/vue-cdr-access/tests/fixtures/recordListFixture.js index 81701c7b69..1b9f47c5eb 100644 --- a/static/js/vue-cdr-access/tests/fixtures/recordListFixture.js +++ b/static/js/vue-cdr-access/tests/fixtures/recordListFixture.js @@ -76,8 +76,7 @@ export const records_list = [ "datastream": [ "techmd_fits|text\/xml|aaa66f91-4870-4937-b7ba-06b015959e4f.xml|xml|5480|urn:sha1:82c71472051b8279a0fbaa537a340c57e3d842f6|aaa66f91-4870-4937-b7ba-06b015959e4f", "original_file|image\/png|Screen+Shot+2018-10-17+at+3.02.53+PM.png|png|232738|urn:md5:f5397b230bb5dfa4d53f57ad35514405|aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_small|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|2454||aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_large|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|5892||aaa66f91-4870-4937-b7ba-06b015959e4f" + "jp2|image/jp2|aaa66f91-4870-4937-b7ba-06b015959e4f.jp2|jp2|2189901|||aaa66f91-4870-4937-b7ba-06b015959e4f" ], "fileDesc": [ "Portable Network Graphics" diff --git a/static/js/vue-cdr-access/tests/unit/aggregateRecord.spec.js b/static/js/vue-cdr-access/tests/unit/aggregateRecord.spec.js index e2bbc6ea97..0bd10798d5 100644 --- a/static/js/vue-cdr-access/tests/unit/aggregateRecord.spec.js +++ b/static/js/vue-cdr-access/tests/unit/aggregateRecord.spec.js @@ -159,8 +159,6 @@ const record = { "original_file|image/jpeg|bee1.jpg|jpg|69481|urn:sha1:87d7bed6cb33c87c589cfcdc2a2ce6110712fabb|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d|607x1024", "techmd_fits|text/xml|techmd_fits.xml|xml|7013|urn:sha1:0c4a500c73146214d5fa08f278c0cdaadede79d0|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d|", "jp2|image/jp2|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d.jp2|jp2|415163||4053adf7-7bdc-4c9c-8769-8cc5da4ce81d|", - "thumbnail_small|image/png|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d.png|png|4802||4053adf7-7bdc-4c9c-8769-8cc5da4ce81d|", - "thumbnail_large|image/png|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d.png|png|16336||4053adf7-7bdc-4c9c-8769-8cc5da4ce81d|", "event_log|application/n-triples|event_log.nt|nt|4504|urn:sha1:b15940ee90b0f6d2b3ab1639eb7a266e54b621f2||", "md_descriptive|text/xml|md_descriptive.xml|xml|459|urn:sha1:17e8dec55960ac14f100541993793dc8da231788||", "md_descriptive_history|text/xml|||4976|urn:sha1:35e4b19ea3c58148c607b6537cc9af510406700c||" diff --git a/static/js/vue-cdr-access/tests/unit/collectionRecord.spec.js b/static/js/vue-cdr-access/tests/unit/collectionRecord.spec.js index 9bb1f46b17..db33a95382 100644 --- a/static/js/vue-cdr-access/tests/unit/collectionRecord.spec.js +++ b/static/js/vue-cdr-access/tests/unit/collectionRecord.spec.js @@ -39,8 +39,7 @@ const recordData = { } ], datastream: [ - "thumbnail_small|image/png|fc77a9be-b49d-4f4e-b656-1644c9e964fc.png|png|6768|||", - "thumbnail_large|image/png|fc77a9be-b49d-4f4e-b656-1644c9e964fc.png|png|23535|||", + "jp2|image/jp2|fc77a9be-b49d-4f4e-b656-1644c9e964fc.jp2|jp2|2189901|||", "event_log|application/n-triples|event_log.nt|nt|8206|urn:sha1:54fe67d57b965651e813eea1777c7f0332253168||", "md_descriptive_history|text/xml|||916|urn:sha1:efb4f2b6226d2932229f0e2b89128ec9a651de71||", "md_descriptive|text/xml|md_descriptive.xml|xml|283|urn:sha1:97f7dbdb806f724f9301445820ff1e0c9691cd6b||" diff --git a/static/js/vue-cdr-access/tests/unit/fileRecord.spec.js b/static/js/vue-cdr-access/tests/unit/fileRecord.spec.js index 989b414bdc..26f6528b33 100644 --- a/static/js/vue-cdr-access/tests/unit/fileRecord.spec.js +++ b/static/js/vue-cdr-access/tests/unit/fileRecord.spec.js @@ -56,8 +56,6 @@ const record = { "techmd_fits|text/xml|techmd_fits.xml|xml|4709|urn:sha1:5b0eabd749222a7c0bcdb92002be9fe3eff60128||", "original_file|image/jpeg|beez||694904|urn:sha1:0d48dadb5d61ae0d41b4998280a3c39577a2f94a||2048x1536", "jp2|image/jp2|4db695c0-5fd5-4abf-9248-2e115d43f57d.jp2|jp2|2189901|||", - "thumbnail_small|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|6768|||", - "thumbnail_large|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|23535|||", "event_log|application/n-triples|event_log.nt|nt|4334|urn:sha1:aabf004766f954db4ac4ab9aa0a115bb10b708b4||" ], parentCollectionId: "fc77a9be-b49d-4f4e-b656-1644c9e964fc", @@ -166,8 +164,6 @@ const record = { "original_file|image/jpeg|bee1.jpg|jpg|69481|urn:sha1:87d7bed6cb33c87c589cfcdc2a2ce6110712fabb||607x1024", "techmd_fits|text/xml|techmd_fits.xml|xml|7013|urn:sha1:0c4a500c73146214d5fa08f278c0cdaadede79d0||", "jp2|image/jp2|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d.jp2|jp2|415163|||", - "thumbnail_small|image/png|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d.png|png|4802|||", - "thumbnail_large|image/png|4053adf7-7bdc-4c9c-8769-8cc5da4ce81d.png|png|16336|||", "event_log|application/n-triples|event_log.nt|nt|5852|urn:sha1:8d80f0de467fa650d4bc8568d4a958e5ced85f96||" ], parentCollectionId: "fc77a9be-b49d-4f4e-b656-1644c9e964fc", @@ -273,8 +269,6 @@ const record = { "techmd_fits|text/xml|techmd_fits.xml|xml|4709|urn:sha1:5b0eabd749222a7c0bcdb92002be9fe3eff60128||", "original_file|image/jpeg|beez||694904|urn:sha1:0d48dadb5d61ae0d41b4998280a3c39577a2f94a||2048x1536", "jp2|image/jp2|4db695c0-5fd5-4abf-9248-2e115d43f57d.jp2|jp2|2189901|||", - "thumbnail_small|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|6768|||", - "thumbnail_large|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|23535|||", "event_log|application/n-triples|event_log.nt|nt|4334|urn:sha1:aabf004766f954db4ac4ab9aa0a115bb10b708b4||" ], parentCollectionId: "fc77a9be-b49d-4f4e-b656-1644c9e964fc", diff --git a/static/js/vue-cdr-access/tests/unit/fileUtils.spec.js b/static/js/vue-cdr-access/tests/unit/fileUtils.spec.js index 899cc2858b..58f1664ad9 100644 --- a/static/js/vue-cdr-access/tests/unit/fileUtils.spec.js +++ b/static/js/vue-cdr-access/tests/unit/fileUtils.spec.js @@ -69,10 +69,9 @@ describe('fileUtils', () => { "title": "Imagy File", "type": "File", "datastream": [ + "jp2|image/jp2|aaa66f91-4870-4937-b7ba-06b015959e4f.jp2|jp2|2189901|||", "techmd_fits|text\/xml|aaa66f91-4870-4937-b7ba-06b015959e4f.xml|xml|5480|urn:sha1:82c71472051b8279a0fbaa537a340c57e3d842f6|aaa66f91-4870-4937-b7ba-06b015959e4f", "original_file|image\/png|Screen+Shot+2018-10-17+at+3.02.53+PM.png|png|232738|urn:md5:f5397b230bb5dfa4d53f57ad35514405|aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_small|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|2454||aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_large|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|5892||aaa66f91-4870-4937-b7ba-06b015959e4f" ], "fileDesc": ["Portable Network Graphics", "Joint Photographic Experts Group"], "fileType": [ @@ -93,8 +92,7 @@ describe('fileUtils', () => { "datastream": [ "techmd_fits|text\/xml|aaa66f91-4870-4937-b7ba-06b015959e4f.xml|xml|5480|urn:sha1:82c71472051b8279a0fbaa537a340c57e3d842f6|aaa66f91-4870-4937-b7ba-06b015959e4f", "original_file|image\/png|Screen+Shot+2018-10-17+at+3.02.53+PM.png|png|232738|urn:md5:f5397b230bb5dfa4d53f57ad35514405|aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_small|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|2454||aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_large|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|5892||aaa66f91-4870-4937-b7ba-06b015959e4f" + "jp2|image/jp2|aaa66f91-4870-4937-b7ba-06b015959e4f.jp2|jp2|2189901|||aaa66f91-4870-4937-b7ba-06b015959e4f" ], "fileDesc": ["Portable Network Graphics", "Portable Network Graphics"], "fileType": [ @@ -115,8 +113,7 @@ describe('fileUtils', () => { "datastream": [ "techmd_fits|text\/xml|aaa66f91-4870-4937-b7ba-06b015959e4f.xml|xml|5480|urn:sha1:82c71472051b8279a0fbaa537a340c57e3d842f6|aaa66f91-4870-4937-b7ba-06b015959e4f", "original_file|image\/png|Screen+Shot+2018-10-17+at+3.02.53+PM.png|png|232738|urn:md5:f5397b230bb5dfa4d53f57ad35514405|aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_small|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|2454||aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_large|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|5892||aaa66f91-4870-4937-b7ba-06b015959e4f" + "jp2|image/jp2|aaa66f91-4870-4937-b7ba-06b015959e4f.jp2|jp2|2189901|||aaa66f91-4870-4937-b7ba-06b015959e4f" ], "fileDesc": [], "fileType": [ @@ -137,8 +134,7 @@ describe('fileUtils', () => { "datastream": [ "techmd_fits|text\/xml|aaa66f91-4870-4937-b7ba-06b015959e4f.xml|xml|5480|urn:sha1:82c71472051b8279a0fbaa537a340c57e3d842f6|aaa66f91-4870-4937-b7ba-06b015959e4f", "original_file|image\/png|Screen+Shot+2018-10-17+at+3.02.53+PM.png|png|232738|urn:md5:f5397b230bb5dfa4d53f57ad35514405|aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_small|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|2454||aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_large|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|5892||aaa66f91-4870-4937-b7ba-06b015959e4f" + "jp2|image/jp2|aaa66f91-4870-4937-b7ba-06b015959e4f.jp2|jp2|2189901|||aaa66f91-4870-4937-b7ba-06b015959e4f" ], "fileDesc": [], "fileType": [ @@ -159,8 +155,7 @@ describe('fileUtils', () => { "datastream": [ "techmd_fits|text\/xml|aaa66f91-4870-4937-b7ba-06b015959e4f.xml|xml|5480|urn:sha1:82c71472051b8279a0fbaa537a340c57e3d842f6|aaa66f91-4870-4937-b7ba-06b015959e4f", "original_file|image\/png|Screen+Shot+2018-10-17+at+3.02.53+PM.png|png|232738|urn:md5:f5397b230bb5dfa4d53f57ad35514405|aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_small|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|2454||aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_large|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|5892||aaa66f91-4870-4937-b7ba-06b015959e4f" + "jp2|image/jp2|aaa66f91-4870-4937-b7ba-06b015959e4f.jp2|jp2|2189901|||aaa66f91-4870-4937-b7ba-06b015959e4f" ], "fileDesc": [], "fileType": [ @@ -181,8 +176,7 @@ describe('fileUtils', () => { "datastream": [ "techmd_fits|text\/xml|aaa66f91-4870-4937-b7ba-06b015959e4f.xml|xml|5480|urn:sha1:82c71472051b8279a0fbaa537a340c57e3d842f6|aaa66f91-4870-4937-b7ba-06b015959e4f", "original_file|image\/png|Screen+Shot+2018-10-17+at+3.02.53+PM.png|png|232738|urn:md5:f5397b230bb5dfa4d53f57ad35514405|aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_small|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|2454||aaa66f91-4870-4937-b7ba-06b015959e4f", - "thumbnail_large|image\/png|aaa66f91-4870-4937-b7ba-06b015959e4f.png|png|5892||aaa66f91-4870-4937-b7ba-06b015959e4f" + "jp2|image/jp2|aaa66f91-4870-4937-b7ba-06b015959e4f.jp2|jp2|2189901|||aaa66f91-4870-4937-b7ba-06b015959e4f" ], "fileType": [ "image/png" diff --git a/static/js/vue-cdr-access/tests/unit/player.spec.js b/static/js/vue-cdr-access/tests/unit/player.spec.js index 33c1672ed4..05535d379b 100644 --- a/static/js/vue-cdr-access/tests/unit/player.spec.js +++ b/static/js/vue-cdr-access/tests/unit/player.spec.js @@ -55,8 +55,6 @@ const record = { "techmd_fits|text/xml|techmd_fits.xml|xml|4709|urn:sha1:5b0eabd749222a7c0bcdb92002be9fe3eff60128||", "original_file|image/jpeg|beez||694904|urn:sha1:0d48dadb5d61ae0d41b4998280a3c39577a2f94a||2048x1536", "jp2|image/jp2|4db695c0-5fd5-4abf-9248-2e115d43f57d.jp2|jp2|2189901|||", - "thumbnail_small|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|6768|||", - "thumbnail_large|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|23535|||", "event_log|application/n-triples|event_log.nt|nt|4334|urn:sha1:aabf004766f954db4ac4ab9aa0a115bb10b708b4||" ], parentCollectionId: "fc77a9be-b49d-4f4e-b656-1644c9e964fc", diff --git a/static/js/vue-cdr-access/tests/unit/restrictedContent.spec.js b/static/js/vue-cdr-access/tests/unit/restrictedContent.spec.js index 884f967810..fe4da529dd 100644 --- a/static/js/vue-cdr-access/tests/unit/restrictedContent.spec.js +++ b/static/js/vue-cdr-access/tests/unit/restrictedContent.spec.js @@ -58,8 +58,6 @@ const record = { "techmd_fits|text/xml|techmd_fits.xml|xml|4709|urn:sha1:5b0eabd749222a7c0bcdb92002be9fe3eff60128||", "original_file|image/jpeg|beez||694904|urn:sha1:0d48dadb5d61ae0d41b4998280a3c39577a2f94a||2848x1536", "jp2|image/jp2|4db695c0-5fd5-4abf-9248-2e115d43f57d.jp2|jp2|2189901|||", - "thumbnail_small|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|6768|||", - "thumbnail_large|image/png|4db695c0-5fd5-4abf-9248-2e115d43f57d.png|png|23535|||", "event_log|application/n-triples|event_log.nt|nt|4334|urn:sha1:aabf004766f954db4ac4ab9aa0a115bb10b708b4||" ], parentCollectionId: "fc77a9be-b49d-4f4e-b656-1644c9e964fc", diff --git a/static/js/vue-cdr-access/tests/unit/searchWrapper.spec.js b/static/js/vue-cdr-access/tests/unit/searchWrapper.spec.js index 113da177aa..8fb7532253 100644 --- a/static/js/vue-cdr-access/tests/unit/searchWrapper.spec.js +++ b/static/js/vue-cdr-access/tests/unit/searchWrapper.spec.js @@ -39,8 +39,6 @@ const response = { "techmd_fits|text/xml|0367e115-fc95-4f61-8539-e9a77cf00d8a.xml|xml|5480|urn:sha1:4b74895e0f119890a1c0ae1e329683e4cb8264af|0367e115-fc95-4f61-8539-e9a77cf00d8a", "original_file|image/png|agent.png|png|174979|urn:md5:68e519e0c42adada7cb543a7c0193101|0367e115-fc95-4f61-8539-e9a77cf00d8a", "jp2|image/jp2|0367e115-fc95-4f61-8539-e9a77cf00d8a.jp2|jp2|427985||0367e115-fc95-4f61-8539-e9a77cf00d8a", - "thumbnail_small|image/png|0367e115-fc95-4f61-8539-e9a77cf00d8a.png|png|1445||0367e115-fc95-4f61-8539-e9a77cf00d8a", - "thumbnail_large|image/png|0367e115-fc95-4f61-8539-e9a77cf00d8a.png|png|3602||0367e115-fc95-4f61-8539-e9a77cf00d8a" ], "_version_": 1649012742492782600, "id": "64e6883d-3667-4e5b-893d-c6e851ac738a", diff --git a/static/js/vue-cdr-access/tests/unit/thumbnail.spec.js b/static/js/vue-cdr-access/tests/unit/thumbnail.spec.js index e63dcdf674..7e08c625c8 100644 --- a/static/js/vue-cdr-access/tests/unit/thumbnail.spec.js +++ b/static/js/vue-cdr-access/tests/unit/thumbnail.spec.js @@ -38,8 +38,7 @@ const recordData = { } ], datastream: [ - "thumbnail_small|image/png|fc77a9be-b49d-4f4e-b656-1644c9e964fc.png|png|6768|||", - "thumbnail_large|image/png|fc77a9be-b49d-4f4e-b656-1644c9e964fc.png|png|23535|||", + "jp2|image/jp2|fc77a9be-b49d-4f4e-b656-1644c9e964fc.jp2|jp2|2189901|||", "event_log|application/n-triples|event_log.nt|nt|8206|urn:sha1:54fe67d57b965651e813eea1777c7f0332253168||", "md_descriptive_history|text/xml|||916|urn:sha1:efb4f2b6226d2932229f0e2b89128ec9a651de71||", "md_descriptive|text/xml|md_descriptive.xml|xml|283|urn:sha1:97f7dbdb806f724f9301445820ff1e0c9691cd6b||" diff --git a/static/templates/admin/runEnhancementsForm.html b/static/templates/admin/runEnhancementsForm.html index d01bd07c21..e86e94cf34 100644 --- a/static/templates/admin/runEnhancementsForm.html +++ b/static/templates/admin/runEnhancementsForm.html @@ -1,11 +1,16 @@

- Enhancements will be performed on the selected objects and their children. + Enhancements will be run on the objects with the following IDs (edit the list as needed):

- - +

+ +

+

- +

+

+ +

diff --git a/web-common/src/main/java/edu/unc/lib/boxc/web/common/services/DerivativeContentService.java b/web-common/src/main/java/edu/unc/lib/boxc/web/common/services/DerivativeContentService.java index f1c6651e28..010a865bf4 100644 --- a/web-common/src/main/java/edu/unc/lib/boxc/web/common/services/DerivativeContentService.java +++ b/web-common/src/main/java/edu/unc/lib/boxc/web/common/services/DerivativeContentService.java @@ -86,29 +86,6 @@ public void streamData(PID pid, String dsName, AccessGroupSet principals, boolea IOUtils.copy(new FileInputStream(derivFile), outStream, BUFFER_SIZE); } - /** - * Returns a response entity consisting of the derivative stream used for thumbnails - * @param pid PID of the repository object - * @param dsName datastream name - * @return - * @throws FileNotFoundException - */ - public ResponseEntity streamThumbnail(PID pid, String dsName) throws FileNotFoundException { - var datastreamType = getType(dsName); - Derivative derivative = getDerivative(pid, dsName, datastreamType); - - var file = derivative.getFile(); - var filename = file.getName(); - var input = new FileInputStream(file); - InputStreamResource resource = new InputStreamResource(input); - return ResponseEntity.ok() - .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=" + filename) - .contentLength(file.length()) - .contentType(MediaType.IMAGE_PNG) - .body(resource); - - } - private DatastreamType getType(String dsName) { DatastreamType derivType = getByIdentifier(dsName); if (derivType == null || !listDerivativeTypes().contains(derivType)) { diff --git a/web-common/src/main/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtil.java b/web-common/src/main/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtil.java index 6ffd8b89b8..5ba6695bf8 100644 --- a/web-common/src/main/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtil.java +++ b/web-common/src/main/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtil.java @@ -131,7 +131,7 @@ public static Datastream getPreferredDatastream(ContentObjectRecord metadata, St */ public static String getThumbnailOwnerId(ContentObjectRecord metadata) { // Prefer the matching derivative from this object - Datastream preferredDS = getPreferredDatastream(metadata, DatastreamType.THUMBNAIL_LARGE.getId()); + Datastream preferredDS = getPreferredDatastream(metadata, DatastreamType.JP2_ACCESS_COPY.getId()); // Ensure that this item has the appropriate thumbnail if (preferredDS == null) { diff --git a/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/AccessCopiesServiceTest.java b/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/AccessCopiesServiceTest.java index 2203762a56..8735914cef 100644 --- a/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/AccessCopiesServiceTest.java +++ b/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/AccessCopiesServiceTest.java @@ -30,6 +30,7 @@ import java.util.UUID; import static edu.unc.lib.boxc.auth.api.Permission.viewOriginal; +import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; import static edu.unc.lib.boxc.model.api.DatastreamType.TECHNICAL_METADATA; import static edu.unc.lib.boxc.web.common.services.AccessCopiesService.AUDIO_MIMETYPE_REGEX; @@ -154,11 +155,11 @@ private ContentObjectSolrRecord createPdfObject(ResourceType resourceType) { private ContentObjectSolrRecord createImgObject(ResourceType resourceType) { var mdObjectImg = new ContentObjectSolrRecord(); mdObjectImg.setResourceType(resourceType.name()); - mdObjectImg.setId(UUID.randomUUID().toString()); - List imgDatastreams = Arrays.asList( + var id = UUID.randomUUID().toString(); + mdObjectImg.setId(id); + List imgDatastreams = List.of( ORIGINAL_FILE.getId() + "|image/png|file.png|png|766|urn:sha1:checksum|", - DatastreamType.THUMBNAIL_LARGE.getId() + "|image/png|thumb|png|55||", - DatastreamType.JP2_ACCESS_COPY.getId() + "|image/jp2|thumb|jp2|555||"); + JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||" + id + "|1200x1200"); mdObjectImg.setFileFormatCategory(Collections.singletonList(ContentCategory.image.getDisplayName())); mdObjectImg.setFileFormatType(Collections.singletonList("image/png")); mdObjectImg.setDatastream(imgDatastreams); @@ -292,9 +293,8 @@ public void getThumbnailIdNoPrimaryMultipleImages() { var mdObjectImg2 = new ContentObjectSolrRecord(); mdObjectImg2.setResourceType(ResourceType.File.name()); mdObjectImg2.setId(UUID.randomUUID().toString()); - var imgDatastreams = Arrays.asList( - ORIGINAL_FILE.getId() + "|image/jpg|file2.png|png|555|urn:sha1:checksum|", - DatastreamType.THUMBNAIL_LARGE.getId() + "|image/png|thumb|png|55||"); + var imgDatastreams = List.of( + ORIGINAL_FILE.getId() + "|image/jpg|file2.png|png|555|urn:sha1:checksum|"); mdObjectImg2.setFileFormatCategory(Collections.singletonList(ContentCategory.image.getDisplayName())); mdObjectImg2.setFileFormatType(Collections.singletonList("png")); mdObjectImg2.setDatastream(imgDatastreams); diff --git a/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/DerivativeContentServiceTest.java b/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/DerivativeContentServiceTest.java index e739758dee..7ca07f2dde 100644 --- a/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/DerivativeContentServiceTest.java +++ b/web-common/src/test/java/edu/unc/lib/boxc/web/common/services/DerivativeContentServiceTest.java @@ -44,18 +44,4 @@ public void init() { void closeService() throws Exception { closeable.close(); } - - @Test - public void testStreamThumbnail() throws FileNotFoundException { - var pid = makePid(); - var datastreamType = DatastreamType.THUMBNAIL_SMALL; - var file = new File("src/test/resources/tokki.jpg"); - var derivative = new DerivativeService.Derivative(datastreamType, file); - when(derivativeService.getDerivative(eq(pid), eq(datastreamType))).thenReturn(derivative); - - var respEntity = derivativeContentService.streamThumbnail(pid, "thumbnail_small"); - assertEquals(HttpStatus.OK, respEntity.getStatusCode()); - assertEquals("inline; filename=\"tokki.jpg\"", respEntity.getHeaders().getContentDisposition().toString()); - assertEquals(MediaType.IMAGE_PNG, respEntity.getHeaders().getContentType()); - } } diff --git a/web-common/src/test/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtilTest.java b/web-common/src/test/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtilTest.java index 7ef1d075fc..7d3f0bdc0e 100644 --- a/web-common/src/test/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtilTest.java +++ b/web-common/src/test/java/edu/unc/lib/boxc/web/common/utils/DatastreamUtilTest.java @@ -1,24 +1,20 @@ package edu.unc.lib.boxc.web.common.utils; +import edu.unc.lib.boxc.model.api.ids.PID; +import edu.unc.lib.boxc.search.solr.models.ContentObjectSolrRecord; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; import static edu.unc.lib.boxc.model.api.DatastreamType.TECHNICAL_METADATA; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_LARGE; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_SMALL; import static edu.unc.lib.boxc.model.fcrepo.test.TestHelper.makePid; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import edu.unc.lib.boxc.model.api.ids.PID; -import edu.unc.lib.boxc.search.solr.models.ContentObjectSolrRecord; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - /** * * @author bbpennel @@ -31,9 +27,6 @@ public class DatastreamUtilTest { private final static String ORIGINAL_DS = ORIGINAL_FILE.getId() + "|image/jpg|image|jpg|555||"; private final static String ORIGINAL_INDEXABLE = ORIGINAL_FILE.getId() + "|application/pdf|doc.pdf|pdf|5555||"; private final static String FITS_DS = TECHNICAL_METADATA.getId() + "|text/xml|fits.xml|xml|5555||"; - private final static String THUMB_SMALL_DS = THUMBNAIL_SMALL.getId() + "|image/png|small|png|3333||"; - private final static String THUMB_LARGE_DS = THUMBNAIL_LARGE.getId() + "|image/png|small|png|10000||"; - private final static List EMPTY_LIST = Collections.emptyList(); @BeforeEach public void setup() { @@ -76,28 +69,31 @@ public void testGetDatastreamUrl() { @Test public void testConstructThumbnailSmall() { PID pid = makePid(); + var id = pid.getId(); ContentObjectSolrRecord mdObj = new ContentObjectSolrRecord(); - mdObj.setId(pid.getId()); - mdObj.setDatastream(asList(ORIGINAL_DS, THUMB_SMALL_DS, THUMB_LARGE_DS)); - - var id = DatastreamUtil.getThumbnailOwnerId(mdObj); - assertEquals(pid.getId(), id); - var url = DatastreamUtil.constructThumbnailUrl(id, "small"); - assertEquals(ENDPOINT_URL + "thumb/" + pid.getId() + "/small", url); + mdObj.setId(id); + var jp2Datastream = JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||" + id + "|1200x1200"; + mdObj.setDatastream(asList(ORIGINAL_DS, jp2Datastream)); + + var ownerId = DatastreamUtil.getThumbnailOwnerId(mdObj); + assertEquals(id, ownerId); + var url = DatastreamUtil.constructThumbnailUrl(ownerId, "small"); + assertEquals(ENDPOINT_URL + "thumb/" + ownerId + "/small", url); } @Test public void testConstructThumbnailUrlForPrimaryObject() { PID primaryObjPid = makePid(); + var primaryObjId = primaryObjPid.getId(); PID pid = makePid(); ContentObjectSolrRecord mdObj = new ContentObjectSolrRecord(); mdObj.setId(pid.getId()); - mdObj.setDatastream(asList(ORIGINAL_DS, - THUMB_SMALL_DS + primaryObjPid.getId(), THUMB_LARGE_DS + primaryObjPid.getId())); + var jp2Datastream = JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||" + primaryObjId + "|1200x1200"; + mdObj.setDatastream(asList(ORIGINAL_DS, jp2Datastream)); var id = DatastreamUtil.getThumbnailOwnerId(mdObj); - assertEquals(primaryObjPid.getId(), id); + assertEquals(primaryObjId, id); var url = DatastreamUtil.constructThumbnailUrl(id, "large"); assertEquals(ENDPOINT_URL + "thumb/" + primaryObjPid.getId() + "/large", url); } @@ -107,7 +103,7 @@ public void testGetThumbnailUrlNoThumbs() { PID pid = makePid(); ContentObjectSolrRecord mdObj = new ContentObjectSolrRecord(); mdObj.setId(pid.getId()); - mdObj.setDatastream(asList(ORIGINAL_DS)); + mdObj.setDatastream(List.of(ORIGINAL_DS)); var id = DatastreamUtil.getThumbnailOwnerId(mdObj); assertNull(id); diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java index 58a411e5fd..88dda0dacf 100644 --- a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java @@ -103,8 +103,12 @@ public String getDownloadFilename(ContentObjectRecord contentObjectRecord, Strin } private Datastream getDatastream(ContentObjectRecord contentObjectRecord) { - var id = DatastreamType.ORIGINAL_FILE.getId(); - return contentObjectRecord.getDatastreamObject(id); + var originalFileDatastream = contentObjectRecord.getDatastreamObject( + DatastreamType.ORIGINAL_FILE.getId()); + if (originalFileDatastream == null) { + return contentObjectRecord.getDatastreamObject(DatastreamType.JP2_ACCESS_COPY.getId()); + } + return originalFileDatastream; } /** diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImportThumbnailService.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImportThumbnailService.java index f4fc5c66e5..47b61c8bac 100644 --- a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImportThumbnailService.java +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImportThumbnailService.java @@ -1,11 +1,14 @@ package edu.unc.lib.boxc.web.services.processing; -import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_DEPTH; -import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_SIZE; -import static edu.unc.lib.boxc.model.fcrepo.ids.RepositoryPaths.idToPath; -import static edu.unc.lib.boxc.operations.jms.RunEnhancementsMessageHelpers.makeEnhancementOperationBody; -import static org.apache.commons.io.FileUtils.copyInputStreamToFile; -import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; +import edu.unc.lib.boxc.auth.api.Permission; +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; +import edu.unc.lib.boxc.auth.api.services.AccessControlService; +import edu.unc.lib.boxc.model.api.ids.PID; +import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequest; +import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequestSender; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -13,16 +16,11 @@ import java.nio.file.Path; import java.nio.file.Paths; -import org.jdom2.Document; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import edu.unc.lib.boxc.auth.api.Permission; -import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; -import edu.unc.lib.boxc.auth.api.services.AccessControlService; -import edu.unc.lib.boxc.model.api.ids.PID; -import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; -import edu.unc.lib.boxc.operations.jms.MessageSender; +import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_DEPTH; +import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_SIZE; +import static edu.unc.lib.boxc.model.fcrepo.ids.RepositoryPaths.idToPath; +import static org.apache.commons.io.FileUtils.copyInputStreamToFile; +import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; /** * Service to process requests to add/update display thumbnail objects @@ -35,7 +33,7 @@ public class ImportThumbnailService { private String sourceImagesDir; private Path storagePath; private AccessControlService aclService; - private MessageSender messageSender; + private ThumbnailRequestSender messageSender; public void init() { storagePath = Paths.get(sourceImagesDir); @@ -57,8 +55,13 @@ public void run(InputStream importStream, AgentPrincipals agent, String uuid, St File finalLocation = storagePath.resolve(thumbnailBasePath).resolve(uuid).toFile(); copyInputStreamToFile(importStream, finalLocation); - Document msg = makeEnhancementOperationBody(agent.getUsername(), pid, true); - messageSender.sendMessage(msg); + var request = new ImportThumbnailRequest(); + request.setAgent(agent); + request.setMimetype(mimeType); + request.setPidString(uuid); + request.setStoragePath(finalLocation.toPath()); + + messageSender.sendToImportQueue(request); log.info("Job to to add thumbnail to object {} has been queued by {}", uuid, agent.getUsername()); @@ -68,7 +71,7 @@ public void setAclService(AccessControlService aclService) { this.aclService = aclService; } - public void setMessageSender(MessageSender messageSender) { + public void setMessageSender(ThumbnailRequestSender messageSender) { this.messageSender = messageSender; } diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsRequest.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsRequest.java new file mode 100644 index 0000000000..8509f57825 --- /dev/null +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsRequest.java @@ -0,0 +1,47 @@ +package edu.unc.lib.boxc.web.services.processing; + +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; + +import java.util.List; + +/** + * @author bbpennel + */ +public class RunEnhancementsRequest { + private List pids; + private boolean force; + private AgentPrincipals agent; + private boolean recursive; + + public List getPids() { + return pids; + } + + public boolean isForce() { + return force; + } + + public void setPids(List pids) { + this.pids = pids; + } + + public void setForce(boolean force) { + this.force = force; + } + + public AgentPrincipals getAgent() { + return agent; + } + + public void setAgent(AgentPrincipals agent) { + this.agent = agent; + } + + public boolean isRecursive() { + return recursive; + } + + public void setRecursive(boolean recursive) { + this.recursive = recursive; + } +} diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsService.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsService.java index 4b3fff5064..7f032a09a6 100644 --- a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsService.java +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsService.java @@ -6,12 +6,12 @@ import java.util.Arrays; import java.util.List; +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; import org.jdom2.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.unc.lib.boxc.auth.api.Permission; -import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; import edu.unc.lib.boxc.auth.api.services.AccessControlService; import edu.unc.lib.boxc.common.metrics.TimerFactory; import edu.unc.lib.boxc.model.api.ResourceType; @@ -41,7 +41,7 @@ public class RunEnhancementsService { private static final Logger LOG = LoggerFactory.getLogger(RunEnhancementsService.class); private static final Timer timer = TimerFactory.createTimerForClass(RunEnhancementsService.class); - private final List resultsFieldList = Arrays.asList( + private static final List RESULTS_FIELD_LIST = Arrays.asList( SearchFieldKey.DATASTREAM.name(), SearchFieldKey.ID.name(), SearchFieldKey.RESOURCE_TYPE.name()); @@ -57,61 +57,70 @@ public class RunEnhancementsService { * Service to take a list of pids searches for file objects which are in the list of pids * or children of those objects and run enhancements on. * - * @param agent security principals of the agent making request. - * @param objectPids List of pids to run enhancements on - * @param force whether enhancements should run if derivatives are already present + * @param request Request to run enhancements */ - public void run(AgentPrincipals agent, List objectPids, boolean force) { - try (Timer.Context context = timer.time()) { + public void run(RunEnhancementsRequest request) { + try (Timer.Context ignored = timer.time()) { + var agent = request.getAgent(); + var objectPids = request.getPids(); + var force = request.isForce(); + var recursive = request.isRecursive(); for (String objectPid : objectPids) { PID pid = PIDs.get(objectPid); aclService.assertHasAccess("User does not have permission to run enhancements", pid, agent.getPrincipals(), Permission.runEnhancements); - LOG.debug("sending solr update message for {} of type runEnhancements", pid); - - if (!(repositoryObjectLoader.getRepositoryObject(pid) instanceof FileObject)) { - SearchState searchState = new SearchState(); - searchState.addFacet(new GenericFacet(SearchFieldKey.RESOURCE_TYPE, ResourceType.File.name())); - searchState.setResultFields(resultsFieldList); - searchState.setRowsPerPage(1000); - searchState.setIgnoreMaxRows(true); - - SearchRequest searchRequest = new SearchRequest(); - searchRequest.setAccessGroups(agent.getPrincipals()); - searchRequest.setSearchState(searchState); - searchRequest.setRootPid(pid); - searchRequest.setApplyCutoffs(false); - - // Page through results for requests to run enhancements of large folders - long totalResults = -1; - int count = 0; - do { - SearchResultResponse resultResponse = queryLayer.performSearch(searchRequest); - if (totalResults == -1) { - totalResults = resultResponse.getResultCount(); - LOG.debug("Found {} items to queue for enhancement run", totalResults); - // Add the root container itself - ContentObjectRecord rootContainer = resultResponse.getSelectedContainer(); - createMessage(rootContainer, agent.getUsername(), force); - } - for (ContentObjectRecord metadata : resultResponse.getResultList()) { - createMessage(metadata, agent.getUsername(), force); - count++; - } - LOG.debug("Queued {} out of {} items for enhancements", count, totalResults); - } while(count < totalResults); + if (recursive && !(repositoryObjectLoader.getRepositoryObject(pid) instanceof FileObject)) { + LOG.debug("Queueing object and children for enhancements: {}", pid); + recursiveEnhancements(pid, agent, force); } else { - LOG.debug("Queueing a file object for enhancements: {}", pid); - SimpleIdRequest searchRequest = new SimpleIdRequest(pid, agent.getPrincipals()); - ContentObjectRecord metadata = queryLayer.getObjectById(searchRequest); - createMessage(metadata, agent.getUsername(), force); + LOG.debug("Queueing object for enhancements: {}", pid); + shallowEnhancements(pid, agent, force); } } } } + private void recursiveEnhancements(PID pid, AgentPrincipals agent, Boolean force) { + SearchState searchState = new SearchState(); + searchState.addFacet(new GenericFacet(SearchFieldKey.RESOURCE_TYPE, ResourceType.File.name())); + searchState.setResultFields(RESULTS_FIELD_LIST); + searchState.setRowsPerPage(1000); + searchState.setIgnoreMaxRows(true); + + SearchRequest searchRequest = new SearchRequest(); + searchRequest.setAccessGroups(agent.getPrincipals()); + searchRequest.setSearchState(searchState); + searchRequest.setRootPid(pid); + searchRequest.setApplyCutoffs(false); + + // Page through results for requests to run enhancements of large folders + long totalResults = -1; + int count = 0; + do { + SearchResultResponse resultResponse = queryLayer.performSearch(searchRequest); + if (totalResults == -1) { + totalResults = resultResponse.getResultCount(); + LOG.debug("Found {} items to queue for enhancement run", totalResults); + // Add the root container itself + ContentObjectRecord rootContainer = resultResponse.getSelectedContainer(); + createMessage(rootContainer, agent.getUsername(), force); + } + for (ContentObjectRecord metadata : resultResponse.getResultList()) { + createMessage(metadata, agent.getUsername(), force); + count++; + } + LOG.debug("Queued {} out of {} items for enhancements", count, totalResults); + } while(count < totalResults); + } + + private void shallowEnhancements(PID pid, AgentPrincipals agent, Boolean force) { + SimpleIdRequest searchRequest = new SimpleIdRequest(pid, agent.getPrincipals()); + ContentObjectRecord metadata = queryLayer.getObjectById(searchRequest); + createMessage(metadata, agent.getUsername(), force); + } + public void setAclService(AccessControlService aclService) { this.aclService = aclService; } diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/DatastreamController.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/DatastreamController.java index a120054935..f0fa637460 100644 --- a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/DatastreamController.java +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/DatastreamController.java @@ -154,16 +154,7 @@ public ResponseEntity getThumbnail(@PathVariable("pid") Str throw new ResourceNotFoundException("The requested object either does not exist or is not accessible"); } - if (ResourceType.Folder.name().equals(objRecord.getResourceType()) || - ResourceType.Collection.name().equals(objRecord.getResourceType()) || - ResourceType.AdminUnit.name().equals(objRecord.getResourceType())) { - String thumbName = "thumbnail_" + size.toLowerCase().trim(); - try { - return derivativeContentService.streamThumbnail(pid, thumbName); - } catch (IOException e) { - log.error("Error streaming thumbnail for {}", pid); - } - } else if (ResourceType.Work.name().equals(objRecord.getResourceType())) { + if (ResourceType.Work.name().equals(objRecord.getResourceType())) { var thumbId = accessCopiesService.getThumbnailId(objRecord, principals, true); if (thumbId != null) { pid = PIDs.get(thumbId); diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsController.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsController.java index c6e7643788..8e1b47424e 100644 --- a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsController.java +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsController.java @@ -3,9 +3,9 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import java.util.HashMap; -import java.util.List; import java.util.Map; +import edu.unc.lib.boxc.web.services.processing.RunEnhancementsRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -37,9 +37,10 @@ public class RunEnhancementsController { @PostMapping(value = "runEnhancements", produces = APPLICATION_JSON_VALUE) public @ResponseBody ResponseEntity runEnhancements(@RequestBody RunEnhancementsRequest data) { Map result = new HashMap<>(); + data.setAgent(GroupsThreadStore.getAgentPrincipals()); try { - enhService.run(GroupsThreadStore.getAgentPrincipals(), data.getPids(), data.isForce()); + enhService.run(data); result.put("message", "Enhancement of " + data.getPids().size() + " object(s) and their children has begun"); result.put("action", "runEnhancements"); @@ -61,19 +62,6 @@ public class RunEnhancementsController { return new ResponseEntity<>(result, HttpStatus.OK); } - public static class RunEnhancementsRequest { - private List pids; - private boolean force; - - public List getPids() { - return pids; - } - - public boolean isForce() { - return force; - } - } - public void setEnhancementService(RunEnhancementsService enhService) { this.enhService = enhService; } diff --git a/web-services-app/src/main/webapp/WEB-INF/service-context.xml b/web-services-app/src/main/webapp/WEB-INF/service-context.xml index 77831c8649..8b0e2bab89 100644 --- a/web-services-app/src/main/webapp/WEB-INF/service-context.xml +++ b/web-services-app/src/main/webapp/WEB-INF/service-context.xml @@ -294,10 +294,10 @@ - - + @@ -444,6 +444,7 @@ + diff --git a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/processing/ImportThumbnailServiceTest.java b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/processing/ImportThumbnailServiceTest.java new file mode 100644 index 0000000000..f39b5fd54a --- /dev/null +++ b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/processing/ImportThumbnailServiceTest.java @@ -0,0 +1,113 @@ +package edu.unc.lib.boxc.web.services.processing; + +import edu.unc.lib.boxc.auth.api.exceptions.AccessRestrictionException; +import edu.unc.lib.boxc.auth.api.models.AccessGroupSet; +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; +import edu.unc.lib.boxc.auth.api.services.AccessControlService; +import edu.unc.lib.boxc.model.api.objects.CollectionObject; +import edu.unc.lib.boxc.model.api.objects.FileObject; +import edu.unc.lib.boxc.model.api.objects.RepositoryObjectLoader; +import edu.unc.lib.boxc.model.api.objects.WorkObject; +import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; +import edu.unc.lib.boxc.operations.jms.OperationsMessageSender; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequest; +import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequest; +import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequestSender; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import static edu.unc.lib.boxc.auth.api.Permission.editDescription; +import static edu.unc.lib.boxc.auth.api.Permission.editResourceType; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.openMocks; + +public class ImportThumbnailServiceTest { + private static final String COLLECTION_UUID = "9cb6cc61-d88e-403e-b959-2396cd331a12"; + private AutoCloseable closeable; + private ImportThumbnailService importThumbnailService; + @Mock + private AccessControlService aclService; + @Mock + private RepositoryObjectLoader repoObjLoader; + @Mock + private ThumbnailRequestSender messageSender; + @Mock + private AgentPrincipals agent; + @Mock + private AccessGroupSet groups; + @Mock + private CollectionObject collectionObject; + @Captor + private ArgumentCaptor requestCaptor; + private InputStream inputStream; + @TempDir + public Path tmpFolder; + private Path tempStoragePath; + + + @BeforeEach + public void init() throws FileNotFoundException { + closeable = openMocks(this); + tempStoragePath = tmpFolder.resolve("thumbnails"); + importThumbnailService = new ImportThumbnailService(); + importThumbnailService.setAclService(aclService); + importThumbnailService.setMessageSender(messageSender); + importThumbnailService.setSourceImagesDir(tempStoragePath.toString()); + importThumbnailService.init(); + inputStream = new FileInputStream("src/test/resources/__files/bunny.jpg"); + } + + @AfterEach + void closeService() throws Exception { + closeable.close(); + } + + @Test + public void noAccessTest() { + Assertions.assertThrows(AccessRestrictionException.class, () -> { + doThrow(new AccessRestrictionException()).when(aclService) + .assertHasAccess(anyString(), any(), any(), eq(editDescription)); + + importThumbnailService.run(inputStream, agent, COLLECTION_UUID, "image/jpeg"); + }); + } + + @Test + public void notAnImageTest() { + Assertions.assertThrows(IllegalArgumentException.class, () -> { + importThumbnailService.run(inputStream, agent, COLLECTION_UUID, "video/mp4"); + }); + } + + @Test + public void successTest() throws IOException { + var mimetype = "image/jpeg"; + importThumbnailService.run(inputStream, agent, COLLECTION_UUID, mimetype); + verify(messageSender).sendToImportQueue(requestCaptor.capture()); + + var request = requestCaptor.getValue(); + assertEquals(COLLECTION_UUID, request.getPidString()); + assertEquals(agent, request.getAgent()); + assertEquals(mimetype, request.getMimetype()); + assertTrue(Files.exists(tempStoragePath)); + } +} diff --git a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsServiceTest.java b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsServiceTest.java new file mode 100644 index 0000000000..6740af8476 --- /dev/null +++ b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/processing/RunEnhancementsServiceTest.java @@ -0,0 +1,249 @@ +package edu.unc.lib.boxc.web.services.processing; + +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; +import edu.unc.lib.boxc.auth.api.services.AccessControlService; +import edu.unc.lib.boxc.auth.fcrepo.models.AccessGroupSetImpl; +import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; +import edu.unc.lib.boxc.model.api.ResourceType; +import edu.unc.lib.boxc.model.api.ids.PID; +import edu.unc.lib.boxc.model.api.objects.CollectionObject; +import edu.unc.lib.boxc.model.api.objects.ContentObject; +import edu.unc.lib.boxc.model.api.objects.RepositoryObjectLoader; +import edu.unc.lib.boxc.model.api.objects.WorkObject; +import edu.unc.lib.boxc.model.fcrepo.ids.DatastreamPids; +import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; +import edu.unc.lib.boxc.model.fcrepo.test.TestHelper; +import edu.unc.lib.boxc.operations.jms.MessageSender; +import edu.unc.lib.boxc.search.api.models.ContentObjectRecord; +import edu.unc.lib.boxc.search.api.models.Datastream; +import edu.unc.lib.boxc.search.solr.responses.SearchResultResponse; +import edu.unc.lib.boxc.web.common.services.SolrQueryLayerService; +import org.jdom2.Document; +import org.jdom2.Element; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import edu.unc.lib.boxc.model.api.objects.FileObject; + +import java.util.List; + +import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; +import static edu.unc.lib.boxc.model.api.xml.JDOMNamespaceUtil.ATOM_NS; +import static edu.unc.lib.boxc.model.api.xml.JDOMNamespaceUtil.CDR_MESSAGE_NS; +import static edu.unc.lib.boxc.operations.jms.JMSMessageUtil.CDRActions.RUN_ENHANCEMENTS; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; + +/** + * @author bbpennel + */ +public class RunEnhancementsServiceTest { + private static final String USER_NAME = "user"; + private AutoCloseable closeable; + @Mock + private AccessControlService aclService; + @Mock + private MessageSender messageSender; + @Mock + private RepositoryObjectLoader repositoryObjectLoader; + @Mock + private SolrQueryLayerService queryLayer; + private AgentPrincipals agent; + private RunEnhancementsService service; + private PID filePid; + @Mock + private FileObject fileObject; + @Mock + private ContentObjectRecord fileRecord; + @Mock + private Datastream originalDs; + private PID workPid; + @Mock + private WorkObject workObject; + @Mock + private ContentObjectRecord workRecord; + @Captor + private ArgumentCaptor docCaptor; + @Mock + private SearchResultResponse searchResultResp; + + @BeforeEach + public void setup() { + closeable = openMocks(this); + service = new RunEnhancementsService(); + service.setAclService(aclService); + service.setMessageSender(messageSender); + service.setQueryLayer(queryLayer); + service.setRepositoryObjectLoader(repositoryObjectLoader); + agent = new AgentPrincipalsImpl(USER_NAME, new AccessGroupSetImpl("group")); + + filePid = TestHelper.makePid(); + mockObject(filePid, fileObject, fileRecord, ResourceType.File); + when(fileRecord.getDatastreamObject(ORIGINAL_FILE.getId())).thenReturn(originalDs); + + workPid = TestHelper.makePid(); + mockObject(workPid, workObject, workRecord, ResourceType.Work); + + when(queryLayer.performSearch(any())).thenReturn(searchResultResp); + } + + private void mockObject(PID pid, ContentObject contentObject, ContentObjectRecord record, ResourceType resourceType) { + when(repositoryObjectLoader.getRepositoryObject(pid)).thenReturn(contentObject); + when(queryLayer.getObjectById(argThat(req -> req != null && pid.equals(req.getPid())))).thenReturn(record); + when(record.getPid()).thenReturn(pid); + when(record.getResourceType()).thenReturn(resourceType.name()); + } + + @AfterEach + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void runFileObjectTest() { + var request = new RunEnhancementsRequest(); + request.setAgent(agent); + request.setRecursive(true); + request.setForce(false); + request.setPids(List.of(filePid.getId())); + + service.run(request); + + verify(messageSender).sendMessage(docCaptor.capture()); + Document msgDoc = docCaptor.getValue(); + var dsPid = DatastreamPids.getOriginalFilePid(filePid); + assertMessageValues(msgDoc, dsPid, false); + } + + @Test + public void runFileObjectWithForceTest() { + var request = new RunEnhancementsRequest(); + request.setAgent(agent); + request.setRecursive(true); + request.setForce(true); + request.setPids(List.of(filePid.getId())); + + service.run(request); + + verify(messageSender).sendMessage(docCaptor.capture()); + Document msgDoc = docCaptor.getValue(); + var dsPid = DatastreamPids.getOriginalFilePid(filePid); + assertMessageValues(msgDoc, dsPid, true); + } + + @Test + public void runWorkObjectShallowTest() { + var request = new RunEnhancementsRequest(); + request.setAgent(agent); + request.setRecursive(false); + request.setForce(false); + request.setPids(List.of(workPid.getId())); + + service.run(request); + + verify(messageSender).sendMessage(docCaptor.capture()); + Document msgDoc = docCaptor.getValue(); + assertMessageValues(msgDoc, workPid, false); + } + + @Test + public void runWorkObjectRecursiveTest() { + when(searchResultResp.getResultCount()).thenReturn(1L); + when(searchResultResp.getSelectedContainer()).thenReturn(workRecord); + when(searchResultResp.getResultList()).thenReturn(List.of(fileRecord)); + + var request = new RunEnhancementsRequest(); + request.setAgent(agent); + request.setRecursive(true); + request.setForce(false); + request.setPids(List.of(workPid.getId())); + + service.run(request); + + verify(messageSender, times(2)).sendMessage(docCaptor.capture()); + var msgDocs = docCaptor.getAllValues(); + assertMessageValues(msgDocs.get(0), workPid, false); + var dsPid = DatastreamPids.getOriginalFilePid(filePid); + assertMessageValues(msgDocs.get(1), dsPid, false); + } + + @Test + public void runMultiplePidsShallowTest() { + PID collPid = TestHelper.makePid(); + var collObject = mock(CollectionObject.class); + var collRecord = mock(ContentObjectRecord.class); + mockObject(collPid, collObject, collRecord, ResourceType.Collection); + + var request = new RunEnhancementsRequest(); + request.setAgent(agent); + request.setRecursive(false); + request.setForce(false); + request.setPids(List.of(workPid.getId(), filePid.getId(), collPid.getId())); + + service.run(request); + + verify(messageSender, times(3)).sendMessage(docCaptor.capture()); + var msgDocs = docCaptor.getAllValues(); + assertMessageValues(msgDocs.get(0), workPid, false); + var dsPid = DatastreamPids.getOriginalFilePid(filePid); + assertMessageValues(msgDocs.get(1), dsPid, false); + assertMessageValues(msgDocs.get(2), collPid, false); + } + + @Test + public void runMultiplePidsRecursiveTest() { + PID workPid2 = TestHelper.makePid(); + var workObject2 = mock(WorkObject.class); + var workRecord2 = mock(ContentObjectRecord.class); + mockObject(workPid2, workObject2, workRecord2, ResourceType.Work); + + PID filePid2 = TestHelper.makePid(); + var fileObject2 = mock(FileObject.class); + var fileRecord2 = mock(ContentObjectRecord.class); + mockObject(filePid2, fileObject2, fileRecord2, ResourceType.File); + when(fileRecord2.getDatastreamObject(ORIGINAL_FILE.getId())).thenReturn(originalDs); + + when(searchResultResp.getResultCount()).thenReturn(1L); + when(searchResultResp.getSelectedContainer()).thenReturn(workRecord, workRecord2); + when(searchResultResp.getResultList()).thenReturn(List.of(fileRecord)).thenReturn(List.of(fileRecord2)); + + var request = new RunEnhancementsRequest(); + request.setAgent(agent); + request.setRecursive(true); + request.setForce(false); + request.setPids(List.of(workPid.getId(), workPid2.getId())); + + service.run(request); + + verify(messageSender, times(4)).sendMessage(docCaptor.capture()); + var msgDocs = docCaptor.getAllValues(); + assertMessageValues(msgDocs.get(0), workPid, false); + var dsPid = DatastreamPids.getOriginalFilePid(filePid); + assertMessageValues(msgDocs.get(1), dsPid, false); + assertMessageValues(msgDocs.get(2), workPid2, false); + var dsPid2 = DatastreamPids.getOriginalFilePid(filePid2); + assertMessageValues(msgDocs.get(3), dsPid2, false); + } + + private void assertMessageValues(Document msgDoc, PID expectedPid, boolean expectedForce) { + Element entry = msgDoc.getRootElement(); + Element runEl = entry.getChild(RUN_ENHANCEMENTS.getName(), CDR_MESSAGE_NS); + String pidString = runEl.getChildText("pid", CDR_MESSAGE_NS); + String author = entry.getChild("author", ATOM_NS) + .getChildText("name", ATOM_NS); + var force = Boolean.valueOf(runEl.getChildText("force", CDR_MESSAGE_NS)); + + assertEquals(expectedPid, PIDs.get(pidString)); + assertEquals(USER_NAME, author); + assertEquals(expectedForce, force); + } +} diff --git a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DatastreamRestControllerIT.java b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DatastreamRestControllerIT.java index 60f139c851..35fc06a483 100644 --- a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DatastreamRestControllerIT.java +++ b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DatastreamRestControllerIT.java @@ -25,7 +25,6 @@ import edu.unc.lib.boxc.web.services.rest.modify.AbstractAPIIT; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.jena.rdf.model.Model; import org.apache.jena.vocabulary.RDF; import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; @@ -52,10 +51,9 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; import static edu.unc.lib.boxc.auth.api.Permission.viewAccessCopies; import static edu.unc.lib.boxc.auth.api.Permission.viewHidden; +import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; import static edu.unc.lib.boxc.model.api.DatastreamType.MD_EVENTS; import static edu.unc.lib.boxc.model.api.DatastreamType.TECHNICAL_METADATA; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_LARGE; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_SMALL; import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_DEPTH; import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_SIZE; import static edu.unc.lib.boxc.model.api.rdf.RDFModelUtil.createModel; @@ -256,7 +254,15 @@ public void testGetThumbnailForCollection() throws Exception { var corpus = populateCorpus(); var collectionPid = corpus.pid2; var id = collectionPid.getId(); - createDerivative(id, THUMBNAIL_LARGE, BINARY_CONTENT.getBytes()); + createDerivative(id, JP2_ACCESS_COPY, BINARY_CONTENT.getBytes()); + + var filename = "bunny.jpg"; + var formattedBasePath = "/iiif/v3/" + ImageServerUtil.getImageServerEncodedId(collectionPid.getId()); + stubFor(WireMock.get(urlMatching(formattedBasePath + "/full/!128,128/0/default.jpg")) + .willReturn(aResponse() + .withStatus(HttpStatus.OK.value()) + .withBody(filename) + .withHeader("Content-Type", MediaType.IMAGE_JPEG_VALUE))); MvcResult result = mvc.perform(get("/thumb/" + id + "/large")) .andExpect(status().is2xxSuccessful()) @@ -264,11 +270,9 @@ public void testGetThumbnailForCollection() throws Exception { // Verify content was retrieved MockHttpServletResponse response = result.getResponse(); - assertEquals(BINARY_CONTENT, response.getContentAsString()); - assertEquals(BINARY_CONTENT.length(), response.getContentLength()); - assertEquals(MediaType.IMAGE_PNG.toString(), response.getContentType()); - assertEquals("inline; filename=" + id + "." + THUMBNAIL_LARGE.getExtension(), - response.getHeader(CONTENT_DISPOSITION)); + assertEquals(filename, response.getContentAsString()); + assertEquals(MediaType.IMAGE_JPEG_VALUE, response.getContentType()); + assertEquals("inline; filename=bunny_128px.jpg", response.getHeader(CONTENT_DISPOSITION)); } @Test @@ -308,9 +312,9 @@ private TestCorpus populateCorpus() throws Exception { public void testGetFileDerivative() throws Exception { PID filePid = makePid(); String id = filePid.getId(); - createDerivative(id, THUMBNAIL_SMALL, BINARY_CONTENT.getBytes()); + createDerivative(id, JP2_ACCESS_COPY, BINARY_CONTENT.getBytes()); - MvcResult result = mvc.perform(get("/file/" + filePid.getId() + "/" + THUMBNAIL_SMALL.getId())) + MvcResult result = mvc.perform(get("/file/" + filePid.getId() + "/" + JP2_ACCESS_COPY.getId())) .andExpect(status().is2xxSuccessful()) .andReturn(); @@ -318,8 +322,8 @@ public void testGetFileDerivative() throws Exception { MockHttpServletResponse response = result.getResponse(); assertEquals(BINARY_CONTENT, response.getContentAsString()); assertEquals(BINARY_CONTENT.length(), response.getContentLength()); - assertEquals("image/png", response.getContentType()); - assertEquals("inline; filename=\"" + id + "." + THUMBNAIL_SMALL.getExtension() + "\"", + assertEquals("image/jp2", response.getContentType()); + assertEquals("inline; filename=\"" + id + "." + JP2_ACCESS_COPY.getExtension() + "\"", response.getHeader(CONTENT_DISPOSITION)); } diff --git a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsIT.java b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsIT.java index 3eaf29b553..da3775d3e1 100644 --- a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsIT.java +++ b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/RunEnhancementsIT.java @@ -163,7 +163,7 @@ public void runEnhancementsWorkObject() throws Exception { MvcResult result = mvc.perform(post("/runEnhancements") .contentType(MediaType.APPLICATION_JSON) - .content("{\"force\":false,\"pids\":[\"" + workFile.getPid().getId() + "\"]}") + .content("{\"force\":false,\"recursive\":true,\"pids\":[\"" + workFile.getPid().getId() + "\"]}") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().is2xxSuccessful()) .andReturn(); @@ -188,7 +188,7 @@ public void runEnhancementsNonFileNonWorkObject() throws Exception { MvcResult result = mvc.perform(post("/runEnhancements") .contentType(MediaType.APPLICATION_JSON) - .content("{\"force\":false,\"pids\":[\"" + filePid.getId() + "\"]}") + .content("{\"force\":false,\"recursive\":true,\"pids\":[\"" + filePid.getId() + "\"]}") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().is2xxSuccessful()) .andReturn(); @@ -212,7 +212,7 @@ public void runEnhancementsNoAccess() throws Exception { mvc.perform(post("/runEnhancements") .contentType(MediaType.APPLICATION_JSON) - .content("{\"force\":false,\"pids\":[\"" + objPid.toString() + "\"]}") + .content("{\"force\":false,\"recursive\":true,\"pids\":[\"" + objPid.toString() + "\"]}") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isForbidden()) .andReturn(); diff --git a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/modify/ThumbnailIT.java b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/modify/ThumbnailIT.java index 1e77f579fc..1149e322b7 100644 --- a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/modify/ThumbnailIT.java +++ b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/modify/ThumbnailIT.java @@ -26,6 +26,7 @@ import edu.unc.lib.boxc.auth.api.services.AccessControlService; import edu.unc.lib.boxc.model.api.objects.RepositoryObjectLoader; import edu.unc.lib.boxc.model.api.rdf.Cdr; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequest; import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequest; import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequestSender; import edu.unc.lib.boxc.web.services.rest.MvcTestHelpers; @@ -69,25 +70,19 @@ public class ThumbnailIT extends AbstractAPIIT { @TempDir public Path tmpFolder; - @Captor - private ArgumentCaptor docCaptor; + private ArgumentCaptor importRequestCaptor; @Captor private ArgumentCaptor requestCaptor; - private ImportThumbnailService service; - @Mock - private MessageSender messageSender; @Autowired private RepositoryObjectFactory repositoryObjectFactory; @Mock private ThumbnailRequestSender thumbnailRequestSender; - @Mock private RepositoryObjectLoader repositoryObjectLoader; @InjectMocks private ThumbnailController controller; - private File tempDir; @BeforeEach @@ -97,7 +92,7 @@ public void initLocal() { aclService = mock(AccessControlService.class); service = new ImportThumbnailService(); service.setAclService(aclService); - service.setMessageSender(messageSender); + service.setMessageSender(thumbnailRequestSender); service.setSourceImagesDir(tempDir.getAbsolutePath()); service.init(); controller.setImportThumbnailService(service); @@ -118,15 +113,17 @@ void closeService() throws Exception { public void addEditThumbnail() throws Exception { FileInputStream input = new FileInputStream("src/test/resources/upload-files/burndown.png"); MockMultipartFile thumbnailFile = new MockMultipartFile("file", "burndown.png", "image/png", IOUtils.toByteArray(input)); + var id = collection.getPid().getUUID(); - mvc.perform(MockMvcRequestBuilders.multipart("/edit/displayThumbnail/" + collection.getPid().getUUID()) + mvc.perform(MockMvcRequestBuilders.multipart("/edit/displayThumbnail/" + id) .file(thumbnailFile)) .andExpect(status().is2xxSuccessful()) .andReturn(); - verify(messageSender).sendMessage(docCaptor.capture()); - Document msgDoc = docCaptor.getValue(); - assertMessageValues(msgDoc, collection.getPid()); + verify(thumbnailRequestSender).sendToImportQueue(importRequestCaptor.capture()); + var request = importRequestCaptor.getValue(); + assertEquals(id, request.getPidString()); + assertEquals("image/png", request.getMimetype()); } @Test @@ -138,7 +135,7 @@ public void addCollectionThumbWrongFileType() throws Exception { .andExpect(status().is4xxClientError()) .andReturn(); - verify(messageSender, never()).sendMessage(any(Document.class)); + verify(thumbnailRequestSender, never()).sendToImportQueue(any(ImportThumbnailRequest.class)); } @Test @@ -153,7 +150,7 @@ public void addCollectionThumbNoAccess() throws Exception { .andExpect(status().isForbidden()) .andReturn(); - verify(messageSender, never()).sendMessage(any(Document.class)); + verify(thumbnailRequestSender, never()).sendToImportQueue(any(ImportThumbnailRequest.class)); } @Test @@ -327,14 +324,4 @@ private byte[] textStream() { return "I am not an image".getBytes(); } - private void assertMessageValues(Document msgDoc, PID expectedPid) { - Element entry = msgDoc.getRootElement(); - String pidString = entry.getChild(RUN_ENHANCEMENTS.getName(), CDR_MESSAGE_NS) - .getChildText("pid", CDR_MESSAGE_NS); - String author = entry.getChild("author", ATOM_NS) - .getChildText("name", ATOM_NS); - - assertEquals(collection.getPid().getURI(), pidString); - assertEquals(USERNAME, author); - } }