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: ElemExtensionCall.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.ExtensionHandler; 026 import org.apache.xalan.extensions.ExtensionsTable; 027 import org.apache.xalan.res.XSLMessages; 028 import org.apache.xalan.res.XSLTErrorResources; 029 import org.apache.xalan.transformer.TransformerImpl; 030 import org.apache.xpath.XPathContext; 031 import org.xml.sax.SAXException; 032 033 /** 034 * Implement an extension element. 035 * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a> 036 * @xsl.usage advanced 037 */ 038 public class ElemExtensionCall extends ElemLiteralResult 039 { 040 static final long serialVersionUID = 3171339708500216920L; 041 042 /** The Namespace URI for this extension call element. 043 * @serial */ 044 String m_extns; 045 046 /** Language used by extension. 047 * @serial */ 048 String m_lang; 049 050 /** URL pointing to extension. 051 * @serial */ 052 String m_srcURL; 053 054 /** Source for script. 055 * @serial */ 056 String m_scriptSrc; 057 058 /** Declaration for Extension element. 059 * @serial */ 060 ElemExtensionDecl m_decl = null; 061 062 /** 063 * Get an int constant identifying the type of element. 064 * @see org.apache.xalan.templates.Constants 065 * 066 *@return The token ID for this element 067 */ 068 public int getXSLToken() 069 { 070 return Constants.ELEMNAME_EXTENSIONCALL; 071 } 072 073 /** 074 * Return the node name. 075 * 076 * @return The element's name 077 */ 078 079 // public String getNodeName() 080 // { 081 // TODO: Need prefix. 082 // return localPart; 083 // } 084 085 /** 086 * This function is called after everything else has been 087 * recomposed, and allows the template to set remaining 088 * values that may be based on some other property that 089 * depends on recomposition. 090 */ 091 public void compose(StylesheetRoot sroot) throws TransformerException 092 { 093 super.compose(sroot); 094 m_extns = this.getNamespace(); 095 m_decl = getElemExtensionDecl(sroot, m_extns); 096 // Register the extension namespace if the extension does not have 097 // an ElemExtensionDecl ("component"). 098 if (m_decl == null) 099 sroot.getExtensionNamespacesManager().registerExtension(m_extns); 100 } 101 102 /** 103 * Return the ElemExtensionDecl for this extension element 104 * 105 * 106 * @param stylesheet Stylesheet root associated with this extension element 107 * @param namespace Namespace associated with this extension element 108 * 109 * @return the ElemExtensionDecl for this extension element. 110 */ 111 private ElemExtensionDecl getElemExtensionDecl(StylesheetRoot stylesheet, 112 String namespace) 113 { 114 115 ElemExtensionDecl decl = null; 116 int n = stylesheet.getGlobalImportCount(); 117 118 for (int i = 0; i < n; i++) 119 { 120 Stylesheet imported = stylesheet.getGlobalImport(i); 121 122 for (ElemTemplateElement child = imported.getFirstChildElem(); 123 child != null; child = child.getNextSiblingElem()) 124 { 125 if (Constants.ELEMNAME_EXTENSIONDECL == child.getXSLToken()) 126 { 127 decl = (ElemExtensionDecl) child; 128 129 String prefix = decl.getPrefix(); 130 String declNamespace = child.getNamespaceForPrefix(prefix); 131 132 if (namespace.equals(declNamespace)) 133 { 134 return decl; 135 } 136 } 137 } 138 } 139 140 return null; 141 } 142 143 /** 144 * Execute the fallbacks when an extension is not available. 145 * 146 * @param transformer non-null reference to the the current transform-time state. 147 * 148 * @throws TransformerException 149 */ 150 private void executeFallbacks( 151 TransformerImpl transformer) 152 throws TransformerException 153 { 154 for (ElemTemplateElement child = m_firstChild; child != null; 155 child = child.m_nextSibling) 156 { 157 if (child.getXSLToken() == Constants.ELEMNAME_FALLBACK) 158 { 159 try 160 { 161 transformer.pushElemTemplateElement(child); 162 ((ElemFallback) child).executeFallback(transformer); 163 } 164 finally 165 { 166 transformer.popElemTemplateElement(); 167 } 168 } 169 } 170 171 } 172 173 /** 174 * Return true if this extension element has a <xsl:fallback> child element. 175 * 176 * @return true if this extension element has a <xsl:fallback> child element. 177 */ 178 private boolean hasFallbackChildren() 179 { 180 for (ElemTemplateElement child = m_firstChild; child != null; 181 child = child.m_nextSibling) 182 { 183 if (child.getXSLToken() == Constants.ELEMNAME_FALLBACK) 184 return true; 185 } 186 187 return false; 188 } 189 190 191 /** 192 * Execute an extension. 193 * 194 * @param transformer non-null reference to the the current transform-time state. 195 * 196 * @throws TransformerException 197 */ 198 public void execute(TransformerImpl transformer) 199 throws TransformerException 200 { 201 if (transformer.getStylesheet().isSecureProcessing()) 202 throw new TransformerException( 203 XSLMessages.createMessage( 204 XSLTErrorResources.ER_EXTENSION_ELEMENT_NOT_ALLOWED_IN_SECURE_PROCESSING, 205 new Object[] {getRawName()})); 206 207 if (transformer.getDebug()) 208 transformer.getTraceManager().fireTraceEvent(this); 209 try 210 { 211 transformer.getResultTreeHandler().flushPending(); 212 213 ExtensionsTable etable = transformer.getExtensionsTable(); 214 ExtensionHandler nsh = etable.get(m_extns); 215 216 if (null == nsh) 217 { 218 if (hasFallbackChildren()) 219 { 220 executeFallbacks(transformer); 221 } 222 else 223 { 224 TransformerException te = new TransformerException(XSLMessages.createMessage( 225 XSLTErrorResources.ER_CALL_TO_EXT_FAILED, new Object[]{getNodeName()})); 226 transformer.getErrorListener().fatalError(te); 227 } 228 229 return; 230 } 231 232 try 233 { 234 nsh.processElement(this.getLocalName(), this, transformer, 235 getStylesheet(), this); 236 } 237 catch (Exception e) 238 { 239 240 if (hasFallbackChildren()) 241 executeFallbacks(transformer); 242 else 243 { 244 if(e instanceof TransformerException) 245 { 246 TransformerException te = (TransformerException)e; 247 if(null == te.getLocator()) 248 te.setLocator(this); 249 250 transformer.getErrorListener().fatalError(te); 251 } 252 else if (e instanceof RuntimeException) 253 { 254 transformer.getErrorListener().fatalError(new TransformerException(e)); 255 } 256 else 257 { 258 transformer.getErrorListener().warning(new TransformerException(e)); 259 } 260 } 261 } 262 } 263 catch(TransformerException e) 264 { 265 transformer.getErrorListener().fatalError(e); 266 } 267 catch(SAXException se) { 268 throw new TransformerException(se); 269 } 270 if (transformer.getDebug()) 271 transformer.getTraceManager().fireTraceEndEvent(this); 272 } 273 274 /** 275 * Return the value of the attribute interpreted as an Attribute 276 * Value Template (in other words, you can use curly expressions 277 * such as href="http://{website}". 278 * 279 * @param rawName Raw name of the attribute to get 280 * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>. 281 * @param transformer non-null reference to the the current transform-time state. 282 * 283 * @return the value of the attribute 284 * 285 * @throws TransformerException 286 */ 287 public String getAttribute( 288 String rawName, org.w3c.dom.Node sourceNode, TransformerImpl transformer) 289 throws TransformerException 290 { 291 292 AVT avt = getLiteralResultAttribute(rawName); 293 294 if ((null != avt) && avt.getRawName().equals(rawName)) 295 { 296 XPathContext xctxt = transformer.getXPathContext(); 297 298 return avt.evaluate(xctxt, 299 xctxt.getDTMHandleFromNode(sourceNode), 300 this); 301 } 302 303 return null; 304 } 305 306 /** 307 * Accept a visitor and call the appropriate method 308 * for this class. 309 * 310 * @param visitor The visitor whose appropriate method will be called. 311 * @return true if the children of the object should be visited. 312 */ 313 protected boolean accept(XSLTVisitor visitor) 314 { 315 return visitor.visitExtensionElement(this); 316 } 317 318 319 }