Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.jelly.parser.XMLParser |
68% |
92% |

1 |  |
     /*
2 |  |
      * Copyright 2002,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 |  |
     package org.apache.commons.jelly.parser;
17 |  |
18 |  |
     import java.io.File;
19 |  |
     import java.io.InputStream;
20 |  |
     import java.io.IOException;
21 |  |
     import java.io.Reader;
22 |  |
     import java.net.URL;
23 |  |
     import java.util.ArrayList;
24 |  |
     import java.util.EmptyStackException;
25 |  |
     import java.util.HashMap;
26 |  |
     import java.util.Iterator;
27 |  |
     import java.util.Map;
28 |  |
     import java.util.Properties;
29 |  |
30 |  |
     import javax.xml.parsers.SAXParser;
31 |  |
     import javax.xml.parsers.SAXParserFactory;
32 |  |
33 |  |
     import org.apache.commons.collections.ArrayStack;
34 |  |
35 |  |
     import org.apache.commons.jelly.JellyContext;
36 |  |
     import org.apache.commons.jelly.JellyException;
37 |  |
     import org.apache.commons.jelly.Script;
38 |  |
     import org.apache.commons.jelly.Tag;
39 |  |
     import org.apache.commons.jelly.TagLibrary;
40 |  |
     import org.apache.commons.jelly.impl.CompositeTextScriptBlock;
41 |  |
     import org.apache.commons.jelly.impl.ExpressionScript;
42 |  |
     import org.apache.commons.jelly.impl.StaticTag;
43 |  |
     import org.apache.commons.jelly.impl.ScriptBlock;
44 |  |
     import org.apache.commons.jelly.impl.StaticTagScript;
45 |  |
     import org.apache.commons.jelly.impl.TagFactory;
46 |  |
     import org.apache.commons.jelly.impl.TagScript;
47 |  |
     import org.apache.commons.jelly.impl.TextScript;
48 |  |
     import org.apache.commons.jelly.util.ClassLoaderUtils;
49 |  |
     import org.apache.commons.jelly.expression.CompositeExpression;
50 |  |
     import org.apache.commons.jelly.expression.ConstantExpression;
51 |  |
     import org.apache.commons.jelly.expression.Expression;
52 |  |
     import org.apache.commons.jelly.expression.ExpressionFactory;
53 |  |
     import org.apache.commons.jelly.expression.jexl.JexlExpressionFactory;
54 |  |
55 |  |
     import org.apache.commons.logging.Log;
56 |  |
     import org.apache.commons.logging.LogFactory;
57 |  |
58 |  |
     import org.xml.sax.Attributes;
59 |  |
     import org.xml.sax.ErrorHandler;
60 |  |
     import org.xml.sax.helpers.DefaultHandler;
61 |  |
     import org.xml.sax.InputSource;
62 |  |
     import org.xml.sax.Locator;
63 |  |
     import org.xml.sax.SAXException;
64 |  |
     import org.xml.sax.SAXParseException;
65 |  |
     import org.xml.sax.XMLReader;
66 |  |
     import org.xml.sax.helpers.AttributesImpl;
67 |  |
68 |  |
     /** <p><code>XMLParser</code> parses the XML Jelly format.
69 |  |
      * The SAXParser and XMLReader portions of this code come from Digester.</p>
70 |  |
      *
71 |  |
      * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
72 |  |
      * @version $Revision: 155420 $
73 |  |
      */
74 |  |
     public class XMLParser extends DefaultHandler {
75 |  |
76 |  |
         /**
77 |  |
          * Share the Jelly properties across parsers
78 |  |
          */
79 |  |
         private static Properties jellyProperties;
80 |  |
81 |  |
82 |  |
         /** JellyContext which is used to locate tag libraries*/
83 | 1027 |
         private JellyContext context = new JellyContext();
84 |  |
85 |  |
         /** the expression factory used to evaluate tag attributes */
86 |  |
         private ExpressionFactory expressionFactory;
87 |  |
88 |  |
         /** The current script block */
89 |  |
         private ScriptBlock script;
90 |  |
91 |  |
         /** The current, parent tagScript */
92 |  |
         private TagScript tagScript;
93 |  |
94 |  |
         /** The stack of body scripts. */
95 | 1027 |
         private ArrayStack scriptStack = new ArrayStack();
96 |  |
97 |  |
         /** The stack of tagScripts - use ArrayList as it allows null. */
98 | 1027 |
         private ArrayList tagScriptStack = new ArrayList();
99 |  |
100 |  |
         /** The current text buffer where non-custom tags get written */
101 |  |
         private StringBuffer textBuffer;
102 |  |
103 |  |
         /**
104 |  |
          * The class loader to use for instantiating application objects.
105 |  |
          * If not specified, the context class loader, or the class loader
106 |  |
          * used to load XMLParser itself, is used, based on the value of the
107 |  |
          * <code>useContextClassLoader</code> variable.
108 |  |
          */
109 | 1027 |
         protected ClassLoader classLoader = null;
110 |  |
111 |  |
         /**
112 |  |
          * Do we want to use the Context ClassLoader when loading classes
113 |  |
          * for instantiating new objects?  Default is <code>false</code>.
114 |  |
          */
115 | 1027 |
         protected boolean useContextClassLoader = false;
116 |  |
117 |  |
         /**
118 |  |
          * The application-supplied error handler that is notified when parsing
119 |  |
          * warnings, errors, or fatal errors occur.
120 |  |
          */
121 | 1027 |
         protected ErrorHandler errorHandler = null;
122 |  |
123 |  |
         /**
124 |  |
          * The SAXParserFactory that is created the first time we need it.
125 |  |
          */
126 | 273 |
         protected static SAXParserFactory factory = null;
127 |  |
128 |  |
         /**
129 |  |
          * The SAXParser we will use to parse the input stream.
130 |  |
          */
131 | 1027 |
         protected SAXParser parser = null;
132 |  |
133 |  |
         /**
134 |  |
          * The XMLReader used to parse digester rules.
135 |  |
          */
136 | 1027 |
         protected XMLReader reader = null;
137 |  |
138 |  |
         /**
139 |  |
          * The Locator associated with our parser.
140 |  |
          */
141 | 1027 |
         protected Locator locator = null;
142 |  |
143 |  |
         /**
144 |  |
          * Registered namespaces we are currently processing.  The key is the
145 |  |
          * namespace prefix that was declared in the document.  The value is an
146 |  |
          * ArrayStack of the namespace URIs this prefix has been mapped to --
147 |  |
          * the top Stack element is the most current one.  (This architecture
148 |  |
          * is required because documents can declare nested uses of the same
149 |  |
          * prefix for different Namespace URIs).
150 |  |
          */
151 | 1027 |
         protected Map namespaces = new HashMap();
152 |  |
153 |  |
         /** The Map of the namespace prefix -&gt; URIs defined for the current element */
154 |  |
         private Map elementNamespaces;
155 |  |
156 |  |
         /**
157 |  |
          * The name of the file being parsed that is passed to the TagScript objects
158 |  |
          * for error reporting
159 |  |
          */
160 |  |
         private String fileName;
161 |  |
162 |  |
         /**
163 |  |
          * Do we want to use a validating parser?
164 |  |
          */
165 | 1027 |
         protected boolean validating = false;
166 |  |
167 |  |
         /** Flag to indicate if this object has been configured */
168 |  |
         private boolean configured;
169 |  |
170 |  |
         /**
171 |  |
          * when not null, set the default namespace for
172 |  |
          * unprefixed elements via the DefaultNamespaceFilter
173 |  |
          * class
174 |  |
          */
175 | 1027 |
         private String defaultNamespaceURI = null;
176 |  |
177 |  |
         /**
178 |  |
          * The Log to which logging calls will be made.
179 |  |
          */
180 | 1300 |
         private Log log = LogFactory.getLog(XMLParser.class);
181 |  |
182 |  |
         /**
183 |  |
          * Construct a new XMLParser with default properties.
184 |  |
          */
185 | 1027 |
         public XMLParser() {
186 | 1027 |
         }
187 |  |
188 |  |
         /**
189 |  |
          * Construct a new XMLParser, allowing a SAXParser to be passed in.  This
190 |  |
          * allows XMLParser to be used in environments which are unfriendly to
191 |  |
          * JAXP1.1 (such as WebLogic 6.0).  Thanks for the request to change go to
192 |  |
          * James House (james@interobjective.com).  This may help in places where
193 |  |
          * you are able to load JAXP 1.1 classes yourself.
194 |  |
          */
195 | 0 |
         public XMLParser(SAXParser parser) {
196 | 0 |
             this.parser = parser;
197 | 0 |
         }
198 |  |
199 |  |
         /**
200 |  |
          * Construct a new XMLParser, allowing an XMLReader to be passed in.  This
201 |  |
          * allows XMLParser to be used in environments which are unfriendly to
202 |  |
          * JAXP1.1 (such as WebLogic 6.0).  Note that if you use this option you
203 |  |
          * have to configure namespace and validation support yourself, as these
204 |  |
          * properties only affect the SAXParser and emtpy constructor.
205 |  |
          */
206 | 0 |
         public XMLParser(XMLReader reader) {
207 | 0 |
             this.reader = reader;
208 | 0 |
         }
209 |  |
210 |  |
         /**
211 |  |
          * Parse the content of the specified file using this XMLParser.  Returns
212 |  |
          * the root element from the object stack (if any).
213 |  |
          *
214 |  |
          * @param file File containing the XML data to be parsed
215 |  |
          *
216 |  |
          * @exception IOException if an input/output error occurs
217 |  |
          * @exception SAXException if a parsing exception occurs
218 |  |
          */
219 |  |
         public Script parse(File file) throws IOException, SAXException {
220 | 0 |
             return parse(file.toURL());
221 |  |
         }
222 |  |
223 |  |
         /**
224 |  |
          * Parse the content of the specified file using this XMLParser.  Returns
225 |  |
          * the root element from the object stack (if any).
226 |  |
          *
227 |  |
          * @param url URL containing the XML data to be parsed
228 |  |
          *
229 |  |
          * @exception IOException if an input/output error occurs
230 |  |
          * @exception SAXException if a parsing exception occurs
231 |  |
          */
232 |  |
         public Script parse(URL url) throws IOException, SAXException {
233 | 845 |
             ensureConfigured();
234 | 845 |
             this.fileName = url.toString();
235 |  |
236 | 845 |
             InputSource source = new InputSource(url.toString());
237 |  |
238 | 845 |
             getXMLReader().parse(source);
239 | 806 |
             return script;
240 |  |
         }
241 |  |
242 |  |
         /**
243 |  |
          * Parse the content of the specified input source using this XMLParser.
244 |  |
          * Returns the root element from the object stack (if any).
245 |  |
          *
246 |  |
          * @param input Input source containing the XML data to be parsed
247 |  |
          *
248 |  |
          * @exception IOException if an input/output error occurs
249 |  |
          * @exception SAXException if a parsing exception occurs
250 |  |
          */
251 |  |
         public Script parse(InputSource input) throws IOException, SAXException {
252 | 130 |
             ensureConfigured();
253 | 130 |
             this.fileName = input.getSystemId();
254 | 130 |
             getXMLReader().parse(input);
255 | 130 |
             return script;
256 |  |
         }
257 |  |
258 |  |
         /**
259 |  |
          * Parse the content of the specified input stream using this XMLParser.
260 |  |
          * Returns the root element from the object stack (if any).
261 |  |
          * (Note: if reading a File or URL, use one of the URL-based
262 |  |
          * parse methods instead.  This method will not be able
263 |  |
          * to resolve any relative paths inside a DTD.)
264 |  |
          *
265 |  |
          * @param input  Input stream containing the XML data to be parsed
266 |  |
          * @return
267 |  |
          * @exception IOException
268 |  |
          *                   if an input/output error occurs
269 |  |
          * @exception SAXException
270 |  |
          *                   if a parsing exception occurs
271 |  |
          */
272 |  |
         public Script parse(InputStream input) throws IOException, SAXException {
273 | 52 |
             ensureConfigured();
274 | 52 |
             this.fileName = getCurrentURI();
275 | 52 |
             getXMLReader().parse(new InputSource(input));
276 | 39 |
             return script;
277 |  |
         }
278 |  |
279 |  |
         /**
280 |  |
          * Parse the content of the specified reader using this XMLParser.
281 |  |
          * Returns the root element from the object stack (if any).
282 |  |
          * (Note: if reading a File or URL, use one of the URL-based
283 |  |
          * parse methods instead.  This method will not be able
284 |  |
          * to resolve any relative paths inside a DTD.)
285 |  |
          *
286 |  |
          * @param reader Reader containing the XML data to be parsed
287 |  |
          * @return
288 |  |
          * @exception IOException
289 |  |
          *                   if an input/output error occurs
290 |  |
          * @exception SAXException
291 |  |
          *                   if a parsing exception occurs
292 |  |
          */
293 |  |
         public Script parse(Reader reader) throws IOException, SAXException {
294 | 0 |
             ensureConfigured();
295 | 0 |
             this.fileName = getCurrentURI();
296 | 0 |
             getXMLReader().parse(new InputSource(reader));
297 | 0 |
             return script;
298 |  |
         }
299 |  |
300 |  |
         /**
301 |  |
          * Parse the content of the specified URI using this XMLParser.
302 |  |
          * Returns the root element from the object stack (if any).
303 |  |
          *
304 |  |
          * @param uri URI containing the XML data to be parsed
305 |  |
          *
306 |  |
          * @exception IOException if an input/output error occurs
307 |  |
          * @exception SAXException if a parsing exception occurs
308 |  |
          */
309 |  |
         public Script parse(String uri) throws IOException, SAXException {
310 | 0 |
             ensureConfigured();
311 | 0 |
             this.fileName = uri;
312 | 0 |
             getXMLReader().parse(uri);
313 | 0 |
             return script;
314 |  |
         }
315 |  |
316 |  |
         /**
317 |  |
          * Return the currently mapped namespace URI for the specified prefix,
318 |  |
          * if any; otherwise return <code>null</code>.  These mappings come and
319 |  |
          * go dynamically as the document is parsed.
320 |  |
          *
321 |  |
          * @param prefix Prefix to look up
322 |  |
          */
323 |  |
         public String findNamespaceURI(String prefix) {
324 | 0 |
             ArrayStack stack = (ArrayStack) namespaces.get(prefix);
325 | 0 |
             if (stack == null) {
326 | 0 |
                 return (null);
327 |  |
             }
328 |  |
             try {
329 | 0 |
                 return ((String) stack.peek());
330 |  |
             }
331 | 0 |
             catch (EmptyStackException e) {
332 | 0 |
                 return (null);
333 |  |
             }
334 |  |
         }
335 |  |
336 |  |
         // Properties
337 |  |
         //-------------------------------------------------------------------------
338 |  |
         public JellyContext getContext() {
339 | 52 |
             return context;
340 |  |
         }
341 |  |
342 |  |
         public void setContext(JellyContext context) {
343 | 1014 |
             this.context = context;
344 | 1014 |
         }
345 |  |
346 |  |
         /**
347 |  |
          * Set the jelly namespace to use for unprefixed elements.
348 |  |
          * Will be overridden by an explicit namespace in the
349 |  |
          * XML document.
350 |  |
          *
351 |  |
          * @param namespace jelly namespace to use (e.g. 'jelly:core')
352 |  |
          */
353 |  |
         public void setDefaultNamespaceURI(String namespace) {
354 | 845 |
             this.defaultNamespaceURI = namespace;
355 | 845 |
         }
356 |  |
357 |  |
         /**
358 |  |
          * Return the class loader to be used for instantiating application objects
359 |  |
          * when required.  This is determined based upon the following rules:
360 |  |
          * <ul>
361 |  |
          * <li>The class loader set by <code>setClassLoader()</code>, if any</li>
362 |  |
          * <li>The thread context class loader, if it exists and the
363 |  |
          *     <code>useContextClassLoader</code> property is set to true</li>
364 |  |
          * <li>The class loader used to load the XMLParser class itself.
365 |  |
          * </ul>
366 |  |
          */
367 |  |
         public ClassLoader getClassLoader() {
368 | 338 |
             return ClassLoaderUtils.getClassLoader(classLoader, useContextClassLoader, getClass());
369 |  |
         }
370 |  |
371 |  |
         /**
372 |  |
          * Set the class loader to be used for instantiating application objects
373 |  |
          * when required.
374 |  |
          *
375 |  |
          * @param classLoader The new class loader to use, or <code>null</code>
376 |  |
          *  to revert to the standard rules
377 |  |
          */
378 |  |
         public void setClassLoader(ClassLoader classLoader) {
379 | 0 |
             this.classLoader = classLoader;
380 | 0 |
         }
381 |  |
382 |  |
         /**
383 |  |
          * Return the boolean as to whether the context classloader should be used.
384 |  |
          */
385 |  |
         public boolean getUseContextClassLoader() {
386 | 0 |
             return useContextClassLoader;
387 |  |
         }
388 |  |
389 |  |
         /**
390 |  |
          * Determine whether to use the Context ClassLoader (the one found by
391 |  |
          * calling <code>Thread.currentThread().getContextClassLoader()</code>)
392 |  |
          * to resolve/load classes.  If not
393 |  |
          * using Context ClassLoader, then the class-loading defaults to
394 |  |
          * using the calling-class' ClassLoader.
395 |  |
          *
396 |  |
          * @param use determines whether to use JellyContext ClassLoader.
397 |  |
          */
398 |  |
         public void setUseContextClassLoader(boolean use) {
399 | 0 |
             useContextClassLoader = use;
400 | 0 |
         }
401 |  |
402 |  |
         /**
403 |  |
          * Return the error handler for this XMLParser.
404 |  |
          */
405 |  |
         public ErrorHandler getErrorHandler() {
406 | 0 |
             return (this.errorHandler);
407 |  |
         }
408 |  |
409 |  |
         /**
410 |  |
          * Set the error handler for this XMLParser.
411 |  |
          *
412 |  |
          * @param errorHandler The new error handler
413 |  |
          */
414 |  |
         public void setErrorHandler(ErrorHandler errorHandler) {
415 | 0 |
             this.errorHandler = errorHandler;
416 | 0 |
         }
417 |  |
418 |  |
         /**
419 |  |
          * Return the current Logger associated with this instance of the XMLParser
420 |  |
          */
421 |  |
         public Log getLogger() {
422 | 0 |
             return log;
423 |  |
         }
424 |  |
425 |  |
         /**
426 |  |
          * Set the current logger for this XMLParser.
427 |  |
          */
428 |  |
         public void setLogger(Log log) {
429 | 0 |
             this.log = log;
430 | 0 |
         }
431 |  |
432 |  |
         /** @return the expression factory used to evaluate tag attributes */
433 |  |
         public ExpressionFactory getExpressionFactory() {
434 | 53495 |
             if (expressionFactory == null) {
435 | 1001 |
                 expressionFactory = createExpressionFactory();
436 |  |
             }
437 | 53495 |
             return expressionFactory;
438 |  |
         }
439 |  |
440 |  |
         /** Sets the expression factory used to evaluate tag attributes */
441 |  |
         public void setExpressionFactory(ExpressionFactory expressionFactory) {
442 | 0 |
             this.expressionFactory = expressionFactory;
443 | 0 |
         }
444 |  |
445 |  |
         /**
446 |  |
          * Return the SAXParser we will use to parse the input stream.  If there
447 |  |
          * is a problem creating the parser, return <code>null</code>.
448 |  |
          */
449 |  |
         public SAXParser getParser() {
450 |  |
             // Return the parser we already created (if any)
451 | 1027 |
             if (parser != null) {
452 | 0 |
                 return (parser);
453 |  |
             }
454 |  |
             // Create and return a new parser
455 | 1027 |
             synchronized (this) {
456 |  |
                 try {
457 | 1027 |
                     if (factory == null) {
458 | 273 |
                         factory = SAXParserFactory.newInstance();
459 |  |
                     }
460 | 1027 |
                     factory.setNamespaceAware(true);
461 | 1027 |
                     factory.setValidating(validating);
462 | 1027 |
                     parser = factory.newSAXParser();
463 | 1027 |
                     return (parser);
464 |  |
                 }
465 | 0 |
                 catch (Exception e) {
466 | 0 |
                     log.error("XMLParser.getParser: ", e);
467 | 0 |
                     return (null);
468 |  |
                 }
469 | 0 |
             }
470 |  |
         }
471 |  |
472 |  |
         /**
473 |  |
          * By setting the reader in the constructor, you can bypass JAXP and
474 |  |
          * be able to use digester in Weblogic 6.0.
475 |  |
          *
476 |  |
          * @deprecated Use getXMLReader() instead, which can throw a
477 |  |
          *  SAXException if the reader cannot be instantiated
478 |  |
          */
479 |  |
         public XMLReader getReader() {
480 |  |
             try {
481 | 0 |
                 return (getXMLReader());
482 |  |
             }
483 | 0 |
             catch (SAXException e) {
484 | 0 |
                 log.error("Cannot get XMLReader", e);
485 | 0 |
                 return (null);
486 |  |
             }
487 |  |
         }
488 |  |
489 |  |
         /**
490 |  |
          * Return the XMLReader to be used for parsing the input document.
491 |  |
          *
492 |  |
          * @exception SAXException if no XMLReader can be instantiated
493 |  |
          */
494 |  |
         public synchronized XMLReader getXMLReader() throws SAXException {
495 | 1027 |
             if (reader == null) {
496 | 1027 |
                 reader = getParser().getXMLReader();
497 | 1027 |
                 if (this.defaultNamespaceURI != null) {
498 | 26 |
                     reader = new DefaultNamespaceFilter(this.defaultNamespaceURI,reader);
499 |  |
                 }
500 |  |
             }
501 |  |
             //set up the parse
502 | 1027 |
             reader.setContentHandler(this);
503 | 1027 |
             reader.setDTDHandler(this);
504 |  |
             //reader.setEntityResolver(this);
505 | 1027 |
             reader.setErrorHandler(this);
506 |  |
507 | 1027 |
             return reader;
508 |  |
         }
509 |  |
510 |  |
         /**
511 |  |
          * Return the validating parser flag.
512 |  |
          */
513 |  |
         public boolean getValidating() {
514 | 0 |
             return (this.validating);
515 |  |
         }
516 |  |
517 |  |
         /**
518 |  |
          * Set the validating parser flag.  This must be called before
519 |  |
          * <code>parse()</code> is called the first time.
520 |  |
          *
521 |  |
          * @param validating The new validating parser flag.
522 |  |
          */
523 |  |
         public void setValidating(boolean validating) {
524 | 845 |
             this.validating = validating;
525 | 845 |
         }
526 |  |
527 |  |
528 |  |
         /**
529 |  |
          * Returns the script that has just been created if this class is used
530 |  |
          * as a SAX ContentHandler and passed into some XML processor or parser.
531 |  |
          *
532 |  |
          * @return the ScriptBlock created if SAX events are piped into this class,
533 |  |
          * which must include a startDocument() and endDocument()
534 |  |
          */
535 |  |
         public ScriptBlock getScript() {
536 | 0 |
             return script;
537 |  |
         }
538 |  |
539 |  |
540 |  |
         // ContentHandler interface
541 |  |
         //-------------------------------------------------------------------------
542 |  |
         /**
543 |  |
          * Process notification of the beginning of the document being reached.
544 |  |
          *
545 |  |
          * @exception SAXException if a parsing error is to be reported
546 |  |
          */
547 |  |
         public void startDocument() throws SAXException {
548 | 1027 |
             script = new ScriptBlock();
549 | 1027 |
             textBuffer = new StringBuffer();
550 | 1027 |
             tagScript = null;
551 | 1027 |
             scriptStack.clear();
552 | 1027 |
             tagScriptStack.clear();
553 | 1027 |
         }
554 |  |
555 |  |
         /**
556 |  |
          * Process notification of the end of the document being reached.
557 |  |
          *
558 |  |
          * @exception SAXException if a parsing error is to be reported
559 |  |
          */
560 |  |
         public void endDocument() throws SAXException {
561 | 975 |
             textBuffer = null;
562 | 975 |
         }
563 |  |
564 |  |
         /**
565 |  |
          * Process notification of the start of an XML element being reached.
566 |  |
          *
567 |  |
          * @param namespaceURI The Namespace URI, or the empty string if the
568 |  |
          *   element has no Namespace URI or if Namespace processing is not
569 |  |
          *   being performed.
570 |  |
          * @param localName The local name (without prefix), or the empty
571 |  |
          *   string if Namespace processing is not being performed.
572 |  |
          * @param qName The qualified name (with prefix), or the empty
573 |  |
          *   string if qualified names are not available.\
574 |  |
          * @param list The attributes attached to the element. If there are
575 |  |
          *   no attributes, it shall be an empty Attributes object.
576 |  |
          * @exception SAXException if a parsing error is to be reported
577 |  |
          */
578 |  |
         public void startElement(
579 |  |
             String namespaceURI,
580 |  |
             String localName,
581 |  |
             String qName,
582 |  |
             Attributes list)
583 |  |
             throws SAXException {
584 |  |
585 |  |
             try {
586 |  |
                 // add check to ensure namespace URI is "" for no namespace
587 | 19981 |
                 if ( namespaceURI == null ) {
588 | 0 |
                     namespaceURI = "";
589 |  |
                 }
590 |  |
591 |  |
                 // if this is a tag then create a script to run it
592 |  |
                 // otherwise pass the text to the current body
593 | 19981 |
                 TagScript newTagScript = createTag(namespaceURI, localName, list);
594 | 19968 |
                 if (newTagScript == null) {
595 | 247 |
                     newTagScript = createStaticTag(namespaceURI, localName, qName, list);
596 |  |
                 }
597 | 19968 |
                 tagScript = newTagScript;
598 | 19968 |
                 tagScriptStack.add(tagScript);
599 | 19968 |
                 if (tagScript != null) {
600 |  |
                     // set the line number details
601 | 19968 |
                     if ( locator != null ) {
602 | 19968 |
                         tagScript.setLocator(locator);
603 |  |
                     }
604 |  |
                     // sets the file name element names
605 | 19968 |
                     tagScript.setFileName(fileName);
606 | 19968 |
                     tagScript.setElementName(qName);
607 | 19968 |
                     tagScript.setLocalName(localName);
608 |  |
609 | 19968 |
                     if (textBuffer.length() > 0) {
610 | 17355 |
                         addTextScript(textBuffer.toString());
611 | 17355 |
                         textBuffer.setLength(0);
612 |  |
                     }
613 | 19968 |
                     script.addScript(tagScript);
614 |  |
                     // start a new body
615 | 19968 |
                     scriptStack.push(script);
616 | 19968 |
                     script = new ScriptBlock();
617 | 19968 |
                     tagScript.setTagBody(script);
618 | 19968 |
                 }
619 |  |
                 else {
620 |  |
                     // XXXX: might wanna handle empty elements later...
621 | 0 |
                     textBuffer.append("<");
622 | 0 |
                     textBuffer.append(qName);
623 | 0 |
                     int size = list.getLength();
624 | 0 |
                     for (int i = 0; i < size; i++) {
625 | 0 |
                         textBuffer.append(" ");
626 | 0 |
                         textBuffer.append(list.getQName(i));
627 | 0 |
                         textBuffer.append("=");
628 | 0 |
                         textBuffer.append("\"");
629 | 0 |
                         textBuffer.append(list.getValue(i));
630 | 0 |
                         textBuffer.append("\"");
631 |  |
                     }
632 | 0 |
                     textBuffer.append(">");
633 |  |
                 }
634 |  |
             }
635 | 13 |
             catch (SAXException e) {
636 | 13 |
                 throw e;
637 |  |
             }
638 | 0 |
             catch (Exception e) {
639 | 0 |
                 log.error( "Caught exception: " + e, e );
640 | 0 |
                 throw new SAXException( "Runtime Exception: " + e, e );
641 | 19968 |
             }
642 | 19968 |
         }
643 |  |
644 |  |
         /**
645 |  |
          * Process notification of character data received from the body of
646 |  |
          * an XML element.
647 |  |
          *
648 |  |
          * @param buffer The characters from the XML document
649 |  |
          * @param start Starting offset into the buffer
650 |  |
          * @param length Number of characters from the buffer
651 |  |
          *
652 |  |
          * @exception SAXException if a parsing error is to be reported
653 |  |
          */
654 |  |
         public void characters(char buffer[], int start, class="keyword">int length)
655 |  |
             throws SAXException {
656 | 31954 |
             textBuffer.append(buffer, start, length);
657 | 31954 |
         }
658 |  |
659 |  |
         /**
660 |  |
          * Process notification of the end of an XML element being reached.
661 |  |
          *
662 |  |
          * @param namespaceURI The Namespace URI, or the empty string if the
663 |  |
          *   element has no Namespace URI or if Namespace processing is not
664 |  |
          *   being performed.
665 |  |
          * @param localName The local name (without prefix), or the empty
666 |  |
          *   string if Namespace processing is not being performed.
667 |  |
          * @param qName The qualified XML 1.0 name (with prefix), or the
668 |  |
          *   empty string if qualified names are not available.
669 |  |
          * @exception SAXException if a parsing error is to be reported
670 |  |
          */
671 |  |
         public void endElement(String namespaceURI, String localName, String qName)
672 |  |
             throws SAXException {
673 |  |
             try {
674 | 19929 |
                 tagScript = (TagScript) tagScriptStack.remove(tagScriptStack.size() - 1);
675 | 19929 |
                 if (tagScript != null) {
676 | 19929 |
                     if (textBuffer.length() > 0) {
677 | 10010 |
                         addTextScript(textBuffer.toString());
678 | 10010 |
                         textBuffer.setLength(0);
679 |  |
                     }
680 | 19929 |
                     script = (ScriptBlock) scriptStack.pop();
681 | 19929 |
                 }
682 |  |
                 else {
683 | 0 |
                     textBuffer.append("</");
684 | 0 |
                     textBuffer.append(qName);
685 | 0 |
                     textBuffer.append(">");
686 |  |
                 }
687 |  |
688 |  |
                 // now lets set the parent tag variable
689 | 19929 |
                 if ( tagScriptStack.isEmpty() ) {
690 | 988 |
                     tagScript = null;
691 | 988 |
                 }
692 |  |
                 else {
693 | 18941 |
                     tagScript = (TagScript) tagScriptStack.get(tagScriptStack.size() - 1);
694 |  |
                 }
695 | 0 |
             } catch (Exception e) {
696 | 0 |
                 log.error( "Caught exception: " + e, e );
697 | 0 |
                 throw new SAXException( "Runtime Exception: " + e, e );
698 | 19929 |
             }
699 | 19929 |
         }
700 |  |
701 |  |
         /**
702 |  |
          * Process notification that a namespace prefix is coming in to scope.
703 |  |
          *
704 |  |
          * @param prefix Prefix that is being declared
705 |  |
          * @param namespaceURI Corresponding namespace URI being mapped to
706 |  |
          *
707 |  |
          * @exception SAXException if a parsing error is to be reported
708 |  |
          */
709 |  |
         public void startPrefixMapping(String prefix, String namespaceURI)
710 |  |
             throws SAXException {
711 |  |
             // Register this prefix mapping
712 | 1118 |
             ArrayStack stack = (ArrayStack) namespaces.get(prefix);
713 | 1118 |
             if (stack == null) {
714 | 1118 |
                 stack = new ArrayStack();
715 | 1118 |
                 namespaces.put(prefix, stack);
716 |  |
             }
717 | 1118 |
             stack.push(namespaceURI);
718 |  |
719 | 1118 |
             if ( elementNamespaces == null ) {
720 | 1040 |
                 elementNamespaces = new HashMap();
721 |  |
             }
722 | 1118 |
             elementNamespaces.put(prefix, namespaceURI);
723 | 1118 |
         }
724 |  |
725 |  |
         /**
726 |  |
          * Process notification that a namespace prefix is going out of scope.
727 |  |
          *
728 |  |
          * @param prefix Prefix that is going out of scope
729 |  |
          *
730 |  |
          * @exception SAXException if a parsing error is to be reported
731 |  |
          */
732 |  |
         public void endPrefixMapping(String prefix) throws SAXException {
733 |  |
             // Deregister this prefix mapping
734 | 1066 |
             ArrayStack stack = (ArrayStack) namespaces.get(prefix);
735 | 1066 |
             if (stack == null) {
736 | 0 |
                 return;
737 |  |
             }
738 |  |
             try {
739 | 1066 |
                 stack.pop();
740 | 1066 |
                 if (stack.empty()) {
741 | 1066 |
                     namespaces.remove(prefix);
742 |  |
                 }
743 |  |
             }
744 | 0 |
             catch (EmptyStackException e) {
745 | 0 |
                 throw createSAXException("endPrefixMapping popped too many times");
746 | 1066 |
             }
747 | 1066 |
         }
748 |  |
749 |  |
         /**
750 |  |
          * Process notification of ignorable whitespace received from the body of
751 |  |
          * an XML element.
752 |  |
          *
753 |  |
          * @param buffer The characters from the XML document
754 |  |
          * @param start Starting offset into the buffer
755 |  |
          * @param len Number of characters from the buffer
756 |  |
          *
757 |  |
          * @exception SAXException if a parsing error is to be reported
758 |  |
          */
759 |  |
         public void ignorableWhitespace(char buffer[], int start, class="keyword">int len)
760 |  |
             throws SAXException {
761 |  |
             ; // No processing required
762 | 338 |
         }
763 |  |
764 |  |
         /**
765 |  |
          * Process notification of a processing instruction that was encountered.
766 |  |
          *
767 |  |
          * @param target The processing instruction target
768 |  |
          * @param data The processing instruction data (if any)
769 |  |
          *
770 |  |
          * @exception SAXException if a parsing error is to be reported
771 |  |
          */
772 |  |
         public void processingInstruction(String target, String data)
773 |  |
             throws SAXException {
774 |  |
             ; // No processing is required
775 | 0 |
         }
776 |  |
777 |  |
         /**
778 |  |
          * Set the document locator associated with our parser.
779 |  |
          *
780 |  |
          * @param locator The new locator
781 |  |
          */
782 |  |
         public void setDocumentLocator(Locator locator) {
783 | 1027 |
             this.locator = locator;
784 | 1027 |
         }
785 |  |
786 |  |
         /**
787 |  |
          * Process notification of a skipped entity.
788 |  |
          *
789 |  |
          * @param name Name of the skipped entity
790 |  |
          *
791 |  |
          * @exception SAXException if a parsing error is to be reported
792 |  |
          */
793 |  |
         public void skippedEntity(String name) throws SAXException {
794 |  |
             ; // No processing required
795 | 0 |
         }
796 |  |
797 |  |
798 |  |
         // DTDHandler interface
799 |  |
         //-------------------------------------------------------------------------
800 |  |
801 |  |
         /**
802 |  |
          * Receive notification of a notation declaration event.
803 |  |
          *
804 |  |
          * @param name The notation name
805 |  |
          * @param publicId The public identifier (if any)
806 |  |
          * @param systemId The system identifier (if any)
807 |  |
          */
808 |  |
         public void notationDecl(String name, String class="keyword">publicId, String systemId) {
809 | 0 |
         }
810 |  |
811 |  |
         /**
812 |  |
          * Receive notification of an unparsed entity declaration event.
813 |  |
          *
814 |  |
          * @param name The unparsed entity name
815 |  |
          * @param publicId The public identifier (if any)
816 |  |
          * @param systemId The system identifier (if any)
817 |  |
          * @param notation The name of the associated notation
818 |  |
          */
819 |  |
         public void unparsedEntityDecl(
820 |  |
             String name,
821 |  |
             String publicId,
822 |  |
             String systemId,
823 |  |
             String notation) {
824 | 0 |
         }
825 |  |
826 |  |
827 |  |
         // ErrorHandler interface
828 |  |
         //-------------------------------------------------------------------------
829 |  |
830 |  |
         /**
831 |  |
          * Forward notification of a parsing error to the application supplied
832 |  |
          * error handler, if any, otherwise throw a SAXException with the error.
833 |  |
          *
834 |  |
          * @param exception The error information
835 |  |
          *
836 |  |
          * @exception SAXException if a parsing exception occurs
837 |  |
          */
838 |  |
         public void error(SAXParseException exception) throws SAXException {
839 | 26 |
             log.error(
840 |  |
                 "Parse Error at line "
841 |  |
                     + exception.getLineNumber()
842 |  |
                     + " column "
843 |  |
                     + exception.getColumnNumber()
844 |  |
                     + ": "
845 |  |
                     + exception.getMessage(),
846 |  |
                 exception);
847 | 26 |
             if (errorHandler != null) {
848 | 0 |
                 errorHandler.error(exception);
849 | 0 |
             } else {
850 | 26 |
                 throw exception;
851 |  |
             }
852 | 0 |
         }
853 |  |
854 |  |
         /**
855 |  |
          * Forward notification of a fatal parsing error to the application
856 |  |
          * supplied error handler, if any, otherwise throw a SAXException with the error.
857 |  |
          *
858 |  |
          * @param exception The fatal error information
859 |  |
          *
860 |  |
          * @exception SAXException if a parsing exception occurs
861 |  |
          */
862 |  |
         public void fatalError(SAXParseException exception) throws SAXException {
863 | 13 |
             log.error(
864 |  |
                 "Parse Fatal Error at line "
865 |  |
                     + exception.getLineNumber()
866 |  |
                     + " column "
867 |  |
                     + exception.getColumnNumber()
868 |  |
                     + ": "
869 |  |
                     + exception.getMessage(),
870 |  |
                 exception);
871 | 13 |
             if (errorHandler != null) {
872 | 0 |
                 errorHandler.fatalError(exception);
873 | 0 |
             } else {
874 | 13 |
                 throw exception;
875 |  |
             }
876 | 0 |
         }
877 |  |
878 |  |
         /**
879 |  |
          * Forward notification of a parse warning to the application supplied
880 |  |
          * error handler (if any).  Unlike XMLParser.error(SAXParseException) and
881 |  |
          * XMLParser.fatalError(SAXParseException), this implementation will
882 |  |
          * NOT throw a SAXException by default if no error handler is supplied.
883 |  |
          *
884 |  |
          * @param exception The warning information
885 |  |
          *
886 |  |
          * @exception SAXException if a parsing exception occurs
887 |  |
          */
888 |  |
         public void warning(SAXParseException exception) throws SAXException {
889 | 0 |
             log.error(
890 |  |
                 "Parse Warning at line "
891 |  |
                     + exception.getLineNumber()
892 |  |
                     + " column "
893 |  |
                     + exception.getColumnNumber()
894 |  |
                     + ": "
895 |  |
                     + exception.getMessage(),
896 |  |
                 exception);
897 | 0 |
             if (errorHandler != null) {
898 | 0 |
                 errorHandler.warning(exception);
899 |  |
             }
900 | 0 |
         }
901 |  |
902 |  |
         // Implementation methods
903 |  |
         //-------------------------------------------------------------------------
904 |  |
         /**
905 |  |
          * If this object has not been configured then register the default
906 |  |
          * namespaces
907 |  |
          */
908 |  |
         private void ensureConfigured() {
909 | 1027 |
             if (!configured) {
910 | 1027 |
                 configure();
911 | 1027 |
                 configured = true;
912 |  |
             }
913 | 1027 |
         }
914 |  |
915 |  |
         /**
916 |  |
          * This method is called only once before parsing occurs
917 |  |
          * which allows tag libraries to be registered and so forth
918 |  |
          */
919 |  |
         protected void configure() {
920 |  |
             // load the properties file of libraries available
921 | 1027 |
             Properties properties = getJellyProperties();
922 | 1027 |
             for (Iterator iter = properties.entrySet().iterator(); iter.hasNext();) {
923 | 39026 |
                 Map.Entry entry = (Map.Entry) iter.next();
924 | 39026 |
                 String uri = (String) entry.getKey();
925 | 39026 |
                 String className = (String) entry.getValue();
926 | 39026 |
                 String libraryURI = "jelly:" + uri;
927 |  |
928 |  |
                 // don't overload any Mock Tags already
929 | 39026 |
                 if ( ! context.isTagLibraryRegistered(libraryURI) ) {
930 | 35074 |
                     context.registerTagLibrary(libraryURI, className);
931 |  |
                 }
932 | 39026 |
             }
933 | 1027 |
         }
934 |  |
935 |  |
936 |  |
         /**
937 |  |
          * A helper method which loads the static Jelly properties once on startup
938 |  |
          */
939 |  |
         protected synchronized Properties getJellyProperties() {
940 | 1027 |
             if (jellyProperties == null) {
941 | 273 |
                 jellyProperties = new Properties();
942 |  |
943 | 273 |
                 InputStream in = null;
944 | 273 |
                 URL url =
945 |  |
                     getClassLoader().getResource("org/apache/commons/jelly/jelly.properties");
946 | 273 |
                 if (url != null) {
947 | 273 |
                     log.debug("Loading Jelly default tag libraries from: " + url);
948 |  |
                     try {
949 | 273 |
                         in = url.openStream();
950 | 273 |
                         jellyProperties .load(in);
951 |  |
                     }
952 | 0 |
                     catch (IOException e) {
953 | 0 |
                         log.error("Could not load jelly properties from: " + url + ". Reason: " + e, e);
954 |  |
                     }
955 |  |
                     finally {
956 | 0 |
                         try {
957 | 273 |
                             in.close();
958 |  |
                         }
959 | 0 |
                         catch (Exception e) {
960 | 0 |
                             if (log.isDebugEnabled()) log.debug("error closing jelly.properties", e);
961 | 273 |
                         }
962 | 0 |
                     }
963 |  |
                 }
964 |  |
             }
965 | 1027 |
             return jellyProperties;
966 |  |
         }
967 |  |
968 |  |
         /**
969 |  |
          * Factory method to create new Tag script for the given namespaceURI and name or
970 |  |
          * return null if this is not a custom Tag.
971 |  |
          */
972 |  |
         protected TagScript createTag(
973 |  |
             String namespaceURI,
974 |  |
             String localName,
975 |  |
             Attributes list)
976 |  |
             throws SAXException {
977 |  |
             try {
978 |  |
                 // use the URI to load a taglib
979 | 19981 |
                 TagLibrary taglib = context.getTagLibrary(namespaceURI);
980 | 19981 |
                 if (taglib == null) {
981 | 312 |
                     if (namespaceURI != null && namespaceURI.startsWith("jelly:")) {
982 | 65 |
                         String uri = namespaceURI.substring(6);
983 |  |
                         // try to find the class on the claspath
984 |  |
                         try {
985 | 65 |
                             Class taglibClass = getClassLoader().loadClass(uri);
986 | 52 |
                             taglib = (TagLibrary) taglibClass.newInstance();
987 | 52 |
                             context.registerTagLibrary(namespaceURI, taglib);
988 |  |
                         }
989 | 13 |
                         catch (ClassNotFoundException e) {
990 | 13 |
                             throw createSAXException("Could not load class: " + uri + " so taglib instantiation failed", e);
991 |  |
                         }
992 | 0 |
                         catch (IllegalAccessException e) {
993 | 0 |
                             throw createSAXException("Constructor for class is not accessible: " + uri + " so taglib instantiation failed",e);
994 |  |
                         }
995 | 0 |
                         catch (InstantiationException e) {
996 | 0 |
                             throw createSAXException("Class could not be instantiated: " + uri + " so taglib instantiation failed",e);
997 |  |
                         }
998 | 0 |
                         catch (ClassCastException e) {
999 | 0 |
                             throw createSAXException("Class is not a TagLibrary: " + uri + " so taglib instantiation failed",e);
1000 | 52 |
                         }
1001 |  |
                     }
1002 |  |
                 }
1003 | 19968 |
                 if (taglib != null) {
1004 | 19721 |
                     TagScript script = taglib.createTagScript(localName, list);
1005 | 19721 |
                     if ( script != null ) {
1006 | 19721 |
                         configureTagScript(script);
1007 |  |
1008 |  |
                         // clone the attributes to keep them around after this parse
1009 | 19721 |
                         script.setSaxAttributes(new AttributesImpl(list));
1010 |  |
1011 |  |
                         // now iterate through through the expressions
1012 | 19721 |
                         int size = list.getLength();
1013 | 45747 |
                         for (int i = 0; i < size; i++) {
1014 | 26026 |
                             String attributeName = list.getLocalName(i);
1015 | 26026 |
                             String attributeValue = list.getValue(i);
1016 | 26026 |
                             Expression expression =
1017 |  |
                                 taglib.createExpression(
1018 |  |
                                     getExpressionFactory(),
1019 |  |
                                     script,
1020 |  |
                                     attributeName,
1021 |  |
                                     attributeValue);
1022 | 26026 |
                             if (expression == null) {
1023 | 0 |
                                 expression = createConstantExpression(localName, attributeName, attributeValue);
1024 |  |
                             }
1025 | 26026 |
                             script.addAttribute(attributeName, expression);
1026 |  |
                         }
1027 |  |
                     }
1028 | 19721 |
                     return script;
1029 |  |
                 }
1030 | 247 |
                 return null;
1031 |  |
             }
1032 | 13 |
             catch (Exception e) {
1033 | 13 |
                 log.warn(
1034 |  |
                     "Could not create taglib or URI: " + namespaceURI + " tag name: " + localName,
1035 |  |
                     e);
1036 | 13 |
                 throw createSAXException(e);
1037 |  |
             }
1038 |  |
         }
1039 |  |
1040 |  |
1041 |  |
         /**
1042 |  |
          * Factory method to create a static Tag that represents some static content.
1043 |  |
          */
1044 |  |
         protected TagScript createStaticTag(
1045 |  |
             final String namespaceURI,
1046 |  |
             final String localName,
1047 |  |
             final String qName,
1048 |  |
             Attributes list)
1049 |  |
             throws SAXException {
1050 |  |
             try {
1051 | 247 |
                 StaticTag tag = new StaticTag( namespaceURI, localName, qName );
1052 | 247 |
                 StaticTagScript script = new StaticTagScript(
1053 |  |
                     new TagFactory() {
1054 |  |
                         public Tag createTag(String name, Attributes attributes) {
1055 |  |
                             return new StaticTag( namespaceURI, localName, qName );
1056 |  |
                         }
1057 |  |
                     }
1058 |  |
                 );
1059 | 247 |
                 configureTagScript(script);
1060 |  |
1061 |  |
                 // now iterate through through the expressions
1062 | 247 |
                 int size = list.getLength();
1063 | 351 |
                 for (int i = 0; i < size; i++) {
1064 | 104 |
                     String attributeValue = list.getValue(i);
1065 | 104 |
                     Expression expression = CompositeExpression.parse(
1066 |  |
                             attributeValue, getExpressionFactory()
1067 |  |
                         );
1068 | 104 |
                     String attrQName = list.getQName(i);
1069 | 104 |
                     script.addAttribute(attrQName, expression);
1070 |  |
                 }
1071 | 247 |
                 return script;
1072 |  |
             }
1073 | 0 |
             catch (Exception e) {
1074 | 0 |
                 log.warn(
1075 |  |
                     "Could not create static tag for URI: "
1076 |  |
                         + namespaceURI
1077 |  |
                         + " tag name: "
1078 |  |
                         + localName,
1079 |  |
                     e);
1080 | 0 |
                 throw createSAXException(e);
1081 |  |
             }
1082 |  |
         }
1083 |  |
1084 |  |
1085 |  |
         /**
1086 |  |
          * Configure a newly created TagScript instance before any Expressions are created
1087 |  |
          *
1088 |  |
          * @param aTagScript
1089 |  |
          */
1090 |  |
         protected void configureTagScript(TagScript aTagScript) {
1091 |  |
             // set parent relationship...
1092 | 19968 |
             aTagScript.setParent(this.tagScript);
1093 |  |
1094 |  |
             // set the namespace Map
1095 | 19968 |
             if ( elementNamespaces != null ) {
1096 | 1040 |
                 aTagScript.setTagNamespacesMap( elementNamespaces );
1097 | 1040 |
                 elementNamespaces = null;
1098 |  |
             }
1099 | 19968 |
         }
1100 |  |
1101 |  |
         /**
1102 |  |
          * Adds the text to the current script block parsing any embedded
1103 |  |
          * expressions inot ExpressionScript objects.
1104 |  |
          */
1105 |  |
         protected void addTextScript(String text) throws JellyException {
1106 | 27365 |
             Expression expression =
1107 |  |
                 CompositeExpression.parse(text, getExpressionFactory());
1108 |  |
1109 | 27365 |
             addExpressionScript(script, expression);
1110 | 27365 |
         }
1111 |  |
1112 |  |
1113 |  |
         /**
1114 |  |
          * Adds the given Expression object to the current Script.
1115 |  |
          */
1116 |  |
         protected void addExpressionScript(ScriptBlock script, Expression expression) {
1117 | 28405 |
             if ( expression instanceof ConstantExpression ) {
1118 | 27768 |
                 ConstantExpression constantExpression
1119 |  |
                     = (ConstantExpression) expression;
1120 | 27768 |
                 Object value = constantExpression.getValue();
1121 | 27768 |
                 if ( value != null ) {
1122 | 27768 |
                     script.addScript(new TextScript( value.toString() ));
1123 |  |
                 }
1124 | 27768 |
             }
1125 |  |
             else
1126 | 637 |
             if ( expression instanceof CompositeExpression ) {
1127 | 208 |
                 CompositeTextScriptBlock newBlock = new CompositeTextScriptBlock();
1128 | 208 |
                 script.addScript(newBlock);
1129 |  |
1130 | 208 |
                 CompositeExpression compositeExpression
1131 |  |
                     = (CompositeExpression) expression;
1132 | 208 |
                 Iterator iter = compositeExpression.getExpressions().iterator();
1133 | 1248 |
                 while (iter.hasNext()) {
1134 | 1040 |
                     addExpressionScript( newBlock, (Expression) iter.next() );
1135 | 1040 |
                 }
1136 | 208 |
             }
1137 |  |
             else {
1138 | 429 |
                 script.addScript(new ExpressionScript(expression));
1139 |  |
             }
1140 | 28405 |
         }
1141 |  |
1142 |  |
         protected Expression createConstantExpression(
1143 |  |
             String tagName,
1144 |  |
             String attributeName,
1145 |  |
             String attributeValue)  {
1146 | 0 |
             return new ConstantExpression(attributeValue);
1147 |  |
         }
1148 |  |
1149 |  |
         protected ExpressionFactory createExpressionFactory() {
1150 | 1001 |
             return new JexlExpressionFactory();
1151 |  |
         }
1152 |  |
1153 |  |
         /**
1154 |  |
          * @return the current context URI as a String or null if there is no
1155 |  |
          * current context defined on the JellyContext
1156 |  |
          */
1157 |  |
         protected String getCurrentURI() {
1158 | 52 |
             URL url = this.getContext().getCurrentURL();
1159 | 52 |
             return (url != null) ? url.toString() : class="keyword">null;
1160 |  |
         }
1161 |  |
1162 |  |
         /**
1163 |  |
          * Create a SAX exception which also understands about the location in
1164 |  |
          * the file where the exception occurs
1165 |  |
          *
1166 |  |
          * @return the new exception
1167 |  |
          */
1168 |  |
         protected SAXException createSAXException(String message, Exception e) {
1169 | 26 |
             log.warn("Underlying exception: " + e);
1170 | 26 |
             e.printStackTrace();
1171 | 26 |
             if (locator != null) {
1172 | 26 |
                 String error =
1173 |  |
                     "Error at ("
1174 |  |
                         + locator.getLineNumber()
1175 |  |
                         + ", "
1176 |  |
                         + locator.getColumnNumber()
1177 |  |
                         + "): "
1178 |  |
                         + message;
1179 | 26 |
                 if (e != null) {
1180 | 26 |
                     return new SAXParseException(error, locator, e);
1181 |  |
                 }
1182 |  |
                 else {
1183 | 0 |
                     return new SAXParseException(error, locator);
1184 |  |
                 }
1185 |  |
             }
1186 | 0 |
             log.error("No Locator!");
1187 | 0 |
             if (e != null) {
1188 | 0 |
                 return new SAXException(message, e);
1189 |  |
             }
1190 |  |
             else {
1191 | 0 |
                 return new SAXException(message);
1192 |  |
             }
1193 |  |
         }
1194 |  |
1195 |  |
         /**
1196 |  |
          * Create a SAX exception which also understands about the location in
1197 |  |
          * the digester file where the exception occurs
1198 |  |
          *
1199 |  |
          * @return the new exception
1200 |  |
          */
1201 |  |
         protected SAXException createSAXException(Exception e) {
1202 | 13 |
             return createSAXException(e.getMessage(), e);
1203 |  |
         }
1204 |  |
         /**
1205 |  |
          * Create a SAX exception which also understands about the location in
1206 |  |
          * the digester file where the exception occurs
1207 |  |
          *
1208 |  |
          * @return the new exception
1209 |  |
          */
1210 |  |
         protected SAXException createSAXException(String message) {
1211 | 0 |
             return createSAXException(message, null);
1212 |  |
         }
1213 |  |
     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.