From 997e6537aa02f7f55c464e6ea50c2c47a2ba31ed Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Fri, 19 Sep 2008 12:51:08 +0000 Subject: [PATCH] Merged V2.2 to HEAD 10931: Merged V2.1 to V2.2 9931: Fix for https://issues.alfresco.com/jira/browse/ETWOONE-295 10094: Further fix for ETWOONE-241: SAXException - XML parser apparently is not thread safe 10101: Resolve ACT 1282: wcm workflow falling over on Oracle while hitting in clause limit of 1000 expressions. 10188: https://issues.alfresco.com/jira/browse/ETWOONE-74 (Part 1) 10447: ETWOONE-328: performance improvement added to rule trigger code 10455: Fix for ETWOONE-306. 10292: Fix for ETWOONE-92: If two users update the same contents at the same time, you get InvalidNodeRefException 10293: Fix for ETWOONE-116: Send email action does not handle invalid email address 10294: Fix for ETWOONE-164: when a powerpoint 2007 pptx is stored in alfresco ... 10341: Action Evaluator request level cache git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10934 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 1 + .../servlet/BaseDownloadContentServlet.java | 12 ++++ .../web/bean/wcm/AVMWorkflowUtil.java | 1 + .../web/bean/wizard/NewUserWizard.java | 21 ++++++- .../alfresco/web/forms/FormDataFunctions.java | 56 +++++++++++++++---- .../evaluator/ActionInstanceEvaluator.java | 50 ++++++++++++++++- .../jsp/wizard/new-user/person-properties.jsp | 4 +- 7 files changed, 130 insertions(+), 15 deletions(-) diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 437f96efd1..db9a9dba19 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -1430,6 +1430,7 @@ user_properties=User Properties first_name=First Name last_name=Last Name email=Email +email_format_is_not_valid=Email format is not valid company_id=Company ID home_space_location=Home Space Location home_space_name=Home Space Name diff --git a/source/java/org/alfresco/web/app/servlet/BaseDownloadContentServlet.java b/source/java/org/alfresco/web/app/servlet/BaseDownloadContentServlet.java index cd3335f58d..55ff6805c5 100644 --- a/source/java/org/alfresco/web/app/servlet/BaseDownloadContentServlet.java +++ b/source/java/org/alfresco/web/app/servlet/BaseDownloadContentServlet.java @@ -72,6 +72,10 @@ public abstract class BaseDownloadContentServlet extends BaseServlet { private static final long serialVersionUID = -4558907921887235966L; + private static final String POWER_POINT_DOCUMENT_MIMETYPE = "application/vnd.powerpoint"; + + private static final String POWER_POINT_2007_DOCUMENT_MIMETYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + protected static final String MIMETYPE_OCTET_STREAM = "application/octet-stream"; protected static final String MSG_ERROR_CONTENT_MISSING = "error_content_missing"; @@ -286,6 +290,14 @@ public abstract class BaseDownloadContentServlet extends BaseServlet } } } + + // explicitly set the content disposition header if the content is powerpoint + if (!attachment && (mimetype.equals(POWER_POINT_2007_DOCUMENT_MIMETYPE) || + mimetype.equals(POWER_POINT_DOCUMENT_MIMETYPE))) + { + res.setHeader("Content-Disposition", "attachment"); + } + // set mimetype for the content and the character encoding for the stream res.setContentType(mimetype); res.setCharacterEncoding(reader.getEncoding()); diff --git a/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java b/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java index 5e6fd76bd2..d7207c13ea 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java @@ -258,6 +258,7 @@ public class AVMWorkflowUtil extends WorkflowUtil final HashMap props = new HashMap(1, 1.0f); props.put(WCMWorkflowModel.PROP_FROM_PATH, fromPath); query.setProcessCustomProps(props); + query.setActive(true); final List tasks = workflowService.queryTasks(query); if (logger.isDebugEnabled()) diff --git a/source/java/org/alfresco/web/bean/wizard/NewUserWizard.java b/source/java/org/alfresco/web/bean/wizard/NewUserWizard.java index d9aa08eab6..0271599741 100644 --- a/source/java/org/alfresco/web/bean/wizard/NewUserWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/NewUserWizard.java @@ -65,6 +65,7 @@ import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.UIActionLink; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.validator.EmailValidator; /** * @author Kevin Roast @@ -84,7 +85,8 @@ public class NewUserWizard extends AbstractWizardBean private static final String STEP2_TITLE_ID = "new_user_step2_title"; private static final String STEP2_DESCRIPTION_ID = "new_user_step2_desc"; private static final String FINISH_INSTRUCTION_ID = "new_user_finish_instruction"; - private static final String ERROR = "error_person"; + private static final String ERROR = "error_person"; + private static final String MSG_ERROR_MAIL_NOT_VALID = "email_format_is_not_valid"; /** form variables */ private String firstName = null; @@ -916,6 +918,23 @@ public class NewUserWizard extends AbstractWizardBean } } + /** + * Validate Email field data is acceptable + * + * @param context + * @param component + * @param value + * @throws ValidatorException + */ + public void validateEmail(FacesContext context, UIComponent component, Object value) throws ValidatorException + { + EmailValidator emailValidator = EmailValidator.getInstance(); + if (!emailValidator.isValid((String) value)) + { + String err =Application.getMessage(context, MSG_ERROR_MAIL_NOT_VALID); + throw new ValidatorException(new FacesMessage(err)); + } + } // ------------------------------------------------------------------------------ // Helper methods diff --git a/source/java/org/alfresco/web/forms/FormDataFunctions.java b/source/java/org/alfresco/web/forms/FormDataFunctions.java index befc297692..7cc3c6f343 100644 --- a/source/java/org/alfresco/web/forms/FormDataFunctions.java +++ b/source/java/org/alfresco/web/forms/FormDataFunctions.java @@ -22,20 +22,23 @@ * http://www.alfresco.com/legal/licensing" */ package org.alfresco.web.forms; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + import org.alfresco.model.WCMAppModel; import org.alfresco.repo.domain.PropertyValue; -import org.alfresco.repo.remote.AVMRemoteInputStream; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; -import org.alfresco.service.cmr.avm.AVMNotFoundException; import org.alfresco.service.cmr.remote.AVMRemote; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.w3c.dom.*; +import org.w3c.dom.Document; import org.xml.sax.SAXException; -import javax.xml.parsers.*; -import java.io.*; -import java.util.Map; -import java.util.HashMap; /** * Common implementation of functions called in the context of FormDataRenderers. @@ -43,14 +46,15 @@ import java.util.HashMap; * of both the alfresco webapp and the virtualization server. * * @author Ariel Backenroth + * @author Arseny Kovalchuk (Fix of the bug reported in https://issues.alfresco.com/jira/browse/ETWOONE-241) */ public class FormDataFunctions { private static final Log LOGGER = LogFactory.getLog(FormDataFunctions.class); - private static DocumentBuilder documentBuilder; - private final AVMRemote avmRemote; + + private ThreadLocal dbf = new ThreadLocal(); public FormDataFunctions(final AVMRemote avmRemote) { @@ -70,7 +74,7 @@ public class FormDataFunctions final InputStream istream = this.avmRemote.getFileInputStream(-1, avmPath); try { - return XMLUtil.parse(istream); + return parseXML(istream); } finally { @@ -123,7 +127,8 @@ public class FormDataFunctions final InputStream istream = this.avmRemote.getFileInputStream(-1, avmPath + '/' + entryName); try { - result.put(entryName, XMLUtil.parse(istream)); + // result.put(entryName, XMLUtil.parse(istream)); + result.put(entryName, parseXML(istream)); } finally { @@ -133,4 +138,33 @@ public class FormDataFunctions } return result; } + + /* + * We need an internal method for XML parsing with ThreadLocal DocumentBuilderFactory + * to avoid a multithread access to the parser in XMLUtils. + * Fix of the bug reported in https://issues.alfresco.com/jira/browse/ETWOONE-241 reported. + */ + private Document parseXML(InputStream is) throws IOException, SAXException + { + Document result = null; + try + { + DocumentBuilderFactory localDbf = dbf.get(); + if (localDbf == null) + { + localDbf = DocumentBuilderFactory.newInstance(); + } + localDbf.setNamespaceAware(true); + localDbf.setValidating(false); + dbf.set(localDbf); + DocumentBuilder builder = localDbf.newDocumentBuilder(); + result = builder.parse(is); + } + catch (ParserConfigurationException pce) + { + LOGGER.error(pce); + } + + return result; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java b/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java index 2763dd84f9..0a5affad64 100644 --- a/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java +++ b/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java @@ -27,6 +27,9 @@ package org.alfresco.web.ui.repo.component.evaluator; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + import javax.faces.context.FacesContext; import javax.faces.el.ValueBinding; @@ -42,6 +45,8 @@ import org.alfresco.web.ui.common.component.evaluator.BaseEvaluator; */ public class ActionInstanceEvaluator extends BaseEvaluator { + private static final String EVALUATOR_CACHE = "_alf_evaluator_cache"; + /** * Evaluate by executing the specified action instance evaluator. * @@ -56,7 +61,7 @@ public class ActionInstanceEvaluator extends BaseEvaluator final Object obj = this.getValue(); if (obj instanceof Node) { - result = this.getEvaluator().evaluate((Node)obj); + result = evaluateCachedResult((Node)obj); } else { @@ -87,6 +92,49 @@ public class ActionInstanceEvaluator extends BaseEvaluator return result; } + /** + * To reduce invocations of a particular evaluator for a particular node + * save a cache of evaluator result for a node against the current request. + * Since the same evaluator may get reused several times for multiple actions, but + * in effect execute against the same node instance, this can significantly reduce + * the number of invocations required for a particular evaluator. + * + * @param node Node to evaluate against + * + * @return evaluator result + */ + private boolean evaluateCachedResult(Node node) + { + Boolean result; + + ActionEvaluator evaluator = getEvaluator(); + String cacheKey = node.getNodeRef().toString() + '_' + evaluator.getClass().getName(); + Map cache = getEvaluatorResultCache(); + result = cache.get(cacheKey); + if (result == null) + { + result = evaluator.evaluate(node); + cache.put(cacheKey, result); + } + + return result; + } + + /** + * @return the evaluator result cache - tied to the current request + */ + private Map getEvaluatorResultCache() + { + FacesContext fc = FacesContext.getCurrentInstance(); + Map cache = (Map)fc.getExternalContext().getRequestMap().get(EVALUATOR_CACHE); + if (cache == null) + { + cache = new HashMap(64, 1.0f); + fc.getExternalContext().getRequestMap().put(EVALUATOR_CACHE, cache); + } + return cache; + } + /** * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object) */ diff --git a/source/web/jsp/wizard/new-user/person-properties.jsp b/source/web/jsp/wizard/new-user/person-properties.jsp index 0f93cf6b4c..3b8ebbf6e5 100644 --- a/source/web/jsp/wizard/new-user/person-properties.jsp +++ b/source/web/jsp/wizard/new-user/person-properties.jsp @@ -170,7 +170,7 @@ : -  * +  * @@ -209,7 +209,7 @@ - +