Source code: org/apache/xalan/templates/ElemExtensionCall.java
1 /*
2 * Copyright 1999-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 /*
17 * $Id: ElemExtensionCall.java,v 1.38 2004/02/16 20:32:32 minchau Exp $
18 */
19 package org.apache.xalan.templates;
20
21 import javax.xml.transform.TransformerException;
22
23 import org.apache.xalan.extensions.ExtensionHandler;
24 import org.apache.xalan.extensions.ExtensionsTable;
25 import org.apache.xalan.res.XSLMessages;
26 import org.apache.xalan.res.XSLTErrorResources;
27 import org.apache.xalan.transformer.TransformerImpl;
28 import org.apache.xpath.XPathContext;
29 import org.xml.sax.SAXException;
30
31 /**
32 * Implement an extension element.
33 * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
34 * @xsl.usage advanced
35 */
36 public class ElemExtensionCall extends ElemLiteralResult
37 {
38
39 /** The Namespace URI for this extension call element.
40 * @serial */
41 String m_extns;
42
43 /** Language used by extension.
44 * @serial */
45 String m_lang;
46
47 /** URL pointing to extension.
48 * @serial */
49 String m_srcURL;
50
51 /** Source for script.
52 * @serial */
53 String m_scriptSrc;
54
55 /** Declaration for Extension element.
56 * @serial */
57 ElemExtensionDecl m_decl = null;
58
59 /**
60 * Get an int constant identifying the type of element.
61 * @see org.apache.xalan.templates.Constants
62 *
63 *@return The token ID for this element
64 */
65 public int getXSLToken()
66 {
67 return Constants.ELEMNAME_EXTENSIONCALL;
68 }
69
70 /**
71 * Return the node name.
72 *
73 * @return The element's name
74 */
75
76 // public String getNodeName()
77 // {
78 // TODO: Need prefix.
79 // return localPart;
80 // }
81
82 /**
83 * This function is called after everything else has been
84 * recomposed, and allows the template to set remaining
85 * values that may be based on some other property that
86 * depends on recomposition.
87 */
88 public void compose(StylesheetRoot sroot) throws TransformerException
89 {
90 super.compose(sroot);
91 m_extns = this.getNamespace();
92 m_decl = getElemExtensionDecl(sroot, m_extns);
93 // Register the extension namespace if the extension does not have
94 // an ElemExtensionDecl ("component").
95 if (m_decl == null)
96 sroot.getExtensionNamespacesManager().registerExtension(m_extns);
97 }
98
99 /**
100 * Return the ElemExtensionDecl for this extension element
101 *
102 *
103 * @param stylesheet Stylesheet root associated with this extension element
104 * @param namespace Namespace associated with this extension element
105 *
106 * @return the ElemExtensionDecl for this extension element.
107 */
108 private ElemExtensionDecl getElemExtensionDecl(StylesheetRoot stylesheet,
109 String namespace)
110 {
111
112 ElemExtensionDecl decl = null;
113 int n = stylesheet.getGlobalImportCount();
114
115 for (int i = 0; i < n; i++)
116 {
117 Stylesheet imported = stylesheet.getGlobalImport(i);
118
119 for (ElemTemplateElement child = imported.getFirstChildElem();
120 child != null; child = child.getNextSiblingElem())
121 {
122 if (Constants.ELEMNAME_EXTENSIONDECL == child.getXSLToken())
123 {
124 decl = (ElemExtensionDecl) child;
125
126 String prefix = decl.getPrefix();
127 String declNamespace = child.getNamespaceForPrefix(prefix);
128
129 if (namespace.equals(declNamespace))
130 {
131 return decl;
132 }
133 }
134 }
135 }
136
137 return null;
138 }
139
140 /**
141 * Execute the fallbacks when an extension is not available.
142 *
143 * @param transformer non-null reference to the the current transform-time state.
144 * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
145 * @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
146 *
147 * @throws TransformerException
148 */
149 private void executeFallbacks(
150 TransformerImpl transformer)
151 throws TransformerException
152 {
153 for (ElemTemplateElement child = m_firstChild; child != null;
154 child = child.m_nextSibling)
155 {
156 if (child.getXSLToken() == Constants.ELEMNAME_FALLBACK)
157 {
158 try
159 {
160 transformer.pushElemTemplateElement(child);
161 ((ElemFallback) child).executeFallback(transformer);
162 }
163 finally
164 {
165 transformer.popElemTemplateElement();
166 }
167 }
168 }
169
170 }
171
172 /**
173 * Return true if this extension element has a <xsl:fallback> child element.
174 *
175 * @return true if this extension element has a <xsl:fallback> child element.
176 */
177 private boolean hasFallbackChildren()
178 {
179 for (ElemTemplateElement child = m_firstChild; child != null;
180 child = child.m_nextSibling)
181 {
182 if (child.getXSLToken() == Constants.ELEMNAME_FALLBACK)
183 return true;
184 }
185
186 return false;
187 }
188
189
190 /**
191 * Execute an extension.
192 *
193 * @param transformer non-null reference to the the current transform-time state.
194 * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
195 * @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
196 *
197 * @throws TransformerException
198 */
199 public void execute(TransformerImpl transformer)
200 throws TransformerException
201 {
202
203 if (TransformerImpl.S_DEBUG)
204 transformer.getTraceManager().fireTraceEvent(this);
205 try
206 {
207 transformer.getResultTreeHandler().flushPending();
208
209 ExtensionsTable etable = transformer.getExtensionsTable();
210 ExtensionHandler nsh = etable.get(m_extns);
211
212 if (null == nsh)
213 {
214 if (hasFallbackChildren())
215 {
216 executeFallbacks(transformer);
217 }
218 else
219 {
220 TransformerException te = new TransformerException(XSLMessages.createMessage(
221 XSLTErrorResources.ER_CALL_TO_EXT_FAILED, new Object[]{getNodeName()}));
222 transformer.getErrorListener().fatalError(te);
223 }
224
225 return;
226 }
227
228 try
229 {
230 nsh.processElement(this.getLocalName(), this, transformer,
231 getStylesheet(), this);
232 }
233 catch (Exception e)
234 {
235
236 if (hasFallbackChildren())
237 executeFallbacks(transformer);
238 else
239 {
240 if(e instanceof TransformerException)
241 {
242 TransformerException te = (TransformerException)e;
243 if(null == te.getLocator())
244 te.setLocator(this);
245
246 transformer.getErrorListener().fatalError(te);
247 }
248 else if (e instanceof RuntimeException)
249 {
250 transformer.getErrorListener().fatalError(new TransformerException(e));
251 }
252 else
253 {
254 transformer.getErrorListener().warning(new TransformerException(e));
255 }
256 }
257 }
258 }
259 catch(TransformerException e)
260 {
261 transformer.getErrorListener().fatalError(e);
262 }
263 catch(SAXException se) {
264 throw new TransformerException(se);
265 }
266 if (TransformerImpl.S_DEBUG)
267 transformer.getTraceManager().fireTraceEndEvent(this);
268 }
269
270 /**
271 * Return the raw value of the attribute.
272 *
273 * @param rawName Raw name of the attribute to get
274 *
275 * @return the raw value of the attribute or null if not found
276 */
277 public String getAttribute(String rawName)
278 {
279
280 AVT avt = getLiteralResultAttribute(rawName);
281
282 if ((null != avt) && avt.getRawName().equals(rawName))
283 {
284 return avt.getSimpleString();
285 }
286
287 return null;
288 }
289
290 /**
291 * Return the value of the attribute interpreted as an Attribute
292 * Value Template (in other words, you can use curly expressions
293 * such as href="http://{website}".
294 *
295 * @param rawName Raw name of the attribute to get
296 * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
297 * @param transformer non-null reference to the the current transform-time state.
298 *
299 * @return the value of the attribute
300 *
301 * @throws TransformerException
302 */
303 public String getAttribute(
304 String rawName, org.w3c.dom.Node sourceNode, TransformerImpl transformer)
305 throws TransformerException
306 {
307
308 AVT avt = getLiteralResultAttribute(rawName);
309
310 if ((null != avt) && avt.getRawName().equals(rawName))
311 {
312 XPathContext xctxt = transformer.getXPathContext();
313
314 return avt.evaluate(xctxt,
315 xctxt.getDTMHandleFromNode(sourceNode),
316 this);
317 }
318
319 return null;
320 }
321
322 /**
323 * Accept a visitor and call the appropriate method
324 * for this class.
325 *
326 * @param visitor The visitor whose appropriate method will be called.
327 * @return true if the children of the object should be visited.
328 */
329 protected boolean accept(XSLTVisitor visitor)
330 {
331 return visitor.visitExtensionElement(this);
332 }
333
334
335 }