From 01013ebea1461b1c5e55770132b59e9b39fdaadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Ko=C5=A1arko?= Date: Wed, 23 Oct 2024 12:14:03 +0200 Subject: [PATCH 1/3] Add a script that adds a file from url to an item intended for large file workflows --- .../org/dspace/administer/FileDownloader.java | 177 ++++++++++++++++++ .../FileDownloaderConfiguration.java | 63 +++++++ .../config/spring/api/scripts.xml | 5 + .../dspace/administer/FileDownloaderIT.java | 101 ++++++++++ dspace/config/spring/rest/scripts.xml | 5 + 5 files changed, 351 insertions(+) create mode 100644 dspace-api/src/main/java/org/dspace/administer/FileDownloader.java create mode 100644 dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java create mode 100644 dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java diff --git a/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java b/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java new file mode 100644 index 000000000000..b6b552c33180 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java @@ -0,0 +1,177 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.administer; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.sql.SQLException; +import java.util.List; +import java.util.UUID; + +import org.apache.commons.cli.ParseException; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Bitstream; +import org.dspace.content.BitstreamFormat; +import org.dspace.content.Bundle; +import org.dspace.content.Item; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.BitstreamFormatService; +import org.dspace.content.service.BitstreamService; +import org.dspace.content.service.ItemService; +import org.dspace.core.Context; +import org.dspace.eperson.EPerson; +import org.dspace.eperson.factory.EPersonServiceFactory; +import org.dspace.eperson.service.EPersonService; +import org.dspace.scripts.DSpaceRunnable; +import org.dspace.scripts.configuration.ScriptConfiguration; +import org.dspace.utils.DSpace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class FileDownloader extends DSpaceRunnable { + + private static final Logger log = LoggerFactory.getLogger(FileDownloader.class); + private boolean help = false; + private UUID itemUUID; + private URI uri; + private String epersonMail; + private EPersonService epersonService; + private ItemService itemService; + private BitstreamService bitstreamService; + private BitstreamFormatService bitstreamFormatService; + private final HttpClient httpClient = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.NORMAL) + .build(); + + /** + * This method will return the Configuration that the implementing DSpaceRunnable uses + * + * @return The {@link ScriptConfiguration} that this implementing DspaceRunnable uses + */ + @Override + public FileDownloaderConfiguration getScriptConfiguration() { + return new DSpace().getServiceManager().getServiceByName("file-downloader", + FileDownloaderConfiguration.class); + } + + /** + * This method has to be included in every script and handles the setup of the script by parsing the CommandLine + * and setting the variables + * + * @throws ParseException If something goes wrong + */ + @Override + public void setup() throws ParseException { + log.debug("Setting up {}", FileDownloader.class.getName()); + if (commandLine.hasOption("h")) { + help = true; + return; + } + + if (!commandLine.hasOption("u")) { + throw new ParseException("No URL option has been provided"); + } + + if (!commandLine.hasOption("i")) { + throw new ParseException("No item option has been provided"); + } + + if (getEpersonIdentifier() == null && !commandLine.hasOption("e")) { + throw new ParseException("No eperson option has been provided"); + } + + + this.epersonService = EPersonServiceFactory.getInstance().getEPersonService(); + this.itemService = ContentServiceFactory.getInstance().getItemService(); + this.bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); + this.bitstreamFormatService = ContentServiceFactory.getInstance().getBitstreamFormatService(); + + try { + uri = new URI(commandLine.getOptionValue("u")); + } catch (URISyntaxException e) { + throw new ParseException("The provided URL is not a valid URL"); + } + itemUUID = UUID.fromString(commandLine.getOptionValue("i")); + + epersonMail = commandLine.getOptionValue("e"); + } + + /** + * This method has to be included in every script and this will be the main execution block for the script that'll + * contain all the logic needed + * + * @throws Exception If something goes wrong + */ + @Override + public void internalRun() throws Exception { + log.debug("Running {}", FileDownloader.class.getName()); + if (help) { + printHelp(); + return; + } + + Context context = new Context(); + context.setCurrentUser(getEperson(context)); + + // Download the file from the given url + // and save it to the item with the given UUID + + //find the item by the given uuid + Item item = itemService.find(context, itemUUID); + if (item == null) { + throw new IllegalArgumentException("No item found for the given UUID"); + } + + HttpRequest request = HttpRequest.newBuilder() + .uri(uri) + .build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream()); + + if (response.statusCode() >= 400) { + throw new IllegalArgumentException("The provided URL returned a status code of " + response.statusCode()); + } + + try (InputStream is = response.body()) { + saveFileToItem(context, item, is); + } + + context.commit(); + } + + private void saveFileToItem(Context context, Item item, InputStream is) + throws SQLException, AuthorizeException, IOException { + log.debug("Saving file to item {}", item.getID()); + List originals = item.getBundles("ORIGINAL"); + Bitstream b; + if (originals.isEmpty()) { + b = itemService.createSingleBitstream(context, is, item); + } else { + Bundle bundle = originals.get(0); + b = bitstreamService.create(context, bundle, is); + } + //now guess format of the bitstream + BitstreamFormat bf = bitstreamFormatService.guessFormat(context, b); + b.setFormat(context, bf); + } + + private EPerson getEperson(Context context) throws SQLException { + if (getEpersonIdentifier() != null) { + return epersonService.find(context, getEpersonIdentifier()); + } else { + return epersonService.findByEmail(context, epersonMail); + } + } +} + diff --git a/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java b/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java new file mode 100644 index 000000000000..3dac14174704 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java @@ -0,0 +1,63 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.administer; + +import org.apache.commons.cli.Options; +import org.dspace.scripts.configuration.ScriptConfiguration; + +public class FileDownloaderConfiguration extends ScriptConfiguration { + + private Class dspaceRunnableClass; + + /** + * Generic getter for the dspaceRunnableClass + * + * @return the dspaceRunnableClass value of this ScriptConfiguration + */ + @Override + public Class getDspaceRunnableClass() { + return dspaceRunnableClass; + } + + /** + * Generic setter for the dspaceRunnableClass + * + * @param dspaceRunnableClass The dspaceRunnableClass to be set on this IndexDiscoveryScriptConfiguration + */ + @Override + public void setDspaceRunnableClass(Class dspaceRunnableClass) { + this.dspaceRunnableClass = dspaceRunnableClass; + } + + /** + * The getter for the options of the Script + * + * @return the options value of this ScriptConfiguration + */ + @Override + public Options getOptions() { + if (options == null) { + + Options options = new Options(); + + options.addOption("h", "help", false, "help"); + + options.addOption("u", "url", true, "source url"); + options.getOption("u").setRequired(true); + + options.addOption("i", "item", true, "item uuid"); + options.getOption("i").setRequired(true); + + options.addOption("e", "eperson", true, "eperson email"); + options.getOption("e").setRequired(false); + + super.options = options; + } + return options; + } +} diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml index e388065b68fd..738e11f7b432 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml @@ -91,4 +91,9 @@ + + + + + diff --git a/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java b/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java new file mode 100644 index 000000000000..f6216ee55d3a --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java @@ -0,0 +1,101 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.administer; + +import static org.junit.Assert.assertEquals; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.dspace.AbstractIntegrationTestWithDatabase; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.ItemBuilder; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.BitstreamService; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockserver.junit.MockServerRule; + +public class FileDownloaderIT extends AbstractIntegrationTestWithDatabase { + + @Rule + public MockServerRule mockServerRule = new MockServerRule(this); + + private Item item; + + //Prepare a community and a collection before the test + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + context.setCurrentUser(admin); + Community community = CommunityBuilder.createCommunity(context).build(); + Collection collection = CollectionBuilder.createCollection(context, community).build(); + item = ItemBuilder.createItem(context, collection).withTitle("FileDownloaderIT Item").build(); + + mockServerRule.getClient().when(request() + .withMethod("GET") + .withPath("/test400") + ).respond( + response() + .withStatusCode(400) + .withBody("test") + ); + + mockServerRule.getClient().when(request() + .withMethod("GET") + .withPath("/test") + ).respond( + response() + .withStatusCode(200) + .withBody("test") + ); + } + + //Test that when an error occurs no bitstream is actually added to the item + @Test() + public void testDownloadFileError() throws Exception { + + + BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); + int oldBitCount = bitstreamService.countTotal(context); + + int port = mockServerRule.getPort(); + String[] args = new String[]{"file-downloader", "-i", item.getID().toString(), + "-u", String.format("http://localhost:%s/test400", port), "-e", "admin@email.com"}; + try { + runDSpaceScript(args); + } catch (IllegalArgumentException e) { + assertEquals(0, item.getBundles().size()); + int newBitCount = bitstreamService.countTotal(context); + assertEquals(oldBitCount, newBitCount); + return; + } + assertEquals(0, 1); + } + + + //Test that FileDownlaoder actually adds the bitstream to the item + @Test + public void testDownloadFile() throws Exception { + + int port = mockServerRule.getPort(); + String[] args = new String[] {"file-downloader", "-i", item.getID().toString(), + "-u", String.format("http://localhost:%s/test", port), "-e", "admin@email.com"}; + runDSpaceScript(args); + + + assertEquals(1, item.getBundles().size()); + assertEquals(1, item.getBundles().get(0).getBitstreams().size()); + } + +} \ No newline at end of file diff --git a/dspace/config/spring/rest/scripts.xml b/dspace/config/spring/rest/scripts.xml index 5fe487ddcc5d..a8ef279383ae 100644 --- a/dspace/config/spring/rest/scripts.xml +++ b/dspace/config/spring/rest/scripts.xml @@ -69,4 +69,9 @@ + + + + + From 1b2bb8edaf4f69aeec871ce7ec46e842c97c1c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Ko=C5=A1arko?= Date: Wed, 23 Oct 2024 17:32:18 +0200 Subject: [PATCH 2/3] Add ways to influence the bitstream name --- .../org/dspace/administer/FileDownloader.java | 21 +++++++++++++++++-- .../FileDownloaderConfiguration.java | 3 +++ .../dspace/administer/FileDownloaderIT.java | 11 +++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java b/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java index b6b552c33180..41ef7d5fba91 100644 --- a/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java +++ b/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java @@ -17,6 +17,7 @@ import java.sql.SQLException; import java.util.List; import java.util.UUID; +import java.util.stream.Stream; import org.apache.commons.cli.ParseException; import org.dspace.authorize.AuthorizeException; @@ -46,6 +47,7 @@ public class FileDownloader extends DSpaceRunnable private UUID itemUUID; private URI uri; private String epersonMail; + private String bitstreamName; private EPersonService epersonService; private ItemService itemService; private BitstreamService bitstreamService; @@ -105,6 +107,10 @@ public void setup() throws ParseException { itemUUID = UUID.fromString(commandLine.getOptionValue("i")); epersonMail = commandLine.getOptionValue("e"); + + if (commandLine.hasOption("n")) { + bitstreamName = commandLine.getOptionValue("n"); + } } /** @@ -143,14 +149,24 @@ public void internalRun() throws Exception { throw new IllegalArgumentException("The provided URL returned a status code of " + response.statusCode()); } + //use the provided value, the content-disposition header, the last part of the uri + if (bitstreamName == null) { + bitstreamName = response.headers().firstValue("Content-Disposition") + .filter(value -> value.contains("filename=")).flatMap(value -> Stream.of(value.split(";")) + .filter(v -> v.contains("filename=")) + .findFirst() + .map(fvalue -> fvalue.replaceFirst("filename=", "").replaceAll("\"", ""))) + .orElse(uri.getPath().substring(uri.getPath().lastIndexOf('/') + 1)); + } + try (InputStream is = response.body()) { - saveFileToItem(context, item, is); + saveFileToItem(context, item, is, bitstreamName); } context.commit(); } - private void saveFileToItem(Context context, Item item, InputStream is) + private void saveFileToItem(Context context, Item item, InputStream is, String name) throws SQLException, AuthorizeException, IOException { log.debug("Saving file to item {}", item.getID()); List originals = item.getBundles("ORIGINAL"); @@ -161,6 +177,7 @@ private void saveFileToItem(Context context, Item item, InputStream is) Bundle bundle = originals.get(0); b = bitstreamService.create(context, bundle, is); } + b.setName(context, name); //now guess format of the bitstream BitstreamFormat bf = bitstreamFormatService.guessFormat(context, b); b.setFormat(context, bf); diff --git a/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java b/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java index 3dac14174704..78177e77a7ef 100644 --- a/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java @@ -56,6 +56,9 @@ public Options getOptions() { options.addOption("e", "eperson", true, "eperson email"); options.getOption("e").setRequired(false); + options.addOption("n", "name", true, "name of the file/bitstream"); + options.getOption("n").setRequired(false); + super.options = options; } return options; diff --git a/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java b/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java index f6216ee55d3a..a946533838df 100644 --- a/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java +++ b/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java @@ -8,13 +8,17 @@ package org.dspace.administer; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; +import java.util.List; + import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; +import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.Item; @@ -25,6 +29,7 @@ import org.junit.Test; import org.mockserver.junit.MockServerRule; + public class FileDownloaderIT extends AbstractIntegrationTestWithDatabase { @Rule @@ -57,6 +62,7 @@ public void setUp() throws Exception { ).respond( response() .withStatusCode(200) + .withHeader("Content-Disposition", "attachment; filename=\"test.txt\"") .withBody("test") ); } @@ -95,7 +101,10 @@ public void testDownloadFile() throws Exception { assertEquals(1, item.getBundles().size()); - assertEquals(1, item.getBundles().get(0).getBitstreams().size()); + List bs = item.getBundles().get(0).getBitstreams(); + assertEquals(1, bs.size()); + assertNotNull("Expecting name to be defined", bs.get(0).getName()); + } } \ No newline at end of file From fd51fafd29b72ebba3cc7f8ecb99d31fd929e89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Ko=C5=A1arko?= Date: Thu, 24 Oct 2024 10:01:43 +0200 Subject: [PATCH 3/3] add more options to specify an item --- .../org/dspace/administer/FileDownloader.java | 53 +++++++++++++++---- .../FileDownloaderConfiguration.java | 11 +++- .../dspace/administer/FileDownloaderIT.java | 2 +- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java b/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java index 41ef7d5fba91..fb592627adef 100644 --- a/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java +++ b/dspace-api/src/main/java/org/dspace/administer/FileDownloader.java @@ -24,15 +24,21 @@ import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; +import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BitstreamFormatService; import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.WorkspaceItemService; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.factory.EPersonServiceFactory; import org.dspace.eperson.service.EPersonService; +import org.dspace.identifier.IdentifierNotFoundException; +import org.dspace.identifier.IdentifierNotResolvableException; +import org.dspace.identifier.factory.IdentifierServiceFactory; +import org.dspace.identifier.service.IdentifierService; import org.dspace.scripts.DSpaceRunnable; import org.dspace.scripts.configuration.ScriptConfiguration; import org.dspace.utils.DSpace; @@ -45,11 +51,15 @@ public class FileDownloader extends DSpaceRunnable private static final Logger log = LoggerFactory.getLogger(FileDownloader.class); private boolean help = false; private UUID itemUUID; + private int workspaceID; + private String pid; private URI uri; private String epersonMail; private String bitstreamName; private EPersonService epersonService; private ItemService itemService; + private WorkspaceItemService workspaceItemService; + private IdentifierService identifierService; private BitstreamService bitstreamService; private BitstreamFormatService bitstreamFormatService; private final HttpClient httpClient = HttpClient.newBuilder() @@ -85,8 +95,8 @@ public void setup() throws ParseException { throw new ParseException("No URL option has been provided"); } - if (!commandLine.hasOption("i")) { - throw new ParseException("No item option has been provided"); + if (!commandLine.hasOption("i") && !commandLine.hasOption("w") && !commandLine.hasOption("p")) { + throw new ParseException("No item id option has been provided"); } if (getEpersonIdentifier() == null && !commandLine.hasOption("e")) { @@ -96,15 +106,24 @@ public void setup() throws ParseException { this.epersonService = EPersonServiceFactory.getInstance().getEPersonService(); this.itemService = ContentServiceFactory.getInstance().getItemService(); + this.workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService(); this.bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); this.bitstreamFormatService = ContentServiceFactory.getInstance().getBitstreamFormatService(); + this.identifierService = IdentifierServiceFactory.getInstance().getIdentifierService(); try { uri = new URI(commandLine.getOptionValue("u")); } catch (URISyntaxException e) { throw new ParseException("The provided URL is not a valid URL"); } - itemUUID = UUID.fromString(commandLine.getOptionValue("i")); + + if (commandLine.hasOption("i")) { + itemUUID = UUID.fromString(commandLine.getOptionValue("i")); + } else if (commandLine.hasOption("w")) { + workspaceID = Integer.parseInt(commandLine.getOptionValue("w")); + } else if (commandLine.hasOption("p")) { + pid = commandLine.getOptionValue("p"); + } epersonMail = commandLine.getOptionValue("e"); @@ -130,13 +149,10 @@ public void internalRun() throws Exception { Context context = new Context(); context.setCurrentUser(getEperson(context)); - // Download the file from the given url - // and save it to the item with the given UUID - - //find the item by the given uuid - Item item = itemService.find(context, itemUUID); + //find the item by the given id + Item item = findItem(context); if (item == null) { - throw new IllegalArgumentException("No item found for the given UUID"); + throw new IllegalArgumentException("No item found for the given ID"); } HttpRequest request = HttpRequest.newBuilder() @@ -166,6 +182,25 @@ public void internalRun() throws Exception { context.commit(); } + private Item findItem(Context context) throws SQLException { + if (itemUUID != null) { + return itemService.find(context, itemUUID); + } else if (workspaceID != 0) { + return workspaceItemService.find(context, workspaceID).getItem(); + } else { + try { + DSpaceObject dso = identifierService.resolve(context, pid); + if (dso instanceof Item) { + return (Item) dso; + } else { + throw new IllegalArgumentException("The provided identifier does not resolve to an item"); + } + } catch (IdentifierNotFoundException | IdentifierNotResolvableException e) { + throw new IllegalArgumentException(e); + } + } + } + private void saveFileToItem(Context context, Item item, InputStream is, String name) throws SQLException, AuthorizeException, IOException { log.debug("Saving file to item {}", item.getID()); diff --git a/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java b/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java index 78177e77a7ef..848b2d99f7c0 100644 --- a/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/administer/FileDownloaderConfiguration.java @@ -7,6 +7,7 @@ */ package org.dspace.administer; +import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; import org.dspace.scripts.configuration.ScriptConfiguration; @@ -44,14 +45,20 @@ public Options getOptions() { if (options == null) { Options options = new Options(); + OptionGroup ids = new OptionGroup(); options.addOption("h", "help", false, "help"); options.addOption("u", "url", true, "source url"); options.getOption("u").setRequired(true); - options.addOption("i", "item", true, "item uuid"); - options.getOption("i").setRequired(true); + options.addOption("i", "uuid", true, "item uuid"); + options.addOption("w", "wsid", true, "workspace id"); + options.addOption("p", "pid", true, "item pid (e.g. handle or doi)"); + ids.addOption(options.getOption("i")); + ids.addOption(options.getOption("w")); + ids.addOption(options.getOption("p")); + ids.setRequired(true); options.addOption("e", "eperson", true, "eperson email"); options.getOption("e").setRequired(false); diff --git a/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java b/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java index a946533838df..ee75fddc57e4 100644 --- a/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java +++ b/dspace-api/src/test/java/org/dspace/administer/FileDownloaderIT.java @@ -86,7 +86,7 @@ public void testDownloadFileError() throws Exception { assertEquals(oldBitCount, newBitCount); return; } - assertEquals(0, 1); + assertEquals("Not expecting to get here", 0, 1); }