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 }