Skip to content

Commit 2419fa0

Browse files
committed
VSB-TUO/Fix: delete the half built submission when embargo metadata is refused
The batch import path completes its context in a finally block, so a workspace item left behind by a refused package was committed as an orphan submission with its bitstreams. The command line path aborts its context and was never affected. Mirrors the cleanup the install failure path in the same method already does.
1 parent c5fe8e4 commit 2419fa0

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

dspace-api/src/main/java/org/dspace/app/itemimport/ItemImportServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,11 @@ protected Item addItem(Context c, List<Collection> mycollections, String path,
819819
try {
820820
processEmbargoMetadata(c, myitem);
821821
} catch (EmbargoMetadataException e) {
822+
// The half built submission goes with the failure: the batch import path completes its context
823+
// in a finally block, so anything left behind here would be committed as an orphan.
824+
if (wi != null) {
825+
workspaceItemService.deleteAll(c, wi);
826+
}
822827
// The operator needs the package directory, not the item id: the package is what they fix.
823828
throw new EmbargoMetadataException("SAF package '" + itemname + "': " + e.getMessage(), e);
824829
}

dspace-api/src/test/java/org/dspace/app/itemimport/EmbargoImportIT.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.time.LocalDate;
2626
import java.time.YearMonth;
2727
import java.time.ZoneOffset;
28+
import java.util.Collections;
2829
import java.util.Date;
2930
import java.util.Iterator;
3031
import java.util.List;
@@ -35,6 +36,7 @@
3536

3637
import org.apache.commons.io.file.PathUtils;
3738
import org.dspace.AbstractIntegrationTestWithDatabase;
39+
import org.dspace.app.itemimport.factory.ItemImportServiceFactory;
3840
import org.dspace.authorize.ResourcePolicy;
3941
import org.dspace.authorize.factory.AuthorizeServiceFactory;
4042
import org.dspace.authorize.service.AuthorizeService;
@@ -50,6 +52,7 @@
5052
import org.dspace.content.factory.ContentServiceFactory;
5153
import org.dspace.content.service.ItemService;
5254
import org.dspace.content.service.MetadataSchemaService;
55+
import org.dspace.content.service.WorkspaceItemService;
5356
import org.dspace.core.Constants;
5457
import org.dspace.eperson.EPerson;
5558
import org.dspace.eperson.Group;
@@ -90,6 +93,8 @@ public class EmbargoImportIT extends AbstractIntegrationTestWithDatabase {
9093
private static final String EMBARGO_POLICY_NAME = "embargo";
9194

9295
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
96+
private WorkspaceItemService workspaceItemService =
97+
ContentServiceFactory.getInstance().getWorkspaceItemService();
9398
private ResourcePolicyService resourcePolicyService =
9499
AuthorizeServiceFactory.getInstance().getResourcePolicyService();
95100
private AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
@@ -606,6 +611,37 @@ public void testBlankEmbargoEndIsRefused() throws Exception {
606611
assertBrokenEmbargoPackageIsRefused("", "an empty dc.date.embargoend");
607612
}
608613

614+
/**
615+
* Verifies that a refused package leaves no workspace item behind. The command line path aborts its
616+
* context, but the batch import path completes its own in a finally block, so a half built submission
617+
* left here would be committed as an orphan submission with its bitstreams.
618+
*
619+
* <p>{@code addItem} is driven directly because that is the unit that has to clean up after itself; going
620+
* through the script would only exercise the caller that aborts anyway.</p>
621+
*/
622+
@Test
623+
public void testRefusedPackageLeavesNoWorkspaceItem() throws Exception {
624+
Path itemDir = safPackage("embargoedAccess", "not-a-date", "TEST CONTENT ORPHAN");
625+
ItemImportServiceImpl importService =
626+
(ItemImportServiceImpl) ItemImportServiceFactory.getInstance().getItemImportService();
627+
importService.setTest(false);
628+
629+
context.turnOffAuthorisationSystem();
630+
try {
631+
importService.addItem(context, Collections.singletonList(collection),
632+
itemDir.getParent().toString(), itemDir.getFileName().toString(), null, false);
633+
fail("an unparseable dc.date.embargoend has to be reported instead of importing the package");
634+
} catch (EmbargoMetadataException expected) {
635+
// the failure the operator is given
636+
} finally {
637+
context.restoreAuthSystemState();
638+
}
639+
640+
assertTrue("the refused package must leave no workspace item behind, the batch import path would"
641+
+ " commit it as an orphan submission",
642+
workspaceItemService.findByCollection(context, collection).isEmpty());
643+
}
644+
609645
/**
610646
* Verifies that a bare year keeps the day {@code DCDate} mapped it to, 1 January; reading it as
611647
* 31 December would extend embargoes that repositories already live with.

0 commit comments

Comments
 (0)