From 2e3cbebd824429a9c90c1700c549860ce22d34a0 Mon Sep 17 00:00:00 2001 From: Ariel Backenroth Date: Wed, 18 Oct 2006 06:20:50 +0000 Subject: [PATCH] - moving AVMRemoteInputStream from jndi-client project to repo project - extracting utility methods from sample website into generalized extension functions that can be used from xsl, freemarker (i hope), and jsp. they all use AVMRemote to access data and each context has it's own adapter. - implemented callout functions from xsl. able to load multiple documents and traverse them. - removed QNames from TemplatingService and added them to WCMModel. this will break edit on any existing assets - you'll have to create new ones that have the right properties. still not happy with model since besides not having child associations in place, i don't have a way of differentiating between the generated xmls and the other generated assets. major bug. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@4138 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- project-build.xml | 3 + .../alfresco/web/bean/wcm/AVMEditBean.java | 3 +- .../web/bean/wcm/CreateWebContentWizard.java | 28 ++- .../alfresco/web/templating/OutputUtil.java | 35 ++-- .../alfresco/web/templating/TemplateType.java | 7 +- .../web/templating/TemplatingService.java | 18 +- .../extension/ExtensionFunctions.java | 143 +++++++++++++ ...rvletContextExtensionFunctionsAdapter.java | 65 ++++++ .../templating/xforms/TemplateTypeImpl.java | 5 + .../templating/xforms/XSLTOutputMethod.java | 192 +++++++++++++++++- .../alfresco/web/pr/CompanyFooterBean.java | 31 +-- .../org/alfresco/web/pr/PressReleaseBean.java | 42 ++-- .../classes/org/alfresco/web/pr/Util.java | 83 -------- .../output-method-callout.xsd | 11 + .../output-method-callout.xsl | 50 +++++ .../configure-template-output-methods.jsp | 4 +- source/web/jsp/wcm/edit-xml-inline.jsp | 9 +- 17 files changed, 552 insertions(+), 177 deletions(-) create mode 100644 source/java/org/alfresco/web/templating/extension/ExtensionFunctions.java create mode 100644 source/java/org/alfresco/web/templating/extension/ServletContextExtensionFunctionsAdapter.java delete mode 100644 source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/Util.java create mode 100644 source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsd create mode 100644 source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsl diff --git a/project-build.xml b/project-build.xml index 80d3d01658..4ee04fccbf 100644 --- a/project-build.xml +++ b/project-build.xml @@ -115,6 +115,9 @@ deprecation="on" debug="on" target="1.5" source="1.5" classpathref="classpath.compile"/> + diff --git a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java index fd1b00f93a..bb85322d51 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java @@ -24,6 +24,7 @@ import javax.faces.event.ActionEvent; import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMModel; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.service.cmr.avm.AVMService; @@ -309,7 +310,7 @@ public class AVMEditBean tx.commit(); // TODO: regenerate template content - if (nodeService.getProperty(avmRef, TemplatingService.TT_QNAME) != null) + if (nodeService.getProperty(avmRef, WCMModel.PROP_TEMPLATE_DERIVED_FROM) != null) { OutputUtil.regenerate(avmRef, this.contentService, diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java index c900179148..bf854b18c6 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java @@ -36,6 +36,7 @@ import org.alfresco.config.Config; import org.alfresco.config.ConfigElement; import org.alfresco.config.ConfigService; import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMModel; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.service.cmr.avm.AVMService; @@ -102,18 +103,23 @@ public class CreateWebContentWizard extends BaseContentWizard { if (logger.isDebugEnabled()) logger.debug("generating template output for " + this.templateTypeName); - this.nodeService.setProperty(AVMNodeConverter.ToNodeRef(-1, this.createdPath), - TemplatingService.TT_QNAME, - this.templateTypeName); - TemplatingService ts = TemplatingService.getInstance(); - TemplateType tt = this.getTemplateType(); + final TemplateType tt = this.getTemplateType(); + final TemplatingService ts = TemplatingService.getInstance(); + + final Map props = new HashMap(); + props.put(WCMModel.PROP_TEMPLATE_DERIVED_FROM, tt.getNodeRef()); + props.put(WCMModel.PROP_TEMPLATE_DERIVED_FROM_NAME, tt.getName()); + this.nodeService.addAspect(AVMNodeConverter.ToNodeRef(-1, this.createdPath), + WCMModel.ASPECT_TEMPLATE_DERIVED, + props); + OutputUtil.generate(this.createdPath.substring(0, this.createdPath.lastIndexOf('/')), - ts.parseXML(this.content), - tt, - this.fileName, - this.contentService, - this.nodeService, - this.avmService); + ts.parseXML(this.content), + tt, + this.fileName, + this.contentService, + this.nodeService, + this.avmService); } // return the default outcome diff --git a/source/java/org/alfresco/web/templating/OutputUtil.java b/source/java/org/alfresco/web/templating/OutputUtil.java index 003cb25127..b736b9ab77 100644 --- a/source/java/org/alfresco/web/templating/OutputUtil.java +++ b/source/java/org/alfresco/web/templating/OutputUtil.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.Map; import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMModel; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.service.cmr.avm.AVMNotFoundException; import org.alfresco.service.cmr.avm.AVMService; @@ -77,24 +78,21 @@ public class OutputUtil final OutputStreamWriter out = new OutputStreamWriter(fileOut); final HashMap parameters = - getOutputMethodParameters(sandBoxUrl, fileName, generatedFileName); + getOutputMethodParameters(sandBoxUrl, fileName, generatedFileName, parentPath); tom.generate(xml, tt, parameters, out); out.close(); NodeRef outputNodeRef = AVMNodeConverter.ToNodeRef(-1, fullAvmPath); - nodeService.setProperty(outputNodeRef, - TemplatingService.TT_QNAME, - tt.getName()); - Map titledProps = new HashMap(1, 1.0f); - titledProps.put(ContentModel.PROP_TITLE, fileName); - nodeService.addAspect(outputNodeRef, ContentModel.ASPECT_TITLED, titledProps); + Map props = new HashMap(); + props.put(WCMModel.PROP_TEMPLATE_DERIVED_FROM, tt.getNodeRef()); + props.put(WCMModel.PROP_TEMPLATE_DERIVED_FROM_NAME, tt.getName()); + nodeService.addAspect(outputNodeRef, WCMModel.ASPECT_TEMPLATE_DERIVED, props); + + props = new HashMap(1, 1.0f); + props.put(ContentModel.PROP_TITLE, fileName); + nodeService.addAspect(outputNodeRef, ContentModel.ASPECT_TITLED, props); LOGGER.debug("generated " + generatedFileName + " using " + tom); - - NodeRef createdNodeRef = AVMNodeConverter.ToNodeRef(-1, parentPath + '/' + fileName); - nodeService.setProperty(createdNodeRef, - TemplatingService.TT_GENERATED_OUTPUT_QNAME, - outputNodeRef.toString()); } } catch (Exception e) @@ -114,9 +112,10 @@ public class OutputUtil try { final TemplatingService ts = TemplatingService.getInstance(); - final String templateTypeName = (String) - nodeService.getProperty(nodeRef, TemplatingService.TT_QNAME); - final TemplateType tt = ts.getTemplateType(templateTypeName); + final NodeRef templateTypeNodeRef = (NodeRef) + nodeService.getProperty(nodeRef, WCMModel.PROP_TEMPLATE_DERIVED_FROM); + + final TemplateType tt = ts.getTemplateType(templateTypeNodeRef); final ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT); final Document xml = ts.parseXML(reader.getContentInputStream()); @@ -147,7 +146,7 @@ public class OutputUtil final OutputStreamWriter writer = new OutputStreamWriter(out); final HashMap parameters = - getOutputMethodParameters(sandBoxUrl, fileName, generatedFileName); + getOutputMethodParameters(sandBoxUrl, fileName, generatedFileName, parentPath); tom.generate(xml, tt, parameters, writer); writer.close(); LOGGER.debug("generated " + fileName + " using " + tom); @@ -163,12 +162,14 @@ public class OutputUtil private static HashMap getOutputMethodParameters(final String sandBoxUrl, final String fileName, - final String generatedFileName) + final String generatedFileName, + final String parentPath) { final HashMap parameters = new HashMap(); parameters.put("avm_store_url", sandBoxUrl); parameters.put("derived_from_file_name", fileName); parameters.put("generated_file_name", generatedFileName); + parameters.put("parent_path", parentPath); return parameters; } } diff --git a/source/java/org/alfresco/web/templating/TemplateType.java b/source/java/org/alfresco/web/templating/TemplateType.java index f33e31c715..2f91f028cf 100644 --- a/source/java/org/alfresco/web/templating/TemplateType.java +++ b/source/java/org/alfresco/web/templating/TemplateType.java @@ -16,10 +16,11 @@ */ package org.alfresco.web.templating; +import org.alfresco.service.cmr.repository.NodeRef; import org.w3c.dom.Document; -import java.util.List; -import java.net.URI; import java.io.Serializable; +import java.net.URI; +import java.util.List; /** * Encapsulation of a template type. @@ -37,6 +38,8 @@ public interface TemplateType /** the xml schema for this template type */ public Document getSchema(); + public NodeRef getNodeRef(); + //XXXarielb not used currently and not sure if it's necessary... // public void addInputMethod(final TemplateInputMethod in); diff --git a/source/java/org/alfresco/web/templating/TemplatingService.java b/source/java/org/alfresco/web/templating/TemplatingService.java index 8baf9cbf7d..2c9d4dfaa4 100644 --- a/source/java/org/alfresco/web/templating/TemplatingService.java +++ b/source/java/org/alfresco/web/templating/TemplatingService.java @@ -55,19 +55,6 @@ import org.alfresco.web.bean.repository.Repository; public final class TemplatingService implements Serializable { - /** - * temporary location of the property on nodes that are xml files created - * by templating. - */ - public static final org.alfresco.service.namespace.QName TT_QNAME = - org.alfresco.service.namespace.QName.createQName(org.alfresco.service.namespace.NamespaceService.CONTENT_MODEL_1_0_URI, "tt"); - - /** - * temporary location of the property on nodes generated from xml assets. - */ - public static final org.alfresco.service.namespace.QName TT_GENERATED_OUTPUT_QNAME = - org.alfresco.service.namespace.QName.createQName(org.alfresco.service.namespace.NamespaceService.CONTENT_MODEL_1_0_URI, "tt_generated_output"); - private static final Log LOGGER = LogFactory.getLog(TemplatingService.class); /** the single instance initialized using spring */ @@ -193,6 +180,11 @@ public final class TemplatingService implements Serializable throw re; } } + + public TemplateType getTemplateType(final NodeRef nodeRef) + { + return this.newTemplateType(nodeRef); + } /** * instantiate a template type. for now this will always generate the diff --git a/source/java/org/alfresco/web/templating/extension/ExtensionFunctions.java b/source/java/org/alfresco/web/templating/extension/ExtensionFunctions.java new file mode 100644 index 0000000000..6afe6636a1 --- /dev/null +++ b/source/java/org/alfresco/web/templating/extension/ExtensionFunctions.java @@ -0,0 +1,143 @@ +/* + * 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.templating.extension; + +import org.alfresco.model.WCMModel; +import org.alfresco.repo.avm.AVMRemote; +import org.alfresco.repo.avm.AVMRemoteInputStream; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMNotFoundException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.*; +import org.xml.sax.SAXException; +import javax.xml.parsers.*; +import java.io.*; +import java.util.Map; +import java.util.HashMap; + +public class ExtensionFunctions +{ + private static final Log LOGGER = LogFactory.getLog(ExtensionFunctions.class); + + private static DocumentBuilder documentBuilder; + + private final AVMRemote avmRemote; + + public ExtensionFunctions(final AVMRemote avmRemote) + { + this.avmRemote = avmRemote; + } + + public Document getXMLDocument(final String avmPath) + throws IOException, + SAXException + { + final DocumentBuilder db = this.getDocumentBuilder(); + final InputStream istream = + new AVMRemoteInputStream(this.avmRemote.getInputHandle(-1, avmPath), + this.avmRemote); + + Document result; + try + { + return db.parse(istream); + } + finally + { + istream.close(); + } + } + + public Map getXMLDocuments(final String templateTypeName, final String avmPath) + throws IOException, + SAXException + { + final Map entries = + this.avmRemote.getDirectoryListing(-1, avmPath); + final DocumentBuilder db = this.getDocumentBuilder(); + final Map result = new HashMap(); + for (Map.Entry entry : entries.entrySet()) + { + final String entryName = entry.getKey(); + AVMNodeDescriptor entryNode = entry.getValue(); + if (entryNode.isFile()) + { + final PropertyValue pv = + this.avmRemote.getNodeProperty(-1, + avmPath + '/' + entryName, + WCMModel.PROP_TEMPLATE_DERIVED_FROM_NAME); + if (pv != null && + pv.getStringValue() != null && + ((String)pv.getStringValue()).equals(templateTypeName)) + { + + InputStream istream = null; + try + { + istream = new AVMRemoteInputStream(this.avmRemote.getInputHandle(-1, avmPath + '/' + entryName), + this.avmRemote); + } + catch (AVMNotFoundException avmnfe) + { + // this is most likely happening because this is the current file we're generating + // and the avm is telling us that it has no content yet. we won't hit this once + // we have a way of distinguishing templateoutputmethodgenerated + // from templategenerated + LOGGER.debug("skipping "+ entryName, avmnfe); + } + try + { + result.put(entryName, db.parse(istream)); + } + catch (SAXException sax) + { + // this is most likely happening because we have the same property for defined + // for tempalteoutputmethodderived and templatederived so we can't distinguish them right now + // need to clean this up + LOGGER.debug("error parsing " + entryName+ "... skipping", sax); + } + finally + { + istream.close(); + } + } + } + } + return result; + } + + private static DocumentBuilder getDocumentBuilder() + { + if (ExtensionFunctions.documentBuilder == null) + { + try + { + final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + ExtensionFunctions.documentBuilder = dbf.newDocumentBuilder(); + } + catch (ParserConfigurationException pce) + { + LOGGER.error(pce); + } + } + return ExtensionFunctions.documentBuilder; + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/web/templating/extension/ServletContextExtensionFunctionsAdapter.java b/source/java/org/alfresco/web/templating/extension/ServletContextExtensionFunctionsAdapter.java new file mode 100644 index 0000000000..0cd9ff925a --- /dev/null +++ b/source/java/org/alfresco/web/templating/extension/ServletContextExtensionFunctionsAdapter.java @@ -0,0 +1,65 @@ +/* + * 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.templating.extension; + +import org.alfresco.jndi.AVMFileDirContext; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; +import javax.servlet.ServletContext; +import java.io.IOException; +import java.util.Map; + +public class ServletContextExtensionFunctionsAdapter + extends ExtensionFunctions +{ + + private final ServletContext servletContext; + + public ServletContextExtensionFunctionsAdapter(final ServletContext servletContext) + { + super(AVMFileDirContext.getAVMRemote()); + this.servletContext = servletContext; + } + + private String toAVMPath(String path) + { + // The real_path will look somethign like this: + // /alfresco.avm/avm.alfresco.localhost/$-1$alfreco-guest-main:/appBase/avm_webapps/my_webapp + path = this.servletContext.getRealPath(path); + + // The avm_path to the root of the context will look something like this: + // alfreco-guest-main:/appBase/avm_webapps/my_webapp + path = path.substring(path.indexOf('$', path.indexOf('$') + 1) + 1); + path = path.replace('\\','/'); + return path; + } + + public Document getXMLDocument(final String path) + throws IOException, + SAXException + { + return super.getXMLDocument(this.toAVMPath(path)); + } + + public Map getXMLDocuments(final String templateTypeName, + final String path) + throws IOException, + SAXException + { + return super.getXMLDocuments(templateTypeName, this.toAVMPath(path)); + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/web/templating/xforms/TemplateTypeImpl.java b/source/java/org/alfresco/web/templating/xforms/TemplateTypeImpl.java index 4a0a020889..86caaa24a8 100644 --- a/source/java/org/alfresco/web/templating/xforms/TemplateTypeImpl.java +++ b/source/java/org/alfresco/web/templating/xforms/TemplateTypeImpl.java @@ -84,6 +84,11 @@ public class TemplateTypeImpl return this.schema; } + public NodeRef getNodeRef() + { + return this.schemaNodeRef; + } + public List getInputMethods() { return INPUT_METHODS; diff --git a/source/java/org/alfresco/web/templating/xforms/XSLTOutputMethod.java b/source/java/org/alfresco/web/templating/xforms/XSLTOutputMethod.java index 74dc93e96d..287467a227 100644 --- a/source/java/org/alfresco/web/templating/xforms/XSLTOutputMethod.java +++ b/source/java/org/alfresco/web/templating/xforms/XSLTOutputMethod.java @@ -19,7 +19,7 @@ package org.alfresco.web.templating.xforms; import java.io.*; import java.net.URI; import java.net.URISyntaxException; -import java.util.Map; +import java.util.*; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.Templates; @@ -34,20 +34,28 @@ import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.alfresco.model.WCMModel; +import org.alfresco.repo.avm.AVMRemote; 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.templating.*; +import org.alfresco.web.templating.extension.ExtensionFunctions; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.chiba.xml.util.DOMUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Node; +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; public class XSLTOutputMethod implements TemplateOutputMethod { + private static final String ALFRESCO_NS = "http://www.alfresco.org/alfresco"; + private static final String ALFRESCO_NS_PREFIX = "alfresco"; private static final Log LOGGER = LogFactory.getLog(XSLTOutputMethod.class); @@ -62,6 +70,170 @@ public class XSLTOutputMethod this.nodeService = nodeService; } + //XXXarielb this is totally dirty - need to figure a better way to do this + private static AVMRemote getAVMRemote() + { + final javax.faces.context.FacesContext fc = + javax.faces.context.FacesContext.getCurrentInstance(); + final org.springframework.web.context.WebApplicationContext wac = + org.springframework.web.jsf.FacesContextUtils.getRequiredWebApplicationContext(fc); + return (AVMRemote)wac.getBean("avmRemote"); + } + + private static ExtensionFunctions getExtensionFunctions() + { + return new ExtensionFunctions(XSLTOutputMethod.getAVMRemote()); + } + + private static String toAVMPath(final ExpressionContext ec, String path) + throws TransformerException + { + final XObject o = ec.getVariableOrParam(new QName("parent_path")); + if (o == null) + return null; + String avmPath = o.toString(); + if (path != null && path.length() != 0 && path.charAt(0) == '/') + { + avmPath = avmPath.substring(0, + avmPath.indexOf(':') + + ('/' + AVMConstants.DIR_APPBASE + + '/' + AVMConstants.DIR_WEBAPPS).length() + 1); + } + return avmPath + (avmPath.endsWith("/") ? path : '/' + path); + } + + public static Document getXMLDocument(final ExpressionContext ec, final String path) + throws TransformerException, + IOException, + SAXException + { + final ExtensionFunctions ef = XSLTOutputMethod.getExtensionFunctions(); + return ef.getXMLDocument(XSLTOutputMethod.toAVMPath(ec, path)); + } + + public static NodeIterator getXMLDocuments(final ExpressionContext ec, + final String templateTypeName, + String path) + throws TransformerException, + IOException, + SAXException + { + final ExtensionFunctions ef = XSLTOutputMethod.getExtensionFunctions(); + path = XSLTOutputMethod.toAVMPath(ec, path); + final Map resultMap = ef.getXMLDocuments(templateTypeName, path); + LOGGER.debug("received " + resultMap.size() + " documents in " + path); + final List> documents = + new ArrayList>(resultMap.entrySet()); + + return new NodeIterator() + { + private int index = 0; + private boolean detached = false; + + public void detach() + { + 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() + { + LOGGER.error("NodeIterator.getRoot() unexpectedly called"); + throw new UnsupportedOperationException(); + } + + public int getWhatToShow() + { + return NodeFilter.SHOW_ALL; + } + + public Node nextNode() + throws DOMException + { + LOGGER.debug("NodeIterator.nextNode(" + index + ")"); + if (this.detached) + throw new DOMException(DOMException.INVALID_STATE_ERR, null); + if (index == documents.size()) + return null; + return this.getNodeAt(index++); + } + + public Node previousNode() + throws DOMException + { + LOGGER.debug("NodeIterator.previousNode(" + index + ")"); + if (this.detached) + throw new DOMException(DOMException.INVALID_STATE_ERR, null); + if (index == -1) + return null; + return this.getNodeAt(index--); + } + + private Document getNodeAt(int index) + { + final Document d = documents.get(index).getValue(); + final Element documentEl = d.getDocumentElement(); + documentEl.setAttribute("xmlns:" + ALFRESCO_NS_PREFIX, ALFRESCO_NS); + documentEl.setAttributeNS(ALFRESCO_NS, + ALFRESCO_NS_PREFIX + ":file-name", + documents.get(index).getKey()); + return d; + } + }; + } + + private void addScript(final Document d) + { + final Element docEl = d.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 = d.createElementNS(XALAN_NS, XALAN_NS_PREFIX + ":component"); + compEl.setAttribute("prefix", "alfresco"); + docEl.appendChild(compEl); + + final Element scriptEl = d.createElementNS(XALAN_NS, XALAN_NS_PREFIX + ":script"); + scriptEl.setAttribute("lang", "javaclass"); + scriptEl.setAttribute("src", XALAN_NS_PREFIX + "://" + this.getClass().getName()); + compEl.appendChild(scriptEl); + } + + private void addParameters(final Map parameters, + final Document xslDocument) + { + final Element docEl = xslDocument.getDocumentElement(); + final String XSL_NS = docEl.getNamespaceURI(); + final String XSL_NS_PREFIX = docEl.getPrefix(); + + for (Map.Entry e : parameters.entrySet()) + { + final Element el = xslDocument.createElementNS(XSL_NS, XSL_NS_PREFIX + ":variable"); + el.setAttribute("name", e.getKey()); + el.appendChild(xslDocument.createTextNode(e.getValue())); + docEl.insertBefore(el, docEl.getFirstChild()); + } + } + public void generate(final Document xmlContent, final TemplateType tt, final Map parameters, @@ -76,7 +248,11 @@ public class XSLTOutputMethod final String sandBoxUrl = (String)parameters.get("avm_store_url"); final TransformerFactory tf = TransformerFactory.newInstance(); final TemplatingService ts = TemplatingService.getInstance(); - final DOMSource source = new DOMSource(ts.parseXML(this.nodeRef)); + final Document xslDocument = ts.parseXML(this.nodeRef); + this.addScript(xslDocument); + this.addParameters(parameters, xslDocument); + + final DOMSource source = new DOMSource(xslDocument); final Templates templates = tf.newTemplates(source); final Transformer t = templates.newTransformer(); t.setURIResolver(new URIResolver() @@ -108,12 +284,6 @@ public class XSLTOutputMethod } }); - for (Map.Entry e : parameters.entrySet()) - { - t.setParameter(e.getKey(), e.getValue()); - } - - LOGGER.debug("setting parameter avm_store_url=" + sandBoxUrl); final StreamResult result = new StreamResult(out); try { diff --git a/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/CompanyFooterBean.java b/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/CompanyFooterBean.java index f39062eff4..f46c6ad04d 100644 --- a/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/CompanyFooterBean.java +++ b/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/CompanyFooterBean.java @@ -19,6 +19,7 @@ package org.alfresco.web.pr; import java.util.*; import javax.servlet.jsp.PageContext; import org.w3c.dom.*; +import org.alfresco.web.templating.extension.*; public class CompanyFooterBean { @@ -26,20 +27,22 @@ public class CompanyFooterBean public static List getCompanyFooters(final PageContext pageContext) throws Exception { - final Map entries = Util.loadXMLDocuments(pageContext, - "/media/releases/content/company_footers", - "alfresco:company-footer"); - final List result = new ArrayList(entries.size()); - for (Map.Entry entry : entries.entrySet()) - { - String fileName = entry.getKey(); - Document d = entry.getValue(); - Element n = (Element)d.getElementsByTagName("alfresco:name").item(0); - String href = "/media/releases/content/company_footers/" + fileName; - result.add(new CompanyFooterBean(n.getFirstChild().getNodeValue(), - href)); - } - return result; + final ExtensionFunctions ef = + new ServletContextExtensionFunctionsAdapter(pageContext.getServletContext()); + + final Map entries = ef.getXMLDocuments("company-footer", + "/media/releases/content/company_footers"); + final List result = new ArrayList(entries.size()); + for (Map.Entry entry : entries.entrySet()) + { + final String fileName = entry.getKey(); + final Document d = entry.getValue(); + final Element n = (Element)d.getElementsByTagName("alfresco:name").item(0); + final String href = "/media/releases/content/company_footers/" + fileName; + result.add(new CompanyFooterBean(n.getFirstChild().getNodeValue(), + href)); + } + return result; } private final String name; diff --git a/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/PressReleaseBean.java b/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/PressReleaseBean.java index 6655fa3adf..7e1acceba8 100644 --- a/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/PressReleaseBean.java +++ b/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/PressReleaseBean.java @@ -20,32 +20,34 @@ import java.util.*; import java.text.*; import javax.servlet.jsp.PageContext; import org.w3c.dom.*; +import org.alfresco.web.templating.extension.*; public class PressReleaseBean { public static List getPressReleases(final PageContext pageContext) throws Exception { - final Map entries = Util.loadXMLDocuments(pageContext, - "/media/releases/content", - "alfresco:press-release"); - final List result = new ArrayList(entries.size()); - for (Map.Entry entry : entries.entrySet() ) - { - String fileName = entry.getKey(); - Document d = entry.getValue(); - Element t = (Element)d.getElementsByTagName("alfresco:title").item(0); - Element a = (Element)d.getElementsByTagName("alfresco:abstract").item(0); - Element dateEl = (Element)d.getElementsByTagName("alfresco:launch_date").item(0); - Date date = new SimpleDateFormat("yyyy-MM-dd").parse(dateEl.getFirstChild().getNodeValue()); - String href = "/media/releases/content/" + fileName; - href = href.replaceAll(".xml$", ".shtml"); - result.add(new PressReleaseBean(t.getFirstChild().getNodeValue(), - a.getFirstChild().getNodeValue(), - date, - href)); - } - return result; + final ExtensionFunctions ef = + new ServletContextExtensionFunctionsAdapter(pageContext.getServletContext()); + + final Map entries = ef.getXMLDocuments("press-release", "/media/releases/content"); + final List result = new ArrayList(entries.size()); + for (Map.Entry entry : entries.entrySet() ) + { + final String fileName = entry.getKey(); + final Document d = entry.getValue(); + final Element t = (Element)d.getElementsByTagName("alfresco:title").item(0); + final Element a = (Element)d.getElementsByTagName("alfresco:abstract").item(0); + final Element dateEl = (Element)d.getElementsByTagName("alfresco:launch_date").item(0); + final Date date = new SimpleDateFormat("yyyy-MM-dd").parse(dateEl.getFirstChild().getNodeValue()); + String href = "/media/releases/content/" + fileName; + href = href.replaceAll(".xml$", ".shtml"); + result.add(new PressReleaseBean(t.getFirstChild().getNodeValue(), + a.getFirstChild().getNodeValue(), + date, + href)); + } + return result; } private final String title; diff --git a/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/Util.java b/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/Util.java deleted file mode 100644 index 0024bd9aed..0000000000 --- a/source/test-resources/websites/alfresco/ROOT/WEB-INF/classes/org/alfresco/web/pr/Util.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.pr; - -import javax.servlet.*; -import javax.servlet.http.*; -import javax.servlet.jsp.PageContext; -import java.io.*; -import java.util.*; -import org.alfresco.jndi.*; -import org.alfresco.repo.avm.AVMRemote; -import org.alfresco.service.cmr.avm.AVMNodeDescriptor; -import org.w3c.dom.*; -import javax.xml.parsers.*; - -public class Util -{ - - public static Map loadXMLDocuments(final PageContext pageContext, - final String path, - final String documentElementNodeName) - throws Exception - { - final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - dbf.setValidating(false); - final DocumentBuilder db = dbf.newDocumentBuilder(); - - // The real_path will look somethign like this: - // /alfresco.avm/avm.alfresco.localhost/$-1$alfreco-guest-main:/appBase/avm_webapps/my_webapp - final String realPath = pageContext.getServletContext().getRealPath(path); - - // The avm_path to the root of the context will look something like this: - // alfreco-guest-main:/appBase/avm_webapps/my_webapp - String avmPath = realPath.substring(realPath.indexOf('$', realPath.indexOf('$') + 1) + 1); - avmPath = avmPath.replace('\\','/'); - - final AVMRemote avm_remote = AVMFileDirContext.getAVMRemote(); - final Map entries = avm_remote.getDirectoryListing(-1, avmPath); - - Map result = new HashMap(); - for (Map.Entry entry : entries.entrySet() ) - { - final String entryName = entry.getKey(); - AVMNodeDescriptor entryNode = entry.getValue(); - if (entryNode.isFile()) - { - final InputStream istream = - new AVMRemoteInputStream(avm_remote.getInputHandle(-1, avmPath + '/' + entryName), - avm_remote ); - try - { - final Document d = db.parse(istream); - if (documentElementNodeName.equals(d.getDocumentElement().getNodeName())) - result.put(entryName, d); - } - catch (Throwable t) - { - t.printStackTrace(); - } - finally - { - istream.close(); - } - } - } - return result; - } -} \ No newline at end of file diff --git a/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsd b/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsd new file mode 100644 index 0000000000..bb2ca1c8dd --- /dev/null +++ b/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsd @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsl b/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsl new file mode 100644 index 0000000000..5d4d1b35c0 --- /dev/null +++ b/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.xsl @@ -0,0 +1,50 @@ + + + + + + + my_variable has a value + my_variable_as_arg has a value + + + + + Simple Test + + +
Generated by output-method-callout.xsl
+
My value accessed using /simple/string:
+ +
My value accessed using alfresco:getXMLDocument():
+ +
Values from xml files generated by in :
+
    + +
  • =
  • +
    +
+ + +
+
diff --git a/source/web/jsp/wcm/create-form-wizard/configure-template-output-methods.jsp b/source/web/jsp/wcm/create-form-wizard/configure-template-output-methods.jsp index 10ba74c04b..2b48ca48fd 100644 --- a/source/web/jsp/wcm/create-form-wizard/configure-template-output-methods.jsp +++ b/source/web/jsp/wcm/create-form-wizard/configure-template-output-methods.jsp @@ -64,7 +64,9 @@ if (upload == null || upload.getFile() == null) <% -} else { +} +else +{ %> diff --git a/source/web/jsp/wcm/edit-xml-inline.jsp b/source/web/jsp/wcm/edit-xml-inline.jsp index 259fe8f287..b575376664 100644 --- a/source/web/jsp/wcm/edit-xml-inline.jsp +++ b/source/web/jsp/wcm/edit-xml-inline.jsp @@ -24,9 +24,10 @@ <%@ page isELIgnored="false" %> <%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> <%@ page import="org.alfresco.web.bean.wcm.*, + org.alfresco.model.WCMModel, org.alfresco.service.cmr.repository.*, - org.alfresco.web.bean.content.*, - org.alfresco.web.templating.*" %> + org.alfresco.web.bean.content.*, + org.alfresco.web.templating.*" %> <%@ page import="java.io.*" %> <%@ page import="org.alfresco.web.app.Application" %> <%@ page import="org.alfresco.web.templating.*" %> @@ -35,9 +36,9 @@ final AVMBrowseBean browseBean = (AVMBrowseBean)session.getAttribute("AVMBrowseBean"); NodeRef nr = browseBean.getAvmActionNode().getNodeRef(); final AVMEditBean editBean = (AVMEditBean)session.getAttribute("AVMEditBean"); -String ttName = (String)browseBean.getNodeService().getProperty(nr, TemplatingService.TT_QNAME); +final NodeRef ttNodeRef = (NodeRef)browseBean.getNodeService().getProperty(nr, WCMModel.PROP_TEMPLATE_DERIVED_FROM); final TemplatingService ts = TemplatingService.getInstance(); -final TemplateType tt = ts.getTemplateType(ttName); +final TemplateType tt = ts.getTemplateType(ttNodeRef); TemplateInputMethod tim = tt.getInputMethods().get(0); final InstanceData instanceData = new InstanceData() {