001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: ElemExsltFunction.java 468643 2006-10-28 06:56:03Z minchau $
020 */
021 package org.apache.xalan.templates;
022
023 import javax.xml.transform.TransformerException;
024
025 import org.apache.xalan.extensions.ExtensionNamespaceSupport;
026 import org.apache.xalan.transformer.TransformerImpl;
027 import org.apache.xpath.VariableStack;
028 import org.apache.xpath.XPathContext;
029 import org.apache.xpath.objects.XObject;
030
031 import org.w3c.dom.Node;
032 import org.w3c.dom.NodeList;
033
034
035 /**
036 * Implement func:function.
037 * @xsl.usage advanced
038 */
039 public class ElemExsltFunction extends ElemTemplate
040 {
041 static final long serialVersionUID = 272154954793534771L;
042 /**
043 * Get an integer representation of the element type.
044 *
045 * @return An integer representation of the element, defined in the
046 * Constants class.
047 * @see org.apache.xalan.templates.Constants
048 */
049 public int getXSLToken()
050 {
051 return Constants.EXSLT_ELEMNAME_FUNCTION;
052 }
053
054 /**
055 * Return the node name, defined in the
056 * Constants class.
057 * @see org.apache.xalan.templates.Constants
058 * @return The node name
059 *
060 */
061 public String getNodeName()
062 {
063 return Constants.EXSLT_ELEMNAME_FUNCTION_STRING;
064 }
065
066 public void execute(TransformerImpl transformer, XObject[] args)
067 throws TransformerException
068 {
069 XPathContext xctxt = transformer.getXPathContext();
070 VariableStack vars = xctxt.getVarStack();
071
072 // Increment the frame bottom of the variable stack by the
073 // frame size
074 int thisFrame = vars.getStackFrame();
075 int nextFrame = vars.link(m_frameSize);
076
077 if (m_inArgsSize < args.length) {
078 throw new TransformerException ("function called with too many args");
079 }
080
081 // Set parameters,
082 // have to clear the section of the stack frame that has params.
083 if (m_inArgsSize > 0) {
084 vars.clearLocalSlots(0, m_inArgsSize);
085
086 if (args.length > 0) {
087 vars.setStackFrame(thisFrame);
088 NodeList children = this.getChildNodes();
089
090 for (int i = 0; i < args.length; i ++) {
091 Node child = children.item(i);
092 if (children.item(i) instanceof ElemParam) {
093 ElemParam param = (ElemParam)children.item(i);
094 vars.setLocalVariable(param.getIndex(), args[i], nextFrame);
095 }
096 }
097
098 vars.setStackFrame(nextFrame);
099 }
100 }
101
102 // Removed ElemTemplate 'push' and 'pop' of RTFContext, in order to avoid losing the RTF context
103 // before a value can be returned. ElemExsltFunction operates in the scope of the template that called
104 // the function.
105 // xctxt.pushRTFContext();
106
107 if (transformer.getDebug())
108 transformer.getTraceManager().fireTraceEvent(this);
109
110 vars.setStackFrame(nextFrame);
111 transformer.executeChildTemplates(this, true);
112
113 // Reset the stack frame after the function call
114 vars.unlink(thisFrame);
115
116 if (transformer.getDebug())
117 transformer.getTraceManager().fireTraceEndEvent(this);
118
119 // Following ElemTemplate 'pop' removed -- see above.
120 // xctxt.popRTFContext();
121
122 }
123
124 /**
125 * Called after everything else has been
126 * recomposed, and allows the function to set remaining
127 * values that may be based on some other property that
128 * depends on recomposition.
129 */
130 public void compose(StylesheetRoot sroot) throws TransformerException
131 {
132 super.compose(sroot);
133
134 // Register the function namespace (if not already registered).
135 String namespace = getName().getNamespace();
136 String handlerClass = sroot.getExtensionHandlerClass();
137 Object[] args ={namespace, sroot};
138 ExtensionNamespaceSupport extNsSpt =
139 new ExtensionNamespaceSupport(namespace, handlerClass, args);
140 sroot.getExtensionNamespacesManager().registerExtension(extNsSpt);
141 // Make sure there is a handler for the EXSLT functions namespace
142 // -- for isElementAvailable().
143 if (!(namespace.equals(Constants.S_EXSLT_FUNCTIONS_URL)))
144 {
145 namespace = Constants.S_EXSLT_FUNCTIONS_URL;
146 args = new Object[]{namespace, sroot};
147 extNsSpt = new ExtensionNamespaceSupport(namespace, handlerClass, args);
148 sroot.getExtensionNamespacesManager().registerExtension(extNsSpt);
149 }
150 }
151 }