/* * 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.distribution.internal; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.apache.commons.lang3.StringUtils; import org.xwiki.bridge.event.DocumentCreatedEvent; import org.xwiki.bridge.event.DocumentDeletedEvent; import org.xwiki.bridge.event.DocumentUpdatedEvent; import org.xwiki.component.annotation.Component; import org.xwiki.context.Execution; import org.xwiki.context.ExecutionContext; import org.xwiki.extension.Extension; import org.xwiki.extension.LocalExtension; import org.xwiki.extension.distribution.internal.DocumentsModifiedDuringDistributionListener.DocumentStatus.Action; import org.xwiki.extension.xar.internal.handler.XarExtensionPlan; import org.xwiki.job.JobContext; import org.xwiki.job.Request; import org.xwiki.model.reference.DocumentReference; import org.xwiki.observation.AbstractEventListener; import org.xwiki.observation.event.Event; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.doc.XWikiDocument; /** * Gather the pages modified during the Distribution Wizard execution. * * @version $Id: 1e48286d3df3cad78918405ba0580e635a9cdcbe $ * @since 5.4RC1 */ @Component @Named(DocumentsModifiedDuringDistributionListener.NAME) @Singleton // TODO: replace this by the concatenation and analysis of the distribution log public class DocumentsModifiedDuringDistributionListener extends AbstractEventListener { public static final String NAME = "distribution.DocumentsModifiedDuringDistributionListener"; @Inject private Execution execution; @Inject private JobContext jobContext; /** * Map<wiki, Map<document, extension>>. */ private Map<String, Map<DocumentReference, DocumentStatus>> documents = new HashMap<String, Map<DocumentReference, DocumentStatus>>(); public static class DocumentStatus { public enum Action { CREATED, DELETED, MODIFIED } private final DocumentReference reference; private final String previousVersion; private final Action action; private final Extension previousExtension; private final Extension nextExtension; public DocumentStatus(DocumentReference reference, String version, Action action) { this(reference, version, action, null, null); } public DocumentStatus(DocumentReference reference, String previousVersion, Action action, Extension previousExtension, Extension nextExtension) { this.reference = reference; this.previousVersion = previousVersion; this.action = action; this.previousExtension = previousExtension; this.nextExtension = nextExtension; } public DocumentReference getReference() { return this.reference; } public String getPreviousVersion() { return this.previousVersion; } public Action getAction() { return this.action; } public Extension getNextExtension() { return this.nextExtension; } public Extension getPreviousExtension() { return this.previousExtension; } } /** * Setup event listener. */ public DocumentsModifiedDuringDistributionListener() { super("DocumentsModifiedDuringDistributionListener", new DocumentCreatedEvent(), new DocumentDeletedEvent(), new DocumentUpdatedEvent()); } @Override public void onEvent(Event event, Object source, Object data) { checkXARHandler(event, (XWikiDocument) source, (XWikiContext) data); checkDistributionAction(event, (XWikiDocument) source, (XWikiContext) data); } private static Action toAction(Event event) { DocumentStatus.Action action; if (event instanceof DocumentCreatedEvent) { action = Action.CREATED; } else if (event instanceof DocumentDeletedEvent) { action = Action.DELETED; } else { action = Action.MODIFIED; } return action; } private void checkXARHandler(Event event, XWikiDocument document, XWikiContext xcontext) { ExecutionContext context = this.execution.getContext(); if (context != null) { XarExtensionPlan xarExtensionPlan = (XarExtensionPlan) context.getProperty(XarExtensionPlan.CONTEXTKEY_XARINSTALLPLAN); if (xarExtensionPlan != null) { Request request = this.jobContext.getCurrentJob().getRequest(); // It's a job started by the Distribution Wizard if (StringUtils.equals(request.<String> getProperty("context.action"), "distribution")) { String distributionWiki = request.getProperty("context.wiki"); if (distributionWiki != null) { DocumentReference reference = document.getDocumentReferenceWithLocale(); DocumentStatus.Action action = toAction(event); LocalExtension previousExtension = xarExtensionPlan.getPreviousXarExtension(reference); LocalExtension nextExtension = xarExtensionPlan.getNextXarExtension(reference); addDocument(distributionWiki, document, action, previousExtension, nextExtension); } } } } } private void checkDistributionAction(Event event, XWikiDocument document, XWikiContext xcontext) { if (DistributionAction.DISTRIBUTION_ACTION.equals(xcontext.getAction())) { String distributionWiki = xcontext.getOriginalWikiId(); DocumentStatus.Action action = toAction(event); addDocument(distributionWiki, document, action, null, null); } } private void addDocument(String distributionWiki, XWikiDocument document, Action action, LocalExtension previousExtension, LocalExtension nextExtension) { Map<DocumentReference, DocumentStatus> wikiDocuments = this.documents.get(distributionWiki); if (wikiDocuments == null) { wikiDocuments = new HashMap<DocumentReference, DocumentsModifiedDuringDistributionListener.DocumentStatus>(); this.documents.put(distributionWiki, wikiDocuments); } DocumentReference reference = document.getDocumentReferenceWithLocale(); DocumentStatus currentStatus = wikiDocuments.get(reference); String previousVersion; if (currentStatus != null) { previousVersion = currentStatus.getPreviousVersion(); if (action == Action.CREATED) { if (previousVersion != null) { action = Action.MODIFIED; } } else if (action == Action.DELETED) { if (previousVersion == null) { // Back to square one wikiDocuments.remove(reference); return; } } else if (action == Action.MODIFIED) { action = currentStatus.getAction(); } } else { if (action != Action.CREATED) { previousVersion = document.getOriginalDocument().getVersion(); } else { previousVersion = null; } } wikiDocuments.put(reference, new DocumentStatus(reference, previousVersion, action, previousExtension, nextExtension)); } public Map<String, Map<DocumentReference, DocumentStatus>> getDocuments() { return this.documents; } }