Merged V2.0 to HEAD

5178: WCM-336, checkin performance
   5182: Missing OpenSearch strings
   5183: AR-1126
   5185: OpenSearch externalized strings
   5190: Schema and xforms
   5191: WCM-343
   5205: NTML using incorrect auth component
   5210: No virtual server start
   5211: WCM-352, WCM-353
   5212: Manage Task Dialog issues


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5332 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-03-07 15:04:21 +00:00
parent 52a3fa1ed1
commit 2725498515
17 changed files with 487 additions and 165 deletions

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing
*/
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.wf.AVMSubmittedAspect;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.util.Pair;
import org.alfresco.web.action.ActionEvaluator;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.wcm.AVMConstants;
/**
* UI Action Evaluator - return true if the node is not part of an in-progress WCM workflow.
* No check for deleted items is made in this evaluator. @see WCMWorkflowEvaluator
*
* @author Kevin Roast
*/
public class WCMWorkflowDeletedEvaluator implements ActionEvaluator
{
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(final Node node)
{
final FacesContext facesContext = FacesContext.getCurrentInstance();
final AVMService avmService = Repository.getServiceRegistry(facesContext).getAVMService();
final Pair<Integer, String> p = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef());
final int version = p.getFirst();
final String path = p.getSecond();
// evaluate to true if we are within a workflow store (i.e. list of resources in the task
// dialog) or not part of an already in-progress workflow
return (AVMConstants.isWorkflowStore(AVMConstants.getStoreName(path)) ||
avmService.hasAspect(version, path, AVMSubmittedAspect.ASPECT) == false);
}
}

View File

@@ -26,10 +26,10 @@ package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.util.Pair;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.wf.AVMSubmittedAspect;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.util.Pair;
import org.alfresco.web.action.ActionEvaluator;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
@@ -48,11 +48,15 @@ public class WCMWorkflowEvaluator implements ActionEvaluator
public boolean evaluate(final Node node)
{
final FacesContext facesContext = FacesContext.getCurrentInstance();
final AVMService avmService =
Repository.getServiceRegistry(facesContext).getAVMService();
final AVMService avmService = Repository.getServiceRegistry(facesContext).getAVMService();
final Pair<Integer, String> p = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef());
final int version = p.getFirst();
final String path = p.getSecond();
return (!avmService.hasAspect(p.getFirst(), path, AVMSubmittedAspect.ASPECT) ||
AVMConstants.isWorkflowStore(AVMConstants.getStoreName(path)));
// evaluate to true if we are not deleted and within a workflow store (i.e. list of resources
// in the task dialog) or not part of an already in-progress workflow
return ((AVMConstants.isWorkflowStore(AVMConstants.getStoreName(path)) ||
avmService.hasAspect(version, path, AVMSubmittedAspect.ASPECT) == false) &&
avmService.lookup(version, path) != null);
}
}

View File

@@ -173,8 +173,8 @@ public class NTLMAuthenticationFilter extends AbstractAuthenticationFilter imple
m_nodeService = serviceRegistry.getNodeService();
m_transactionService = serviceRegistry.getTransactionService();
m_authService = (AuthenticationService) ctx.getBean("authenticationService");
m_authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
m_authService = (AuthenticationService) ctx.getBean("AuthenticationService");
m_authComponent = (AuthenticationComponent) ctx.getBean("AuthenticationComponent");
m_personService = (PersonService) ctx.getBean("personService");
m_configService = (ConfigService) ctx.getBean("webClientConfigService");

View File

@@ -140,18 +140,7 @@ public class AVMNode extends Node implements Map<String, Object>
this.avmRef = avmRef;
this.version = -1; // TODO: always -1 for now...
this.id = avmRef.getPath();
}
/**
* Constructor
*
* @param avmRef The AVMNodeDescriptor that describes this node
* @param deleted True if the node represents a ghosted deleted node
*/
public AVMNode(AVMNodeDescriptor avmRef, boolean deleted)
{
this(avmRef);
this.deleted = deleted;
this.deleted = avmRef.isDeleted();
}
@Override
@@ -196,12 +185,12 @@ public class AVMNode extends Node implements Map<String, Object>
public final boolean isDirectory()
{
return this.avmRef.isDirectory();
return this.avmRef.isDirectory() || this.avmRef.isDeletedDirectory();
}
public final boolean isFile()
{
return this.avmRef.isFile();
return this.avmRef.isFile() || this.avmRef.isDeletedFile();
}
/**

View File

@@ -33,6 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
@@ -62,6 +63,7 @@ import org.alfresco.web.forms.RenderingEngine;
import org.alfresco.web.forms.RenderingEngineTemplate;
import org.alfresco.web.forms.RenderingEngineTemplateImpl;
import org.alfresco.web.forms.XMLUtil;
import org.alfresco.web.forms.xforms.FormBuilderException;
import org.alfresco.web.forms.xforms.SchemaUtil;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIListItem;
@@ -615,7 +617,16 @@ public class CreateFormWizard
try
{
final Document d = XMLUtil.parse(this.getSchemaFile());
this.schema = SchemaUtil.parseSchema(d);
try
{
this.schema = SchemaUtil.parseSchema(d, true);
}
catch (FormBuilderException fbe)
{
this.schema = SchemaUtil.parseSchema(d, false);
LOGGER.warn("non fatal errors encountered parsing schema " + this.getFileName(FILE_SCHEMA) +
"\n " + fbe.getMessage());
}
}
catch (Exception e)
{

View File

@@ -309,24 +309,15 @@ public class CreateWebContentWizard extends BaseContentWizard
}
}
this.avmSyncService.update(diffList, null, true, true, true, true, null, null);
// reset all paths and structures to the main store
this.createdPath = AVMConstants.getCorrespondingPathInMainStore(this.createdPath);
if (LOGGER.isDebugEnabled())
LOGGER.debug("reset path " + this.createdPath + " to main store");
boolean form = (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null);
if (form)
{
this.formInstanceData = new FormInstanceDataImpl(AVMNodeConverter.ToNodeRef(-1, this.createdPath));
this.renditions = this.formInstanceData.getRenditions();
if (LOGGER.isDebugEnabled())
LOGGER.debug("reset form instance data " + this.formInstanceData.getName() +
" and " + this.renditions.size() + " to main store");
}
if (this.startWorkflow)
{
final WorkflowDefinition wd = this.getForm().getDefaultWorkflow();
if (wd == null)
{
throw new AlfrescoRuntimeException(Application.getMessage(context, "submit_no_workflow_warning"));
}
final Map<QName, Serializable> parameters = this.getForm().getDefaultWorkflowParameters();
if (LOGGER.isDebugEnabled())
@@ -334,8 +325,7 @@ public class CreateWebContentWizard extends BaseContentWizard
if (parameters == null)
{
Utils.addErrorMessage(Application.getMessage(context, "submit_workflow_config_error"));
return null;
throw new AlfrescoRuntimeException(Application.getMessage(context, "submit_workflow_config_error"));
}
// start the workflow to get access to the start task
@@ -357,7 +347,7 @@ public class CreateWebContentWizard extends BaseContentWizard
final List<String> srcPaths = new ArrayList<String>();
// construct diffs for selected items for submission
final String sandboxName = this.avmBrowseBean.getSandbox();
if (form)
if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null)
{
// collect diffs for form data instance and all renditions
for (Rendition rendition : this.getRenditions())
@@ -379,10 +369,17 @@ public class CreateWebContentWizard extends BaseContentWizard
}
if (LOGGER.isDebugEnabled())
LOGGER.debug("creating workflow package with " + srcPaths.size() + " files");
{
LOGGER.debug("creating workflow package with " + srcPaths.size() + " files: {");
for (final String srcPath : srcPaths)
{
LOGGER.debug("-- " + srcPath + ",");
}
LOGGER.debug("}");
}
// Create workflow sandbox for workflow package
SandboxInfo sandboxInfo = SandboxFactory.createWorkflowSandbox(storeId);
final SandboxInfo sandboxInfo = SandboxFactory.createWorkflowSandbox(storeId);
final NodeRef packageNodeRef =
AVMWorkflowUtil.createWorkflowPackage(srcPaths,
@@ -396,7 +393,10 @@ public class CreateWebContentWizard extends BaseContentWizard
parameters.put(WorkflowModel.ASSOC_PACKAGE, packageNodeRef);
// TODO: capture label and comment?
parameters.put(AVMWorkflowUtil.PROP_LABEL, form ? this.formInstanceData.getName() : this.getFileName());
parameters.put(AVMWorkflowUtil.PROP_LABEL,
MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null
? this.formInstanceData.getName()
: this.getFileName());
parameters.put(AVMWorkflowUtil.PROP_FROM_PATH, AVMConstants.buildStoreRootPath(sandboxName));
// update start task with submit parameters
@@ -417,6 +417,25 @@ public class CreateWebContentWizard extends BaseContentWizard
// return the default outcome
return outcome;
}
@Override
protected String doPostCommitProcessing(final FacesContext facesContext, final String outcome)
{
// reset all paths and structures to the main store
this.createdPath = AVMConstants.getCorrespondingPathInMainStore(this.createdPath);
if (LOGGER.isDebugEnabled())
LOGGER.debug("reset path " + this.createdPath + " to main store");
if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null)
{
this.formInstanceData = new FormInstanceDataImpl(AVMNodeConverter.ToNodeRef(-1, this.createdPath));
this.renditions = this.formInstanceData.getRenditions();
if (LOGGER.isDebugEnabled())
LOGGER.debug("reset form instance data " + this.formInstanceData.getName() +
" and " + this.renditions.size() + " to main store");
}
return super.doPostCommitProcessing(facesContext, outcome);
}
@Override
public boolean getNextButtonDisabled()

View File

@@ -42,6 +42,7 @@ import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.forms.xforms.FormBuilderException;
import org.alfresco.web.forms.xforms.SchemaUtil;
import org.alfresco.web.forms.Form;
import org.alfresco.web.forms.FormsService;
@@ -94,7 +95,7 @@ public class EditFormWizard
ContentModel.PROP_NAME));
try
{
this.schema = SchemaUtil.parseSchema(form.getSchema());
this.schema = SchemaUtil.parseSchema(form.getSchema(), false);
}
catch (Throwable t)
{

View File

@@ -658,12 +658,14 @@ public class ManageTaskDialog extends BaseDialogBean
WCMModel.PROP_AVM_DIR_INDIRECTION);
final String stagingAvmPath = AVMNodeConverter.ToAVMVersionPath(stagingNodeRef).getSecond();
final String packageAvmPath = AVMNodeConverter.ToAVMVersionPath(this.workflowPackage).getSecond();
LOGGER.debug("comparing " + packageAvmPath + " with " + stagingAvmPath);
if (LOGGER.isDebugEnabled())
LOGGER.debug("comparing " + packageAvmPath + " with " + stagingAvmPath);
for (AVMDifference d : this.avmSyncService.compare(-1, packageAvmPath,
-1, stagingAvmPath,
null))
{
LOGGER.debug("got difference " + d);
if (LOGGER.isDebugEnabled())
LOGGER.debug("got difference " + d);
if (d.getDifferenceCode() == AVMDifference.NEWER ||
d.getDifferenceCode() == AVMDifference.CONFLICT)
{

View File

@@ -135,7 +135,7 @@ public class Schema2XForms
final ResourceBundle resourceBundle)
throws FormBuilderException
{
final XSModel schema = SchemaUtil.parseSchema(schemaDocument);
final XSModel schema = SchemaUtil.parseSchema(schemaDocument, true);
this.typeTree = SchemaUtil.buildTypeTree(schema);
//refCounter = 0;
@@ -278,9 +278,13 @@ public class Schema2XForms
if (importedInstanceDocumentElement != null)
{
this.insertUpdatedNodes(importedInstanceDocumentElement,
defaultInstanceDocumentElement,
schemaNamespacesMap);
this.insertPrototypeNodes(importedInstanceDocumentElement,
defaultInstanceDocumentElement,
schemaNamespacesMap);
}
this.createSubmitElements(xformsDocument, modelSection, rootGroup);
@@ -303,6 +307,117 @@ public class Schema2XForms
this.counter.clear();
}
/**
* Inserts nodes that exist in the prototype document that are absent in the imported instance.
* This is to handle the case where a schema has been updated since the last time the
* imported document was modified.
*
* @param instanceDocumentElement the user provided instance document
* @param prototypeInstanceElement the generated prototype instance document
* @param schemaNamespaces the namespaces used by the instance document needed for
* initializing the xpath context.
*/
private void insertUpdatedNodes(final Element instanceDocumentElement,
final Element prototypeDocumentElement,
final HashMap<String, String> schemaNamespaces)
{
LOGGER.debug("updating imported instance document");
final JXPathContext prototypeContext =
JXPathContext.newContext(prototypeDocumentElement);
prototypeContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX,
NamespaceService.ALFRESCO_URI);
final JXPathContext instanceContext =
JXPathContext.newContext(instanceDocumentElement);
instanceContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX,
NamespaceService.ALFRESCO_URI);
// identify all non prototype elements in the prototypeDocument
for (final String prefix : schemaNamespaces.keySet())
{
prototypeContext.registerNamespace(prefix, schemaNamespaces.get(prefix));
instanceContext.registerNamespace(prefix, schemaNamespaces.get(prefix));
}
final Iterator it =
prototypeContext.iteratePointers("//*[not(@" + NamespaceService.ALFRESCO_PREFIX +
":prototype='true')] | //@*[name()!='" + NamespaceService.ALFRESCO_PREFIX +
":prototype']");
while (it.hasNext())
{
final Pointer p = (Pointer)it.next();
if (LOGGER.isDebugEnabled())
{
LOGGER.debug("evaluating prototype node " + p.asPath() +
" normalized " + p.asPath().replaceAll("\\[\\d+\\]", ""));
}
String path = p.asPath().replaceAll("\\[\\d+\\]", "");
if (path.lastIndexOf("/") == 0)
{
if (instanceContext.selectNodes(path).size() == 0)
{
LOGGER.debug("copying " + path + " into imported instance");
// remove child elements - we want attributes but don't want to
// copy any potential prototyp nodes
final Node clone = ((Node)p.getNode()).cloneNode(true);
if (clone instanceof Attr)
{
instanceDocumentElement.setAttributeNode((Attr)clone);
}
else
{
final NodeList children = clone.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
if (children.item(i) instanceof Element)
{
clone.removeChild(children.item(i));
}
}
instanceDocumentElement.appendChild(clone);
}
}
}
else
{
// change path /foo/bar into /foo[not(child::bar)]
if (path.indexOf("@") >= 0)
{
path = path.replaceAll("\\/(@.+)$", "[not($1)]");
}
else
{
path = path.replaceAll("\\/([^/]+)$", "[not(child::$1)]");
}
final List<Node> l = (List<Node>)instanceContext.selectNodes(path);
LOGGER.debug("appending node " + ((Node)p.getNode()).getNodeName() +
" to the " + l.size() + " selected nodes matching path " + path);
for (Node n : l)
{
// remove child elements - we want attributes but don't want to
// copy any potential prototyp nodes
final Node clone = ((Node)p.getNode()).cloneNode(true);
if (clone instanceof Attr)
{
((Element)n).setAttributeNode((Attr)clone);
}
else
{
final NodeList children = clone.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
if (children.item(i) instanceof Element)
{
clone.removeChild(children.item(i));
}
}
n.appendChild(clone);
}
}
}
}
}
/**
* Inserts prototype nodes into the provided instance document by aggregating insertion
* points from the generated prototype instance docment.

View File

@@ -32,7 +32,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xerces.xs.*;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.*;
import org.w3c.dom.Document;
import org.w3c.dom.*;
/**
* Provides utility functions for xml schema parsing.
@@ -208,7 +208,8 @@ public class SchemaUtil
return SchemaUtil.DATA_TYPE_TO_NAME.get(type);
}
public static XSModel parseSchema(final Document schemaDocument)
public static XSModel parseSchema(final Document schemaDocument,
final boolean failOnError)
throws FormBuilderException
{
try
@@ -222,13 +223,59 @@ public class SchemaUtil
final DOMImplementationLS lsImpl = (DOMImplementationLS)
registry.getDOMImplementation("XML 1.0 LS 3.0");
if (lsImpl == null)
{
throw new FormBuilderException("unable to create DOMImplementationLS using " + registry);
}
final LSInput in = lsImpl.createLSInput();
in.setStringData(XMLUtil.toString(schemaDocument));
final XSImplementation xsImpl = (XSImplementation)
registry.getDOMImplementation("XS-Loader");
final XSLoader schemaLoader = xsImpl.createXSLoader(null);
final DOMConfiguration config = schemaLoader.getConfig();
final LinkedList<DOMError> errors = new LinkedList<DOMError>();
config.setParameter("error-handler", new DOMErrorHandler()
{
public boolean handleError(final DOMError domError)
{
errors.add(domError);
return true;
}
});
final XSModel result = schemaLoader.load(in);
if (failOnError && errors.size() != 0)
{
final HashSet<String> messages = new HashSet<String>();
StringBuilder message = null;
for (DOMError e : errors)
{
message = new StringBuilder();
final DOMLocator dl = e.getLocation();
if (dl != null)
{
message.append("at line ").append(dl.getLineNumber())
.append(" column ").append(dl.getColumnNumber());
if (dl.getRelatedNode() != null)
{
message.append(" node ").append(dl.getRelatedNode().getNodeName());
}
message.append(": ").append(e.getMessage());
}
messages.add(message.toString());
}
message = new StringBuilder();
message.append(messages.size() > 1 ? "errors" : "error").append(" parsing schema: \n");
for (final String s : messages)
{
message.append(s).append("\n");
}
throw new FormBuilderException(message.toString());
}
if (result == null)
{
throw new FormBuilderException("invalid schema");

View File

@@ -115,48 +115,49 @@ public class UIOpenSearch extends SelfRenderingComponent
out.write("', '");
out.write(engine.getUrl());
out.write("');\n");
// pass in NLS strings
out.write(clientId);
out.write(".setMsgNoResults(\"");
out.write(Application.getMessage(context, "no_results"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgOf(\"");
out.write(Application.getMessage(context, "of"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgFailedGenerateUrl(\"");
out.write(Application.getMessage(context, "failed_gen_url"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgFailedSearch(\"");
out.write(Application.getMessage(context, "failed_search"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgFirstPage(\"");
out.write(Application.getMessage(context, "first_page"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgPreviousPage(\"");
out.write(Application.getMessage(context, "prev_page"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgNextPage(\"");
out.write(Application.getMessage(context, "next_page"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgLastPage(\"");
out.write(Application.getMessage(context, "last_page"));
out.write("\");\n");
}
// pass in NLS strings
out.write(clientId);
out.write(".setMsgNoResults(\"");
out.write(Application.getMessage(context, "no_results"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgOf(\"");
out.write(Application.getMessage(context, "of"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgFailedGenerateUrl(\"");
out.write(Application.getMessage(context, "failed_gen_url"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgFailedSearch(\"");
out.write(Application.getMessage(context, "failed_search"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgFirstPage(\"");
out.write(Application.getMessage(context, "first_page"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgPreviousPage(\"");
out.write(Application.getMessage(context, "prev_page"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgNextPage(\"");
out.write(Application.getMessage(context, "next_page"));
out.write("\");\n");
out.write(clientId);
out.write(".setMsgLastPage(\"");
out.write(Application.getMessage(context, "last_page"));
out.write("\");\n");
out.write("</script>\n");
// write out the HTML

View File

@@ -787,7 +787,7 @@ public class UIUserSandboxes extends SelfRenderingComponent
out.write("</td><td style='color:#aaaaaa'>");
// deleted UI actions for this item
uiDeletedActions.setContext(new AVMNode(node, true));
uiDeletedActions.setContext(new AVMNode(node));
Utils.encodeRecursive(fc, uiDeletedActions);
}
out.write("</td></tr>");