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 }