From fd844b56b3cd69651144f2be3f35800db5c2b405 Mon Sep 17 00:00:00 2001 From: Thomas Mortagne Date: Tue, 16 Jul 2024 12:28:39 +0200 Subject: [PATCH] XWIKI-22328: IllegalStateException when installing extension which replace an extension installed on several namespace --- .../job/internal/AbstractInstallPlanJob.java | 13 +++--- .../job/internal/InstallPlanJobTest.java | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/main/java/org/xwiki/extension/job/internal/AbstractInstallPlanJob.java b/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/main/java/org/xwiki/extension/job/internal/AbstractInstallPlanJob.java index 41c0347819..01d59f4790 100644 --- a/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/main/java/org/xwiki/extension/job/internal/AbstractInstallPlanJob.java +++ b/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/main/java/org/xwiki/extension/job/internal/AbstractInstallPlanJob.java @@ -1076,7 +1076,7 @@ private ModifableExtensionPlanNode installExtension(Extension sourceExtension, E this.progressManager.startStep(this); - // Find all existing versions of the extension + // Find extension colliding with the extension being installed Set previousExtensions = getReplacedInstalledExtensions(rewrittenExtension, namespace); this.progressManager.endStep(this); @@ -1092,19 +1092,22 @@ private ModifableExtensionPlanNode installExtension(Extension sourceExtension, E if (namespace == null && previousExtension.getNamespaces() != null) { for (String previousNamespace : previousExtension.getNamespaces()) { uninstallExtension(previousExtension, previousNamespace, this.extensionTree, false); - it.remove(); - // Remember replaced extension for through the whole job + // Remember replaced extensions through the whole job this.extensionsCache.addPrevious(previousExtension.getId().getId(), previousNamespace); } + + // This is an uninstall/install situation (and not an upgrade or downgrade), so we remove this + // extension from the previous ones + it.remove(); } else { uninstallExtension(previousExtension, namespace, this.extensionTree, false); - // Remember replaced extension for through the whole job + // Remember replaced extensions through the whole job this.extensionsCache.addPrevious(previousExtension.getId().getId(), namespace); } } else { - // Remember replaced extension for through the whole job + // Remember replaced extensions through the whole job this.extensionsCache.addPrevious(previousExtension.getId().getId(), namespace); } } diff --git a/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/test/java/org/xwiki/extension/job/internal/InstallPlanJobTest.java b/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/test/java/org/xwiki/extension/job/internal/InstallPlanJobTest.java index 6b741ef553..a2a94b7708 100644 --- a/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/test/java/org/xwiki/extension/job/internal/InstallPlanJobTest.java +++ b/xwiki-commons-core/xwiki-commons-extension/xwiki-commons-extension-api/src/test/java/org/xwiki/extension/job/internal/InstallPlanJobTest.java @@ -404,6 +404,47 @@ void testInstallOnNamespaceThenOnRoot() throws Throwable assertEquals(0, node.getChildren().size()); } + @Test + void testInstallOnSeveralNamespacesThenOnRoot() throws Throwable + { + // Install 1.0 on namespace1 and namespace2 + install(TestResources.REMOTE_UPGRADE10_ID, "namespace1"); + install(TestResources.REMOTE_UPGRADE10_ID, "namespace2"); + + // Move 1.0 on root + ExtensionPlan plan = installPlan(TestResources.REMOTE_UPGRADE10_ID); + + assertEquals(3, plan.getTree().size()); + + Iterator it = plan.getTree().iterator(); + + ExtensionPlanNode node = it.next(); + ExtensionPlanAction action = node.getAction(); + assertEquals(TestResources.REMOTE_UPGRADE10_ID, action.getExtension().getId()); + assertEquals(Action.UNINSTALL, action.getAction()); + assertEquals(1, action.getPreviousExtensions().size()); + assertEquals(TestResources.REMOTE_UPGRADE10_ID, action.getPreviousExtension().getId()); + assertEquals("namespace1", action.getNamespace()); + assertEquals(0, node.getChildren().size()); + + node = it.next(); + action = node.getAction(); + assertEquals(TestResources.REMOTE_UPGRADE10_ID, action.getExtension().getId()); + assertEquals(Action.UNINSTALL, action.getAction()); + assertEquals(1, action.getPreviousExtensions().size()); + assertEquals(TestResources.REMOTE_UPGRADE10_ID, action.getPreviousExtension().getId()); + assertEquals("namespace2", action.getNamespace()); + assertEquals(0, node.getChildren().size()); + + node = it.next(); + action = node.getAction(); + assertEquals(TestResources.REMOTE_UPGRADE10_ID, action.getExtension().getId()); + assertEquals(Action.INSTALL, action.getAction()); + assertEquals(0, action.getPreviousExtensions().size()); + assertNull(action.getNamespace()); + assertEquals(0, node.getChildren().size()); + } + @Test void testInstallOnNamespaceThenUnpgradeOnRoot() throws Throwable {