/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.extension.xar.internal.handler; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xwiki.component.manager.ComponentLookupException; import org.xwiki.extension.ExtensionException; import org.xwiki.extension.ExtensionId; import org.xwiki.extension.InstalledExtension; import org.xwiki.extension.LocalExtension; import org.xwiki.extension.job.plan.ExtensionPlan; import org.xwiki.extension.job.plan.ExtensionPlanAction; import org.xwiki.extension.job.plan.ExtensionPlanAction.Action; import org.xwiki.extension.repository.InstalledExtensionRepository; import org.xwiki.extension.repository.LocalExtensionRepository; import org.xwiki.extension.xar.internal.handler.packager.Packager; import org.xwiki.extension.xar.internal.repository.XarInstalledExtension; import org.xwiki.filter.FilterException; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.LocalDocumentReference; import org.xwiki.model.reference.WikiReference; import org.xwiki.xar.XarEntry; import org.xwiki.xar.XarException; import org.xwiki.xar.XarPackage; import com.xpn.xwiki.doc.XWikiDocument; /** * @version $Id: b3ea2a99ad363b725f2a192581f8ca6d4e48de33 $ * @since 5.4M1 */ public class XarExtensionPlan implements Closeable { public static final String CONTEXTKEY_XARINSTALLPLAN = "extension.xar.installplan"; /** * Logging helper object. */ private static final Logger LOGGER = LoggerFactory.getLogger(XarExtensionPlan.class); public final Map<String, Map<XarEntry, XarExtensionPlanEntry>> previousXAREntries; /** * Map<namespace, > */ public final Map<String, Map<XarEntry, LocalExtension>> nextXAREntries; public XarExtensionPlan(ExtensionPlan plan, InstalledExtensionRepository xarRepository, LocalExtensionRepository localReposirory) throws ExtensionException, XarException, IOException { this.previousXAREntries = new HashMap<>(); this.nextXAREntries = new HashMap<>(); Map<ExtensionId, XarExtensionPlanEntry> planEntry = new HashMap<>(); for (ExtensionPlanAction action : plan.getActions()) { if (action.getExtension().getType().equals(XarExtensionHandler.TYPE)) { // Get previous entries Collection<InstalledExtension> previousExtensions = action.getPreviousExtensions(); for (InstalledExtension previousExtension : previousExtensions) { if (previousExtension != null && previousExtension.getType().equals(XarExtensionHandler.TYPE)) { XarInstalledExtension previousXARExtension = (XarInstalledExtension) xarRepository.getInstalledExtension(previousExtension.getId()); if (previousXARExtension == null) { // Very weird situation but let's be safe LOGGER.error("Installed extension [{}] is not properly registered in" + " the virtual XAR installed extensions repository", previousExtension); continue; } XarExtensionPlanEntry xarPlanEntry = planEntry.get(previousXARExtension.getId()); if (xarPlanEntry == null) { xarPlanEntry = new XarExtensionPlanEntry(previousXARExtension, previousXARExtension.getXarPackage()); planEntry.put(previousXARExtension.getId(), xarPlanEntry); } for (XarEntry entry : previousXARExtension.getXarPackage().getEntries()) { String wiki; try { wiki = XarHandlerUtils.getWikiFromNamespace(action.getNamespace()); } catch (UnsupportedNamespaceException e) { throw new ExtensionException("Failed to extract wiki id from namespace", e); } Map<XarEntry, XarExtensionPlanEntry> pages = previousXAREntries.get(wiki); if (pages == null) { pages = new HashMap<>(); this.previousXAREntries.put(wiki, pages); } pages.put(entry, xarPlanEntry); } } } // Get new entries LocalExtension nextExtension = action.getAction() != Action.UNINSTALL && action.getExtension() != null ? localReposirory.getLocalExtension(action.getExtension().getId()) : null; if (nextExtension != null) { try { Collection<XarEntry> entries = XarPackage.getEntries(new File(nextExtension.getFile().getAbsolutePath())); for (XarEntry entry : entries) { String wiki; try { wiki = XarHandlerUtils.getWikiFromNamespace(action.getNamespace()); } catch (UnsupportedNamespaceException e) { throw new ExtensionException("Failed to extract wiki id from namespace", e); } Map<XarEntry, LocalExtension> pages = this.nextXAREntries.get(wiki); if (pages == null) { pages = new HashMap<>(); this.nextXAREntries.put(wiki, pages); } pages.put(entry, nextExtension); } } catch (Exception e) { LOGGER.error("Failed to parse extension file [{}]", nextExtension.getFile().getAbsolutePath(), e); } } } } } public XarExtensionPlanEntry getPreviousXarExtensionPlanEntry(DocumentReference documentReference) { String wiki = documentReference.getWikiReference().getName(); LocalDocumentReference localDocumentReference = new LocalDocumentReference(documentReference); return getPreviousXarExtensionPlanEntry(wiki, localDocumentReference); } public XarExtensionPlanEntry getPreviousXarExtensionPlanEntry(String wiki, LocalDocumentReference localDocumentReference) { XarEntry xarEntry = new XarEntry(localDocumentReference); XarExtensionPlanEntry planEntry = null; Map<XarEntry, XarExtensionPlanEntry> wikiEntry = this.previousXAREntries.get(wiki); if (wikiEntry != null) { planEntry = wikiEntry.get(xarEntry); } if (planEntry == null) { wikiEntry = this.previousXAREntries.get(null); if (wikiEntry != null) { planEntry = wikiEntry.get(xarEntry); } } return planEntry; } public XarInstalledExtension getPreviousXarExtension(DocumentReference documentReference) { String wiki = documentReference.getWikiReference().getName(); LocalDocumentReference localDocumentReference = new LocalDocumentReference(documentReference); return getPreviousXarExtension(wiki, localDocumentReference); } public XarInstalledExtension getPreviousXarExtension(String wiki, LocalDocumentReference localDocumentReference) { XarExtensionPlanEntry entry = getPreviousXarExtensionPlanEntry(wiki, localDocumentReference); return entry != null ? entry.extension : null; } public LocalExtension getNextXarExtension(DocumentReference documentReference) { WikiReference wikiReference = documentReference.getWikiReference(); LocalDocumentReference localDocumentReference = new LocalDocumentReference(documentReference); return getNextXarExtension(wikiReference.getName(), localDocumentReference); } public LocalExtension getNextXarExtension(String wiki, LocalDocumentReference localDocumentReference) { XarEntry xarEntry = new XarEntry(localDocumentReference); LocalExtension nextExtension = null; Map<XarEntry, LocalExtension> wikiEntry = this.nextXAREntries.get(wiki); if (wikiEntry != null) { nextExtension = wikiEntry.get(xarEntry); } if (nextExtension == null) { wikiEntry = this.nextXAREntries.get(null); if (wikiEntry != null) { nextExtension = wikiEntry.get(xarEntry); } } return nextExtension; } public XWikiDocument getPreviousXWikiDocument(DocumentReference documentReference, Packager packager) throws FilterException, ComponentLookupException, IOException { WikiReference wikiReference = documentReference.getWikiReference(); LocalDocumentReference localDocumentReference = new LocalDocumentReference(documentReference); return getPreviousXWikiDocument(wikiReference, localDocumentReference, packager); } public XWikiDocument getPreviousXWikiDocument(WikiReference wikiReference, LocalDocumentReference localReference, Packager packager) throws FilterException, ComponentLookupException, IOException { XarExtensionPlanEntry xarPlanEntry = getPreviousXarExtensionPlanEntry(wikiReference.getName(), localReference); return xarPlanEntry != null ? packager.getXWikiDocument(wikiReference, localReference, xarPlanEntry.xarFile) : null; } @Override public void close() throws IOException { for (Map<XarEntry, XarExtensionPlanEntry> wikiEntry : this.previousXAREntries.values()) { for (XarExtensionPlanEntry entry : wikiEntry.values()) { entry.close(); } } } public boolean containsNewPage(DocumentReference documentReference) { WikiReference wikiReference = documentReference.getWikiReference(); LocalDocumentReference localDocumentReference = new LocalDocumentReference(documentReference); return containsNewPage(wikiReference, localDocumentReference); } public boolean containsNewPage(WikiReference wikiReference, LocalDocumentReference localDocumentReference) { return getNextXarExtension(wikiReference.getName(), localDocumentReference) != null; } }