From fbcc541bfd6d329e61354a530599d94c30889083 Mon Sep 17 00:00:00 2001 From: Thomas Mortagne <thomas.mortagne@gmail.com> Date: Tue, 4 Oct 2016 10:58:29 +0200 Subject: [PATCH] XWIKI-13766: When uninstalling a XAR pages which are part of several extensions are sometimes selected XWIKI-13764: XAR extension pages index is not properly filled at init --- .../XarInstalledExtensionRepository.java | 34 +++++++++++-- .../handler/XarExtensionHandlerTest.java | 35 +++++++++++-- .../XarInstalledExtensionRepositoryTest.java | 49 +++++++++++++------ .../model/reference/DocumentReference.java | 22 ++++++++- 4 files changed, 114 insertions(+), 26 deletions(-) diff --git a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/main/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepository.java b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/main/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepository.java index 82c027aaf1a..73ba5ec8c2f 100644 --- a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/main/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepository.java +++ b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/main/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepository.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -106,6 +107,12 @@ private void pagesUpdated(ExtensionId extensionId, String namespace, boolean add { XarInstalledExtension installedExtension = (XarInstalledExtension) getInstalledExtension(extensionId); + pagesUpdated(installedExtension, namespace, add); + } + + private void pagesUpdated(XarInstalledExtension installedExtension, String namespace, boolean add) + throws UnsupportedNamespaceException + { if (installedExtension != null) { for (XarEntry xarEntry : installedExtension.getXarPackage().getEntries()) { if (namespace != null) { @@ -165,11 +172,14 @@ void updateCachedXarExtension(ExtensionId extensionId) } } - private void addCacheXarExtension(InstalledExtension installedExtension) throws IOException, XarException + private XarInstalledExtension addCacheXarExtension(InstalledExtension installedExtension) + throws IOException, XarException { XarInstalledExtension xarExtension = new XarInstalledExtension(installedExtension, this); addCachedExtension(xarExtension); + + return xarExtension; } protected void removeCachedXarExtension(ExtensionId extensionId) @@ -186,9 +196,21 @@ private void loadExtensions() for (InstalledExtension localExtension : this.installedRepository.getInstalledExtensions()) { if (localExtension.getType().equalsIgnoreCase(XarExtensionHandler.TYPE)) { try { - addCacheXarExtension(localExtension); + // Add XAR extension to the cache + XarInstalledExtension xarInstalledExtension = addCacheXarExtension(localExtension); + + // Add extension pages to the index + if (xarInstalledExtension.getNamespaces() == null) { + pagesUpdated(xarInstalledExtension, null, true); + } else { + for (String namespace : localExtension.getNamespaces()) { + pagesUpdated(xarInstalledExtension, namespace, true); + } + } } catch (Exception e) { this.logger.error("Failed to parse extension [{}]", localExtension.getId(), e); + + continue; } } } @@ -201,8 +223,12 @@ private void loadExtensions() */ public Collection<XarInstalledExtension> getXarInstalledExtensions(DocumentReference reference) { - Collection<XarInstalledExtension> wikiExtensions = this.documents.get(reference); - Collection<XarInstalledExtension> rootExtensions = this.rootDocuments.get(reference); + Collection<XarInstalledExtension> wikiExtensions = this.documents + .get(reference.getLocale() == null ? new DocumentReference(reference, Locale.ROOT) : reference); + Collection<XarInstalledExtension> rootExtensions = + this.rootDocuments.get(reference.getLocaleDocumentReference().getLocale() == null + ? new LocalDocumentReference(reference.getLocaleDocumentReference(), Locale.ROOT) + : reference.getLocaleDocumentReference()); List<XarInstalledExtension> allExtensions = new ArrayList<>(); diff --git a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/handler/XarExtensionHandlerTest.java b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/handler/XarExtensionHandlerTest.java index e922e339389..0c2ec18536c 100644 --- a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/handler/XarExtensionHandlerTest.java +++ b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/handler/XarExtensionHandlerTest.java @@ -42,6 +42,7 @@ import org.xwiki.extension.repository.InstalledExtensionRepository; import org.xwiki.extension.test.MockitoRepositoryUtilsRule; import org.xwiki.extension.xar.internal.repository.XarInstalledExtension; +import org.xwiki.extension.xar.internal.repository.XarInstalledExtensionRepository; import org.xwiki.job.Job; import org.xwiki.job.JobExecutor; import org.xwiki.logging.LogLevel; @@ -67,6 +68,7 @@ import com.xpn.xwiki.test.MockitoOldcoreRule; import com.xpn.xwiki.util.XWikiStubContextProvider; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; @@ -78,14 +80,16 @@ @AllComponents public class XarExtensionHandlerTest { - private MockitoComponentManagerRule componentManager = new MockitoComponentManagerRule(); + private MockitoOldcoreRule oldcore = new MockitoOldcoreRule(); - private MockitoOldcoreRule oldcore = new MockitoOldcoreRule(this.componentManager); + private MockitoComponentManagerRule componentManager = this.oldcore.getMocker(); @Rule public MockitoRepositoryUtilsRule repositoryUtil = new MockitoRepositoryUtilsRule(this.componentManager, this.oldcore); + private XarInstalledExtensionRepository installedExtensionRepository; + private ExtensionId localXarExtensiontId1; private ExtensionId localXarExtensiontId2; @@ -143,6 +147,9 @@ public void setUp() throws Exception // Get rid of wiki macro listener this.componentManager.<ObservationManager>getInstance(ObservationManager.class) .removeListener("RegisterMacrosOnImportListener"); + + this.installedExtensionRepository = + this.componentManager.getInstance(InstalledExtensionRepository.class, "xar"); } private void mockHasAdminRight(boolean right) throws XWikiException @@ -241,7 +248,7 @@ public void testInstallOnWiki() throws Throwable // install - install(this.localXarExtensiontId1, "wiki", this.contextUser); + XarInstalledExtension xarInstalledExtension = install(this.localXarExtensiontId1, "wiki", this.contextUser); verifyHasAdminRight(2); @@ -295,6 +302,15 @@ public void testInstallOnWiki() throws Throwable Assert.assertFalse("Document wiki:space1.page1 has not been saved in the database", page1.isNew()); + assertEquals(Arrays.asList(xarInstalledExtension), + this.installedExtensionRepository.getXarInstalledExtensions(page1.getDocumentReference())); + assertEquals(Arrays.asList(xarInstalledExtension), + this.installedExtensionRepository.getXarInstalledExtensions(page1.getDocumentReferenceWithLocale())); + assertEquals(0, this.installedExtensionRepository + .getXarInstalledExtensions(new DocumentReference("wiki", "space1", "page1", Locale.ENGLISH)).size()); + assertEquals(0, this.installedExtensionRepository + .getXarInstalledExtensions(new DocumentReference("otherwiki", "space1", "page1")).size()); + // translated.translated DocumentReference translatedReference = new DocumentReference("wiki", "translated", "translated"); XWikiDocument defaultTranslated = @@ -311,6 +327,9 @@ public void testInstallOnWiki() throws Throwable Assert.assertEquals("Wrong content author", this.contextUser, defaultTranslated.getContentAuthorReference()); Assert.assertEquals("Wrong version", "1.1", defaultTranslated.getVersion()); + assertEquals(Arrays.asList(xarInstalledExtension), this.installedExtensionRepository + .getXarInstalledExtensions(defaultTranslated.getDocumentReferenceWithLocale())); + // translated.translated.tr XWikiDocument translated = this.oldcore.getDocuments().get(new DocumentReference(translatedReference, new Locale("tr"))); @@ -326,6 +345,9 @@ public void testInstallOnWiki() throws Throwable Assert.assertEquals("Wrong content author", this.contextUser, translated.getContentAuthorReference()); Assert.assertEquals("Wrong version", "1.1", translated.getVersion()); + assertEquals(Arrays.asList(xarInstalledExtension), + this.installedExtensionRepository.getXarInstalledExtensions(translated.getDocumentReferenceWithLocale())); + // translated.translated.fr XWikiDocument translated2 = this.oldcore.getDocuments().get(new DocumentReference(translatedReference, new Locale("fr"))); @@ -341,6 +363,9 @@ public void testInstallOnWiki() throws Throwable Assert.assertEquals("Wrong content author", this.contextUser, translated2.getContentAuthorReference()); Assert.assertEquals("Wrong version", "1.1", translated2.getVersion()); + assertEquals(Arrays.asList(xarInstalledExtension), + this.installedExtensionRepository.getXarInstalledExtensions(translated2.getDocumentReferenceWithLocale())); + // space.hiddenpage XWikiDocument hiddenpage = this.oldcore.getSpyXWiki() @@ -796,11 +821,13 @@ public void testUninstallFromWiki() throws Throwable // validate + // space.page belong to several extensions XWikiDocument page = this.oldcore.getSpyXWiki().getDocument(new DocumentReference("wiki", "space", "page"), getXWikiContext()); - Assert.assertTrue("Document wiki.space.page has not been removed from the database", page.isNew()); + Assert.assertFalse("Document wiki.space.page has been removed from the database", page.isNew()); + // space1.page1 only belong to the uninstalled extension XWikiDocument page1 = this.oldcore.getSpyXWiki().getDocument(new DocumentReference("wiki", "space1", "page1"), getXWikiContext()); diff --git a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepositoryTest.java b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepositoryTest.java index b9e98b69161..d0c0d7c0ad2 100644 --- a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepositoryTest.java +++ b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-handlers/xwiki-platform-extension-handler-xar/src/test/java/org/xwiki/extension/xar/internal/repository/XarInstalledExtensionRepositoryTest.java @@ -19,7 +19,9 @@ */ package org.xwiki.extension.xar.internal.repository; -import org.junit.Assert; +import java.util.Arrays; +import java.util.Locale; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -28,10 +30,14 @@ import org.xwiki.extension.repository.InstalledExtensionRepository; import org.xwiki.extension.repository.search.SearchException; import org.xwiki.extension.test.MockitoRepositoryUtilsRule; -import org.xwiki.extension.xar.internal.repository.XarInstalledExtensionRepository; +import org.xwiki.model.reference.DocumentReference; import org.xwiki.test.annotation.AllComponents; import org.xwiki.test.mockito.MockitoComponentManagerRule; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + @AllComponents public class XarInstalledExtensionRepositoryTest { @@ -53,22 +59,33 @@ public void setUp() throws Exception @Test public void testInit() throws ResolveException, SearchException { - Assert.assertTrue(this.installedExtensionRepository.countExtensions() == 1); + assertEquals(1, this.installedExtensionRepository.countExtensions()); + + XarInstalledExtension xarInstalledExtension = + this.installedExtensionRepository.resolve(new ExtensionId("xarinstalledextension", "1.0")); + assertNotNull(xarInstalledExtension); + + assertNotNull( + this.installedExtensionRepository.getInstalledExtension(new ExtensionId("xarinstalledextension", "1.0"))); + assertNotNull(this.installedExtensionRepository.getInstalledExtension("xarinstalledextension", null)); + assertNull(this.installedExtensionRepository.getInstalledExtension("notexisting", null)); - Assert - .assertNotNull(this.installedExtensionRepository.resolve(new ExtensionId("xarinstalledextension", "1.0"))); - - Assert.assertNotNull(this.installedExtensionRepository.getInstalledExtension(new ExtensionId( - "xarinstalledextension", "1.0"))); - Assert.assertNotNull(this.installedExtensionRepository.getInstalledExtension("xarinstalledextension", null)); - Assert.assertNull(this.installedExtensionRepository.getInstalledExtension("notexisting", null)); + assertEquals(1, this.installedExtensionRepository.getInstalledExtensions().size()); + assertEquals(1, this.installedExtensionRepository.getInstalledExtensions(null).size()); - Assert.assertEquals(1, this.installedExtensionRepository.getInstalledExtensions().size()); - Assert.assertEquals(1, this.installedExtensionRepository.getInstalledExtensions(null).size()); + assertEquals(1, this.installedExtensionRepository.search("xarinstalledextension", 0, -1).getSize()); + assertEquals(1, this.installedExtensionRepository.search(null, 0, -1).getSize()); + assertEquals(1, this.installedExtensionRepository + .searchInstalledExtensions("xarinstalledextension", null, 0, -1).getSize()); + assertEquals(1, this.installedExtensionRepository.searchInstalledExtensions(null, null, 0, -1).getSize()); - Assert.assertEquals(1, this.installedExtensionRepository.search("xarinstalledextension", 0, -1).getSize()); - Assert.assertEquals(1, this.installedExtensionRepository.search(null, 0, -1).getSize()); - Assert.assertEquals(1, this.installedExtensionRepository.searchInstalledExtensions("xarinstalledextension", null, 0, -1).getSize()); - Assert.assertEquals(1, this.installedExtensionRepository.searchInstalledExtensions(null, null, 0, -1).getSize()); + assertEquals(Arrays.asList(xarInstalledExtension), this.installedExtensionRepository + .getXarInstalledExtensions(new DocumentReference("xwiki", "space", "page"))); + assertEquals(Arrays.asList(xarInstalledExtension), this.installedExtensionRepository + .getXarInstalledExtensions(new DocumentReference("wiki2", "space", "page"))); + assertEquals(Arrays.asList(xarInstalledExtension), this.installedExtensionRepository + .getXarInstalledExtensions(new DocumentReference("xwiki", "space", "page", Locale.ROOT))); + assertEquals(0, this.installedExtensionRepository + .getXarInstalledExtensions(new DocumentReference("xwiki", "space", "page", Locale.ENGLISH)).size()); } } diff --git a/xwiki-platform-core/xwiki-platform-model/src/main/java/org/xwiki/model/reference/DocumentReference.java b/xwiki-platform-core/xwiki-platform-model/src/main/java/org/xwiki/model/reference/DocumentReference.java index 58939d20c03..84557f8b4ef 100644 --- a/xwiki-platform-core/xwiki-platform-model/src/main/java/org/xwiki/model/reference/DocumentReference.java +++ b/xwiki-platform-core/xwiki-platform-model/src/main/java/org/xwiki/model/reference/DocumentReference.java @@ -52,6 +52,11 @@ public class DocumentReference extends EntityReference */ static final String LOCALE = "LOCALE"; + /** + * Cache the {@link LocalDocumentReference} corresponding to this {@link DocumentReference}. + */ + private LocalDocumentReference localDocumentReference; + /** * Special constructor that transforms a generic entity reference into a {@link DocumentReference}. It checks the * validity of the passed reference (ie correct type and correct parent). @@ -126,8 +131,8 @@ public DocumentReference(String wikiName, String spaceName, String pageName, Loc */ public DocumentReference(String wikiName, String spaceName, String pageName, String language) { - this(pageName, new SpaceReference(spaceName, new WikiReference(wikiName)), (language == null) ? null - : new Locale(language)); + this(pageName, new SpaceReference(spaceName, new WikiReference(wikiName)), + (language == null) ? null : new Locale(language)); } /** @@ -320,6 +325,19 @@ public DocumentReference replaceParent(EntityReference oldParent, EntityReferenc return new DocumentReference(this, oldParent, newParent); } + /** + * @return the {@link LocalDocumentReference} corresponding to this {@link DocumentReference} + * @since 8.3 + */ + public LocalDocumentReference getLocaleDocumentReference() + { + if (this.localDocumentReference == null) { + this.localDocumentReference = new LocalDocumentReference(this); + } + + return this.localDocumentReference; + } + @Override public String toString() { -- GitLab