1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id: ElemExtensionCall.java 468643 2006-10-28 06:56:03Z minchau $ 20 */ 21 package org.apache.xalan.templates; 22 23 import javax.xml.transform.TransformerException; 24 25 import org.apache.xalan.extensions.ExtensionHandler; 26 import org.apache.xalan.extensions.ExtensionsTable; 27 import org.apache.xalan.res.XSLMessages; 28 import org.apache.xalan.res.XSLTErrorResources; 29 import org.apache.xalan.transformer.TransformerImpl; 30 import org.apache.xpath.XPathContext; 31 import org.xml.sax.SAXException; 32 33 /** 34 * Implement an extension element. 35 * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a> 36 * @xsl.usage advanced 37 */ 38 public class ElemExtensionCall extends ElemLiteralResult 39 { 40 static final long serialVersionUID = 3171339708500216920L; 41 42 /** The Namespace URI for this extension call element. 43 * @serial */ 44 String m_extns; 45 46 /** Language used by extension. 47 * @serial */ 48 String m_lang; 49 50 /** URL pointing to extension. 51 * @serial */ 52 String m_srcURL; 53 54 /** Source for script. 55 * @serial */ 56 String m_scriptSrc; 57 58 /** Declaration for Extension element. 59 * @serial */ 60 ElemExtensionDecl m_decl = null; 61 62 /** 63 * Get an int constant identifying the type of element. 64 * @see org.apache.xalan.templates.Constants 65 * 66 *@return The token ID for this element 67 */ 68 public int getXSLToken() 69 { 70 return Constants.ELEMNAME_EXTENSIONCALL; 71 } 72 73 /** 74 * Return the node name. 75 * 76 * @return The element's name 77 */ 78 79 // public String getNodeName() 80 // { 81 // TODO: Need prefix. 82 // return localPart; 83 // } 84 85 /** 86 * This function is called after everything else has been 87 * recomposed, and allows the template to set remaining 88 * values that may be based on some other property that 89 * depends on recomposition. 90 */ 91 public void compose(StylesheetRoot sroot) throws TransformerException 92 { 93 super.compose(sroot); 94 m_extns = this.getNamespace(); 95 m_decl = getElemExtensionDecl(sroot, m_extns); 96 // Register the extension namespace if the extension does not have 97 // an ElemExtensionDecl ("component"). 98 if (m_decl == null) 99 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 try 208 { 209 transformer.getResultTreeHandler().flushPending(); 210 211 ExtensionsTable etable = transformer.getExtensionsTable(); 212 ExtensionHandler nsh = etable.get(m_extns); 213 214 if (null == nsh) 215 { 216 if (hasFallbackChildren()) 217 { 218 executeFallbacks(transformer); 219 } 220 else 221 { 222 TransformerException te = new TransformerException(XSLMessages.createMessage( 223 XSLTErrorResources.ER_CALL_TO_EXT_FAILED, new Object[]{getNodeName()})); 224 transformer.getErrorListener().fatalError(te); 225 } 226 227 return; 228 } 229 230 try 231 { 232 nsh.processElement(this.getLocalName(), this, transformer, 233 getStylesheet(), this); 234 } 235 catch (Exception e) 236 { 237 238 if (hasFallbackChildren()) 239 executeFallbacks(transformer); 240 else 241 { 242 if(e instanceof TransformerException) 243 { 244 TransformerException te = (TransformerException)e; 245 if(null == te.getLocator()) 246 te.setLocator(this); 247 248 transformer.getErrorListener().fatalError(te); 249 } 250 else if (e instanceof RuntimeException) 251 { 252 transformer.getErrorListener().fatalError(new TransformerException(e)); 253 } 254 else 255 { 256 transformer.getErrorListener().warning(new TransformerException(e)); 257 } 258 } 259 } 260 } 261 catch(TransformerException e) 262 { 263 transformer.getErrorListener().fatalError(e); 264 } 265 catch(SAXException se) { 266 throw new TransformerException(se); 267 } 268 } 269 270 /** 271 * Return the value of the attribute interpreted as an Attribute 272 * Value Template (in other words, you can use curly expressions 273 * such as href="http://{website}". 274 * 275 * @param rawName Raw name of the attribute to get 276 * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>. 277 * @param transformer non-null reference to the the current transform-time state. 278 * 279 * @return the value of the attribute 280 * 281 * @throws TransformerException 282 */ 283 public String getAttribute( 284 String rawName, org.w3c.dom.Node sourceNode, TransformerImpl transformer) 285 throws TransformerException 286 { 287 288 AVT avt = getLiteralResultAttribute(rawName); 289 290 if ((null != avt) && avt.getRawName().equals(rawName)) 291 { 292 XPathContext xctxt = transformer.getXPathContext(); 293 294 return avt.evaluate(xctxt, 295 xctxt.getDTMHandleFromNode(sourceNode), 296 this); 297 } 298 299 return null; 300 } 301 302 /** 303 * Accept a visitor and call the appropriate method 304 * for this class. 305 * 306 * @param visitor The visitor whose appropriate method will be called. 307 * @return true if the children of the object should be visited. 308 */ 309 protected boolean accept(XSLTVisitor visitor) 310 { 311 return visitor.visitExtensionElement(this); 312 } 313 314 315 } 316