From c06a82a0dee410f3696b93d22319f99e23560d49 Mon Sep 17 00:00:00 2001 From: Gavin Cornwell Date: Tue, 19 Jun 2007 21:30:52 +0000 Subject: [PATCH] Refactored links management UI following link validation service API changes git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6024 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../messages/action-config.properties | 1 + .../workflow/wcm-workflow-messages.properties | 2 + config/alfresco/workflow/wcmWorkflowModel.xml | 5 + .../linkvalidation/LinkValidationAction.java | 92 +++++++++++--- .../linkvalidation/LinkValidationReport.java | 119 +++++++++++++++--- .../org/alfresco/model/WCMWorkflowModel.java | 1 + .../repo/avm/wf/AVMSubmitLinkChecker.java | 43 +++---- 7 files changed, 203 insertions(+), 60 deletions(-) diff --git a/config/alfresco/messages/action-config.properties b/config/alfresco/messages/action-config.properties index 24afb97244..a40de555ec 100644 --- a/config/alfresco/messages/action-config.properties +++ b/config/alfresco/messages/action-config.properties @@ -136,4 +136,5 @@ copy-to-web-project.description=This will copy the matched item to a folder in a avm-link-validation.title=Performs a link validation check. avm-link-validation.description=Performs a link validation check. avm-link-validation.monitor.display-label=The status object used to determine progress +avm-link-validation.compare-to-staging.display-label=Determines whether the link check should use the corresponding staging area for comparison diff --git a/config/alfresco/workflow/wcm-workflow-messages.properties b/config/alfresco/workflow/wcm-workflow-messages.properties index cf6e0db582..46659a95ff 100644 --- a/config/alfresco/workflow/wcm-workflow-messages.properties +++ b/config/alfresco/workflow/wcm-workflow-messages.properties @@ -59,6 +59,8 @@ wcmwf_workflowmodel.property.wcmwf_launchDate.title=Launch Date wcmwf_workflowmodel.property.wcmwf_launchDate.description=Date the content in the submission should be committed wcmwf_workflowmodel.property.wcmwf_validateLinks.title=Validate Links wcmwf_workflowmodel.property.wcmwf_validateLinks.description=Whether links should be verified before entering the review cycle +wcmwf_workflowmodel.property.wcmwf_webapp.title=Webapp +wcmwf_workflowmodel.property.wcmwf_webapp.description=The webapp within the workflow store to check links for wcmwf_workflowmodel.property.wcmwf_reviewerCnt.title=Total Reviewed wcmwf_workflowmodel.property.wcmwf_reviewerCnt.description=Count of people who reviewed wcmwf_workflowmodel.property.wcmwf_approveCnt.title=Total Approved diff --git a/config/alfresco/workflow/wcmWorkflowModel.xml b/config/alfresco/workflow/wcmWorkflowModel.xml index e21295d3c2..231de5dabb 100644 --- a/config/alfresco/workflow/wcmWorkflowModel.xml +++ b/config/alfresco/workflow/wcmWorkflowModel.xml @@ -228,6 +228,11 @@ Determines whether links should be verified before entering the review cycle d:boolean + + Webapp + The webapp within the workflow store to check links for + d:text + diff --git a/source/java/org/alfresco/linkvalidation/LinkValidationAction.java b/source/java/org/alfresco/linkvalidation/LinkValidationAction.java index e27485810b..0f678b333a 100644 --- a/source/java/org/alfresco/linkvalidation/LinkValidationAction.java +++ b/source/java/org/alfresco/linkvalidation/LinkValidationAction.java @@ -27,6 +27,7 @@ package org.alfresco.linkvalidation; import java.util.List; +import org.alfresco.config.JNDIConstants; import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; import org.alfresco.repo.avm.AVMNodeConverter; @@ -51,6 +52,7 @@ public class LinkValidationAction extends ActionExecuterAbstractBase { public static final String NAME = "avm-link-validation"; + public static final String PARAM_COMPARE_TO_STAGING = "compare-to-staging"; public static final String PARAM_MONITOR = "monitor"; private LinkValidationService linkValidationService; @@ -81,6 +83,8 @@ public class LinkValidationAction extends ActionExecuterAbstractBase @Override protected void addParameterDefinitions(List paramList) { + paramList.add(new ParameterDefinitionImpl(PARAM_COMPARE_TO_STAGING, DataTypeDefinition.BOOLEAN, + false, getParamDisplayLabel(PARAM_COMPARE_TO_STAGING))); paramList.add(new ParameterDefinitionImpl(PARAM_MONITOR, DataTypeDefinition.ANY, false, getParamDisplayLabel(PARAM_MONITOR))); } @@ -88,38 +92,86 @@ public class LinkValidationAction extends ActionExecuterAbstractBase @Override protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { - // get the store to check the links for (is represented by the actioned upon node) + // get the webapp path to check the links for (is represented by the actioned upon node) Pair avmVersionPath = AVMNodeConverter.ToAVMVersionPath(actionedUponNodeRef); - String path = avmVersionPath.getSecond(); + String webappPath = avmVersionPath.getSecond(); // get store name and path parts. - String [] storePath = path.split(":"); - if (storePath.length != 2) + String [] webappParts = webappPath.split(":"); + if (webappParts.length != 2) { - throw new AVMSyncException("Malformed source path: " + path); + throw new AVMSyncException("Malformed source path: " + webappPath); + } + + // extract the store name + String storeName = actionedUponNodeRef.getStoreRef().getIdentifier(); + + // extract the webapp name + String webappName = webappPath.substring(webappPath.lastIndexOf("/")+1); + + // get the compare to staging flag + String destWebappPath = null; + Boolean compareToStaging = (Boolean)action.getParameterValue(PARAM_COMPARE_TO_STAGING); + if (compareToStaging != null) + { + if (compareToStaging.booleanValue()) + { + // get the corresponding path in the staging area for the given source + PropertyValue val = this.avmService.getStoreProperty(storeName, SandboxConstants.PROP_WEBSITE_NAME); + if (val != null) + { + String stagingStoreName = val.getStringValue(); + destWebappPath = stagingStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW + "/" + + JNDIConstants.DIR_DEFAULT_APPBASE + "/" + webappName; + } + } } - // extract the store name - String store = storePath[0]; - // get the monitor object HrefValidationProgress monitor = (HrefValidationProgress)action.getParameterValue(PARAM_MONITOR); if (logger.isDebugEnabled()) - logger.debug("Performing link validation check for store '" + store + "'"); + { + if (destWebappPath == null) + { + logger.debug("Performing link validation check for webapp '" + webappPath + "'"); + } + else + { + logger.debug("Performing link validation check for webapp '" + webappPath + "', comparing against '" + + destWebappPath + "'"); + } + } LinkValidationReport report = null; try { - // firstly call updateHrefInfo to scan the whole store for broken links - // NOTE: currently this is NOT done incrementally - this.linkValidationService.updateHrefInfo(store, false, 10000, 30000, 5, monitor); + // determine which API to call depending on whether there is a destination webapp present + if (destWebappPath != null) + { + // get the object to represent the broken files + HrefDifference hdiff = this.linkValidationService.getHrefDifference(webappPath, destWebappPath, + 10000, 30000, 5, monitor); + + // get the broken files created due to deletions and new/modified files + HrefManifest brokenByDelete = this.linkValidationService.getHrefManifestBrokenByDelete(hdiff); + HrefManifest brokenByNewOrMod = this.linkValidationService.getHrefManifestBrokenByNewOrMod(hdiff); + + // create the report object using the 2 sets of results + report = new LinkValidationReport(storeName, webappName, monitor, brokenByDelete, brokenByNewOrMod); + } + else + { + // firstly call updateHrefInfo to scan the whole store for broken links + // NOTE: currently this is NOT done incrementally + this.linkValidationService.updateHrefInfo(webappPath, false, 10000, 30000, 5, monitor); - // retrieve the manifest of all the broken links and files - List manifests = this.linkValidationService.getBrokenHrefManifestEntries(store); - - // create the report object using the link check results - report = new LinkValidationReport(monitor, manifests); + // retrieve the manifest of all the broken links and files for the webapp + List manifests = this.linkValidationService.getBrokenHrefManifestEntries(webappPath); + + // create the report object using the link check results + report = new LinkValidationReport(storeName, webappName, monitor, manifests); + } } catch (Throwable err) { @@ -129,15 +181,15 @@ public class LinkValidationAction extends ActionExecuterAbstractBase } else { - report = new LinkValidationReport(err); + report = new LinkValidationReport(storeName, webappName, err); } logger.error("Link Validation Error: ", err); } // store the report as a store property on the store we ran the link check on - this.avmService.deleteStoreProperty(store, SandboxConstants.PROP_LINK_VALIDATION_REPORT); - this.avmService.setStoreProperty(store, SandboxConstants.PROP_LINK_VALIDATION_REPORT, + this.avmService.deleteStoreProperty(storeName, SandboxConstants.PROP_LINK_VALIDATION_REPORT); + this.avmService.setStoreProperty(storeName, SandboxConstants.PROP_LINK_VALIDATION_REPORT, new PropertyValue(DataTypeDefinition.ANY, report)); } } diff --git a/source/java/org/alfresco/linkvalidation/LinkValidationReport.java b/source/java/org/alfresco/linkvalidation/LinkValidationReport.java index 3b18c8521f..f745702172 100755 --- a/source/java/org/alfresco/linkvalidation/LinkValidationReport.java +++ b/source/java/org/alfresco/linkvalidation/LinkValidationReport.java @@ -27,10 +27,13 @@ package org.alfresco.linkvalidation; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.alfresco.util.ParameterCheck; + /** * Object representing the result of a link validation action being executed. * This object combines the results of the multiple service calls required to @@ -44,10 +47,13 @@ import java.util.Map; */ public class LinkValidationReport implements Serializable { + private String store; + private String webapp; private int numberFilesChecked = -1; private int numberLinksChecked = -1; private int numberBrokenLinks = -1; private boolean successful = true; + private Date completedAt; private Throwable error; private List brokenFiles; @@ -56,46 +62,101 @@ public class LinkValidationReport implements Serializable private static final long serialVersionUID = 7562964706845609991L; /** - * Constructs a link validation report from the results of a check + * Constructs a link validation report from the results of a check of the + * staging area. * + * @param store The store the link check was run against + * @param webapp The webapp within the store the check was run against * @param status The object containing status i.e. file, link counts and the list * of files containing broken links * @param manifests The manifest of broken links and files */ - public LinkValidationReport(HrefValidationProgress status, List manifests) + public LinkValidationReport(String store, String webapp, HrefValidationProgress status, + List manifests) { + this.store = store; + this.webapp = webapp; + this.completedAt = new Date(); this.numberFilesChecked = status.getFileUpdateCount(); this.numberLinksChecked = status.getUrlUpdateCount(); - // create a list of broken files + // create list and map this.brokenFiles = new ArrayList(manifests.size()); - - // create a map of broken links by file. this.brokenLinksByFile = new HashMap(manifests.size()); - // build the required list and maps - for (HrefManifestEntry manifest : manifests) - { - String fileName = manifest.getFileName(); - this.brokenFiles.add(fileName); - this.brokenLinksByFile.put(fileName, manifest); - this.numberBrokenLinks = this.numberBrokenLinks + manifest.getHrefs().size(); - } + // build the required list and map + storeBrokenFiles(manifests); + } + + /** + * Constructs a link validation report from the results of a comparison check + * between the staging area and another sandbox i.e. an authors sandbox or a + * workflow sandbox. + * + * @param store The store the link check was run against + * @param webapp The webapp within the store the check was run against + * @param status The object containing status i.e. file, link counts and the list + * of files containing broken links + * @param brokenByDelete Object representing the broken links caused by deleted assets + * @param brokenByNewOrMod Object representing the broken links caused by new or + * modified assets + */ + public LinkValidationReport(String store, String webapp, HrefValidationProgress status, + HrefManifest brokenByDelete, HrefManifest brokenByNewOrMod) + { + this.store = store; + this.webapp = webapp; + this.completedAt = new Date(); + this.numberFilesChecked = status.getFileUpdateCount(); + this.numberLinksChecked = status.getUrlUpdateCount(); + + // get the lists of broken files + List byDelete = brokenByDelete.getManifestEntries(); + List byNewOrMod = brokenByNewOrMod.getManifestEntries(); + + // create list and map + this.brokenFiles = new ArrayList(byDelete.size() + byNewOrMod.size()); + this.brokenLinksByFile = new HashMap( + byDelete.size() + byNewOrMod.size()); + + // build the required list and map + storeBrokenFiles(byDelete); + storeBrokenFiles(byNewOrMod); } /** * Constructs a link validation report from an error that occurred - * + * + * @param store The store the link check was run against + * @param webapp The webapp within the store the check was run against * @param error The error that caused the link check to fail */ - public LinkValidationReport(Throwable error) + public LinkValidationReport(String store, String webapp, Throwable error) { + this.store = store; + this.webapp = webapp; + this.completedAt = new Date(); this.setError(error); this.brokenFiles = Collections.emptyList(); this.brokenLinksByFile = Collections.emptyMap(); } + public String getStore() + { + return this.store; + } + + public String getWebapp() + { + return this.webapp; + } + + public Date getCheckCompletedAt() + { + return this.completedAt; + } + public int getNumberFilesChecked() { return this.numberFilesChecked; @@ -149,6 +210,34 @@ public class LinkValidationReport implements Serializable { return this.error; } + + @Override + public String toString() + { + StringBuilder buffer = new StringBuilder(super.toString()); + buffer.append(" (store=").append(this.store); + buffer.append(" webapp=").append(this.webapp); + buffer.append(" error=").append(this.error).append(")"); + return buffer.toString(); + } + + /** + * Stores the given list of manifest entries in the internal lists and maps + * + * @param manifests Manifest entries to store + */ + protected void storeBrokenFiles(List manifests) + { + ParameterCheck.mandatory("manifests", manifests); + + for (HrefManifestEntry manifest : manifests) + { + String fileName = manifest.getFileName(); + this.brokenFiles.add(fileName); + this.brokenLinksByFile.put(fileName, manifest); + this.numberBrokenLinks = this.numberBrokenLinks + manifest.getHrefs().size(); + } + } } diff --git a/source/java/org/alfresco/model/WCMWorkflowModel.java b/source/java/org/alfresco/model/WCMWorkflowModel.java index 24584a1e99..01c63061fe 100644 --- a/source/java/org/alfresco/model/WCMWorkflowModel.java +++ b/source/java/org/alfresco/model/WCMWorkflowModel.java @@ -37,5 +37,6 @@ public interface WCMWorkflowModel static final QName PROP_LABEL = QName.createQName(NamespaceService.WCMWF_MODEL_1_0_URI, "label"); static final QName PROP_LAUNCH_DATE = QName.createQName(NamespaceService.WCMWF_MODEL_1_0_URI, "launchDate"); static final QName PROP_VALIDATE_LINKS = QName.createQName(NamespaceService.WCMWF_MODEL_1_0_URI, "validateLinks"); + static final QName PROP_WEBAPP = QName.createQName(NamespaceService.WCMWF_MODEL_1_0_URI, "webapp"); static final QName ASSOC_WEBPROJECT = QName.createQName(NamespaceService.WCMWF_MODEL_1_0_URI, "webproject"); } diff --git a/source/java/org/alfresco/repo/avm/wf/AVMSubmitLinkChecker.java b/source/java/org/alfresco/repo/avm/wf/AVMSubmitLinkChecker.java index f43f3df12b..cccf379e06 100644 --- a/source/java/org/alfresco/repo/avm/wf/AVMSubmitLinkChecker.java +++ b/source/java/org/alfresco/repo/avm/wf/AVMSubmitLinkChecker.java @@ -31,7 +31,6 @@ import org.alfresco.config.JNDIConstants; import org.alfresco.linkvalidation.HrefValidationProgress; import org.alfresco.linkvalidation.LinkValidationAction; import org.alfresco.linkvalidation.LinkValidationReport; -import org.alfresco.linkvalidation.LinkValidationService; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.workflow.jbpm.JBPMNode; @@ -41,8 +40,6 @@ import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.util.Pair; import org.apache.log4j.Logger; import org.jbpm.graph.exe.ExecutionContext; import org.springframework.beans.factory.BeanFactory; @@ -89,21 +86,20 @@ public class AVMSubmitLinkChecker extends JBPMSpringActionHandler { // retrieve the workflow sandbox (the workflow package) NodeRef pkg = ((JBPMNode)executionContext.getContextInstance().getVariable("bpm_package")).getNodeRef(); - Pair pkgPath = AVMNodeConverter.ToAVMVersionPath(pkg); - - // remove the trailing www from the path - String path = pkgPath.getSecond(); - path = path.substring(0, (path.length()-JNDIConstants.DIR_DEFAULT_WWW.length())); - NodeRef storePath = AVMNodeConverter.ToNodeRef(-1, path); // get the store name String storeName = pkg.getStoreRef().getIdentifier(); + // retrieve the webapp name from the workflow execution context + String webappName = (String)executionContext.getContextInstance().getVariable("wcmwf_webapp"); + String webappPath = storeName + ":/" + JNDIConstants.DIR_DEFAULT_WWW + "/" + + JNDIConstants.DIR_DEFAULT_APPBASE + "/" + webappName; + NodeRef webappPathRef = AVMNodeConverter.ToNodeRef(-1, webappPath); + if (logger.isDebugEnabled()) - logger.info("Found workflow store to check links for: " + path); + logger.debug("Checking links in workflow webapp: " + webappPath); - // create and execute the action in the background - Throwable cause = null; + // create and execute the action int brokenLinks = -1; try @@ -111,8 +107,15 @@ public class AVMSubmitLinkChecker extends JBPMSpringActionHandler HrefValidationProgress monitor = new HrefValidationProgress(); Map args = new HashMap(1, 1.0f); args.put(LinkValidationAction.PARAM_MONITOR, monitor); + + // TODO: determine what should happen here, comparing against staging + // does not work as the webapp is not virtualised yet so workflow + // always goes straight to 'review'. Temporarily removed the flag + // so just the workflow store gets checked. + +// args.put(LinkValidationAction.PARAM_COMPARE_TO_STAGING, Boolean.TRUE); Action action = this.fActionService.createAction(LinkValidationAction.NAME, args); - this.fActionService.executeAction(action, storePath, false, false); + this.fActionService.executeAction(action, webappPathRef, false, false); // retrieve the deployment report from the store property PropertyValue val = this.fAVMService.getStoreProperty(storeName, @@ -124,10 +127,6 @@ public class AVMSubmitLinkChecker extends JBPMSpringActionHandler { brokenLinks = report.getNumberBrokenLinks(); } - else - { - cause = report.getError(); - } } if (logger.isDebugEnabled()) @@ -135,16 +134,10 @@ public class AVMSubmitLinkChecker extends JBPMSpringActionHandler } catch (Throwable err) { - cause = err; - } - - // set the number of broken links in a variable - if (brokenLinks == -1) - { - // TODO: Decide how to handle errors, - // for now just return -1 and the workflow can decide + logger.error(err); } + // set the number of broken links in a variable, -1 indicates an error occured executionContext.setVariable("wcmwf_brokenLinks", brokenLinks); } }