mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
- added utility methods to AVMConstants to extract information about stores from their names. this has to be reimplemented to look at store properties rather than inferring things from their names - but it works for now. this also centralizes all the usage of the store name to infer data about it so it'll make it easier later. - made the problematic constants jon changed private to avoid having this problem happen again - checked pretty much every usage of buildAVM<bla> to ensure that nothing else was broken. in the process removed the AVM part from the buildAVM<bla> part of the method to shorten it and since it's redundant with the classname AVMConstants in which their contained. creating workflow sandboxes in a manner consistent with user sandboxes - added a method to SandboxFactory to create workflow sandboxes. they're created with the name <storeId>--workflow-<guid> - centralized workflow package creation code in AVMWorkflowUtil. - refactored sandbox creation code to use new utility methods in AVMConstants and so that at some point it can be further refactored. getting avm actions to show up in manage task screen for avm workflows - modified the model to use different packageItemActionGroups for wcm workflows - modified the AVMWorkflowEvaluator to allow all actions for items in a workflow package - added some debug output to various classes - made wcm navigation ids exposed throughout the app since they are now called from workflow jsps. things that now work that didn't before: - virtualization now works again with jon's new naming scheme - some actions from the manage task screen. known bugs introduced or remaining as a consequence of this change (i'll filed jira issues for these as soon as i commit this): - i'm inaccurately counting the number of users in a sandbox since it's harder now to differentiate between user main sandboxes and all the other ones that are being created - preview does not work on assets within the workflow sandboxes - review and approve workflow does not appear to actually submit once approved. not sure if it did before - lots of actions still do not work from manage tasks, though edit does appear to. - i commented out the location column in the manage task screen since the path link was causing me troubles - need to put that back in. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4692 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
382 lines
13 KiB
Java
382 lines
13 KiB
Java
/*
|
|
* Copyright (C) 2005 Alfresco, Inc.
|
|
*
|
|
* Licensed under the Mozilla Public License version 1.1
|
|
* with a permitted attribution clause. You may obtain a
|
|
* copy of the License at
|
|
*
|
|
* http://www.alfresco.org/legal/license.txt
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
* either express or implied. See the License for the specific
|
|
* language governing permissions and limitations under the
|
|
* License.
|
|
*/
|
|
package org.alfresco.web.forms;
|
|
|
|
import java.io.*;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.util.*;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.transform.Result;
|
|
import javax.xml.transform.Source;
|
|
import javax.xml.transform.Transformer;
|
|
import javax.xml.transform.TransformerConfigurationException;
|
|
import javax.xml.transform.TransformerException;
|
|
import javax.xml.transform.TransformerFactory;
|
|
import javax.xml.transform.URIResolver;
|
|
import javax.xml.transform.dom.DOMSource;
|
|
import javax.xml.transform.sax.TransformerHandler;
|
|
import javax.xml.transform.stream.StreamResult;
|
|
import javax.xml.transform.stream.StreamSource;
|
|
import org.alfresco.service.cmr.repository.ContentService;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.web.bean.wcm.AVMConstants;
|
|
import org.alfresco.web.forms.FormsService;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.apache.xalan.extensions.ExpressionContext;
|
|
import org.apache.xpath.objects.XObject;
|
|
import org.apache.xml.utils.QName;
|
|
import org.w3c.dom.*;
|
|
import org.w3c.dom.traversal.NodeFilter;
|
|
import org.w3c.dom.traversal.NodeIterator;
|
|
import org.xml.sax.SAXException;
|
|
import org.apache.bsf.BSFManager;
|
|
|
|
/**
|
|
* A rendering engine which uses xsl templates to render renditions of
|
|
* form instance data.
|
|
*
|
|
* @author Ariel Backenroth
|
|
*/
|
|
public class XSLTRenderingEngine
|
|
extends AbstractRenderingEngine
|
|
{
|
|
|
|
private static final Log LOGGER = LogFactory.getLog(XSLTRenderingEngine.class);
|
|
|
|
public XSLTRenderingEngine()
|
|
{
|
|
super();
|
|
}
|
|
|
|
public String getName()
|
|
{
|
|
return "XSLT";
|
|
}
|
|
|
|
public String getDefaultTemplateFileExtension()
|
|
{
|
|
return "xsl";
|
|
}
|
|
|
|
protected static String toAVMPath(final ExpressionContext ec, String path)
|
|
throws TransformerException
|
|
{
|
|
final XObject o = ec.getVariableOrParam(new QName(ALFRESCO_NS, ALFRESCO_NS_PREFIX, "parent_path"));
|
|
return o == null ? null : AVMConstants.buildPath(o.toString(),
|
|
path,
|
|
AVMConstants.PathRelation.WEBAPP_RELATIVE);
|
|
}
|
|
|
|
/**
|
|
* Adapter function used by the xsl tempalte to retrieve an xml asset at the given
|
|
* path.
|
|
*
|
|
* @return the document element for the xml asset at the given path.
|
|
*/
|
|
public static Node parseXMLDocument(final ExpressionContext ec, final String path)
|
|
throws TransformerException,
|
|
IOException,
|
|
SAXException
|
|
{
|
|
final FormDataFunctions ef = XSLTRenderingEngine.getFormDataFunctions();
|
|
final Document d = ef.parseXMLDocument(XSLTRenderingEngine.toAVMPath(ec, path));
|
|
return d != null ? d.getDocumentElement() : null;
|
|
}
|
|
|
|
/**
|
|
* Adapter function used by the xsl tempalte to retrieve a xml assets in the
|
|
* current directory.
|
|
*/
|
|
public static NodeIterator parseXMLDocuments(final ExpressionContext ec,
|
|
final String formName)
|
|
throws TransformerException,
|
|
IOException,
|
|
SAXException
|
|
{
|
|
return XSLTRenderingEngine.parseXMLDocuments(ec, formName, "");
|
|
}
|
|
|
|
/**
|
|
* Adapter function used by the xsl tempalte to retrieve a xml assets at
|
|
* the given path.
|
|
*
|
|
* @return an iterator of the document elements for each of the xml
|
|
* assets at the given path. In order to enable xpath expressions to
|
|
* properly access siblings, each root element is rooted at a node named
|
|
* file-list in the alfresco namespace.
|
|
*/
|
|
public static NodeIterator parseXMLDocuments(final ExpressionContext ec,
|
|
final String formName,
|
|
String path)
|
|
throws TransformerException,
|
|
IOException,
|
|
SAXException
|
|
{
|
|
final FormDataFunctions ef = XSLTRenderingEngine.getFormDataFunctions();
|
|
path = XSLTRenderingEngine.toAVMPath(ec, path);
|
|
final Map<String, Document> resultMap = ef.parseXMLDocuments(formName, path);
|
|
if (LOGGER.isDebugEnabled())
|
|
LOGGER.debug("received " + resultMap.size() + " documents in " + path);
|
|
|
|
// create a root document for rooting all the results. we do this
|
|
// so that each document root element has a common parent node
|
|
// and so that xpath axes work properly
|
|
final FormsService fs = FormsService.getInstance();
|
|
final DocumentBuilder documentBuilder = fs.getDocumentBuilder();
|
|
final Document rootNodeDocument = documentBuilder.newDocument();
|
|
final Element rootNodeDocumentEl =
|
|
rootNodeDocument.createElementNS(ALFRESCO_NS,
|
|
ALFRESCO_NS_PREFIX + ":file_list");
|
|
rootNodeDocumentEl.setAttribute("xmlns:" + ALFRESCO_NS_PREFIX, ALFRESCO_NS);
|
|
rootNodeDocument.appendChild(rootNodeDocumentEl);
|
|
|
|
final List<Node> documents = new ArrayList<Node>(resultMap.size());
|
|
for (Map.Entry<String, Document> mapEntry : resultMap.entrySet())
|
|
{
|
|
final Element documentEl = mapEntry.getValue().getDocumentElement();
|
|
documentEl.setAttributeNS(ALFRESCO_NS,
|
|
ALFRESCO_NS_PREFIX + ":file_name",
|
|
mapEntry.getKey());
|
|
final Node n = rootNodeDocument.importNode(documentEl, true);
|
|
documents.add(n);
|
|
rootNodeDocumentEl.appendChild(n);
|
|
}
|
|
|
|
return new NodeIterator()
|
|
{
|
|
private int index = 0;
|
|
private boolean detached = false;
|
|
|
|
public void detach()
|
|
{
|
|
if (LOGGER.isDebugEnabled())
|
|
LOGGER.debug("detaching NodeIterator");
|
|
resultMap.clear();
|
|
documents.clear();
|
|
this.detached = true;
|
|
}
|
|
|
|
public boolean getExpandEntityReferences()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public NodeFilter getFilter()
|
|
{
|
|
return new NodeFilter()
|
|
{
|
|
public short acceptNode(final Node n)
|
|
{
|
|
return NodeFilter.FILTER_ACCEPT;
|
|
}
|
|
};
|
|
}
|
|
|
|
public Node getRoot()
|
|
{
|
|
return rootNodeDocumentEl;
|
|
}
|
|
|
|
public int getWhatToShow()
|
|
{
|
|
return NodeFilter.SHOW_ALL;
|
|
}
|
|
|
|
public Node nextNode()
|
|
throws DOMException
|
|
{
|
|
if (LOGGER.isDebugEnabled())
|
|
LOGGER.debug("NodeIterator.nextNode(" + index + ")");
|
|
if (this.detached)
|
|
throw new DOMException(DOMException.INVALID_STATE_ERR, null);
|
|
if (index == documents.size())
|
|
return null;
|
|
return documents.get(index++);
|
|
}
|
|
|
|
public Node previousNode()
|
|
throws DOMException
|
|
{
|
|
if (LOGGER.isDebugEnabled())
|
|
LOGGER.debug("NodeIterator.previousNode(" + index + ")");
|
|
if (this.detached)
|
|
throw new DOMException(DOMException.INVALID_STATE_ERR, null);
|
|
if (index == -1)
|
|
return null;
|
|
return documents.get(index--);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* for debugging only. provides the absolute avm path for the given
|
|
* path.
|
|
*/
|
|
public static String _getAVMPath(final ExpressionContext ec,
|
|
final String path)
|
|
throws TransformerException,
|
|
IOException,
|
|
SAXException
|
|
{
|
|
final FormDataFunctions ef = XSLTRenderingEngine.getFormDataFunctions();
|
|
return XSLTRenderingEngine.toAVMPath(ec, path);
|
|
}
|
|
|
|
/**
|
|
* Adds a script element to the xsl which makes static methods on this
|
|
* object available to the xsl tempalte.
|
|
*
|
|
* @param xslTemplate the xsl template
|
|
*/
|
|
protected void addScript(final Document xslTemplate)
|
|
{
|
|
final Element docEl = xslTemplate.getDocumentElement();
|
|
final String XALAN_NS = "http://xml.apache.org/xalan";
|
|
final String XALAN_NS_PREFIX = "xalan";
|
|
docEl.setAttribute("xmlns:" + XALAN_NS_PREFIX, XALAN_NS);
|
|
docEl.setAttribute("xmlns:" + ALFRESCO_NS_PREFIX, ALFRESCO_NS);
|
|
|
|
final Element compEl = xslTemplate.createElementNS(XALAN_NS, XALAN_NS_PREFIX + ":component");
|
|
compEl.setAttribute("prefix", "alfresco");
|
|
docEl.appendChild(compEl);
|
|
|
|
final Element scriptEl = xslTemplate.createElementNS(XALAN_NS, XALAN_NS_PREFIX + ":script");
|
|
scriptEl.setAttribute("lang", "javaclass");
|
|
scriptEl.setAttribute("src", XALAN_NS_PREFIX + "://" + this.getClass().getName());
|
|
compEl.appendChild(scriptEl);
|
|
}
|
|
|
|
/**
|
|
* Adds the specified parameters to the xsl template as variables within the
|
|
* alfresco namespace.
|
|
*
|
|
* @param parameters the variables to place within the xsl template
|
|
* @param xslTemplate the xsl template
|
|
*/
|
|
protected void addParameters(final Map<String, String> parameters,
|
|
final Document xslTemplate)
|
|
{
|
|
final Element docEl = xslTemplate.getDocumentElement();
|
|
final String XSL_NS = docEl.getNamespaceURI();
|
|
final String XSL_NS_PREFIX = docEl.getPrefix();
|
|
|
|
for (Map.Entry<String, String> e : parameters.entrySet())
|
|
{
|
|
final Element el = xslTemplate.createElementNS(XSL_NS, XSL_NS_PREFIX + ":variable");
|
|
el.setAttribute("name", ALFRESCO_NS_PREFIX + ':' + e.getKey());
|
|
el.appendChild(xslTemplate.createTextNode(e.getValue()));
|
|
docEl.insertBefore(el, docEl.getFirstChild());
|
|
}
|
|
}
|
|
|
|
public void render(final Document formInstanceData,
|
|
final RenderingEngineTemplate ret,
|
|
final Map<String, String> parameters,
|
|
final OutputStream out)
|
|
throws IOException,
|
|
RenderingEngine.RenderingException
|
|
{
|
|
this.render(new DOMSource(formInstanceData), ret, parameters, new StreamResult(out));
|
|
}
|
|
|
|
protected void render(final Source formInstanceDataSource,
|
|
final RenderingEngineTemplate ret,
|
|
final Map<String, String> parameters,
|
|
final Result result)
|
|
throws IOException,
|
|
RenderingEngine.RenderingException
|
|
{
|
|
System.setProperty("org.apache.xalan.extensions.bsf.BSFManager",
|
|
BSFManager.class.getName());
|
|
final FormsService ts = FormsService.getInstance();
|
|
Document xslTemplate = null;
|
|
try
|
|
{
|
|
xslTemplate = ts.parseXML(ret.getInputStream());
|
|
}
|
|
catch (final SAXException sax)
|
|
{
|
|
throw new RenderingEngine.RenderingException(sax);
|
|
}
|
|
this.addScript(xslTemplate);
|
|
this.addParameters(parameters, xslTemplate);
|
|
|
|
Transformer t = null;
|
|
try
|
|
{
|
|
final TransformerFactory tf = TransformerFactory.newInstance();
|
|
t = tf.newTransformer(new DOMSource(xslTemplate));
|
|
t.setParameter("versionParam", "2.0");
|
|
}
|
|
catch (TransformerConfigurationException tce)
|
|
{
|
|
LOGGER.error(tce);
|
|
throw new RenderingEngine.RenderingException(tce);
|
|
}
|
|
|
|
// create a uri resolver to resolve document() calls to the virtualized
|
|
// web application
|
|
t.setURIResolver(new URIResolver()
|
|
{
|
|
public Source resolve(final String href, final String base)
|
|
throws TransformerException
|
|
{
|
|
// XXXarielb - dirty - fix this
|
|
final String sandBoxUrl = (String)parameters.get("avm_sandbox_url");
|
|
|
|
URI uri = null;
|
|
try
|
|
{
|
|
uri = new URI(sandBoxUrl + href);
|
|
}
|
|
catch (URISyntaxException e)
|
|
{
|
|
throw new TransformerException("unable to create uri " +
|
|
sandBoxUrl + href,
|
|
e);
|
|
}
|
|
try
|
|
{
|
|
if (LOGGER.isDebugEnabled())
|
|
LOGGER.debug("loading " + uri);
|
|
final Document d = ts.parseXML(uri.toURL().openStream());
|
|
if (LOGGER.isDebugEnabled())
|
|
LOGGER.debug("loaded " + ts.writeXMLToString(d));
|
|
return new DOMSource(d);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new TransformerException("unable to load " + uri, e);
|
|
}
|
|
}
|
|
});
|
|
|
|
try
|
|
{
|
|
t.transform(formInstanceDataSource, result);
|
|
}
|
|
catch (TransformerException e)
|
|
{
|
|
LOGGER.error(e.getMessageAndLocation());
|
|
throw new RenderingEngine.RenderingException(e);
|
|
}
|
|
}
|
|
}
|