View Javadoc

1   /*
2    * $Header: /usr/local/cvsroot/dev/madcache/src/com/macvu/tiles/xmlDefinition/XmlCacheParser.java,v 1.1 2004/04/08 06:24:44 macvu Exp $
3    * $Revision: 1.1 $
4    * $Date: 2004/04/08 06:24:44 $
5    *
6    * ====================================================================
7    *
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer.
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution, if
26   *    any, must include the following acknowlegement:
27   *       "This product includes software developed by the
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowlegement may appear in the software itself,
30   *    if and wherever such third-party acknowlegements normally appear.
31   *
32   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
33   *    Foundation" must not be used to endorse or promote products derived
34   *    from this software without prior written permission. For written
35   *    permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache"
38   *    nor may "Apache" appear in their names without prior written
39   *    permission of the Apache Group.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   *
60   */
61  
62  package com.macvu.tiles.xmlDefinition;
63  
64  import org.apache.commons.digester.Digester;
65  import org.xml.sax.SAXException;
66  
67  import java.io.IOException;
68  import java.io.InputStream;
69  import java.net.URL;
70  
71  public class XmlCacheParser {
72  
73      /***
74       * Associated digester.
75       */
76      protected Digester digester;
77      /***
78       * Should we use a validating XML parser to read the configuration file.
79       * Default is <code>false</code>.
80       */
81      protected boolean validating = false;
82      /***
83       * The set of public identifiers, and corresponding resource names for
84       * the versions of the configuration file DTDs we know about.  There
85       * <strong>MUST</strong> be an even number of Strings in this list!
86       */
87      protected String registrations[] = {
88          // pre 1.1
89          "-//Apache Software Foundation//DTD Tiles Configuration//EN",
90          "/org/apache/struts/resources/tiles-config_1_1.dtd",
91          "-//Apache Software Foundation//DTD Components Configuration//EN",
92          "/org/apache/struts/resources/tiles-config.dtd",
93          // version 1.1
94          "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN",
95          "/org/apache/struts/resources/tiles-config_1_1.dtd",
96      };
97  
98      /***
99       * Constructor.
100      * Creates a digester parser and initializes syntax rules.
101      */
102     public XmlCacheParser() {
103         digester = new Digester();
104         digester.setValidating(validating);
105         digester.setNamespaceAware(true);
106         digester.setUseContextClassLoader(true);
107         // Register our local copy of the DTDs that we can find
108         for (int i = 0; i < registrations.length; i += 2) {
109             URL url = this.getClass().getResource(registrations[i + 1]);
110             if (url != null) {
111                 digester.register(registrations[i], url.toString());
112             }
113         }
114         // Init syntax rules
115         initDigester(digester);
116     }
117 
118     /***
119      * Set digester validating flag.
120      */
121     public void setValidating(boolean validating) {
122         digester.setValidating(validating);
123     }
124 
125     /***
126      * Set digester detail level.
127      *
128      * @deprecated Use the commons-logging to set digester debug level.
129      */
130     public void setDetailLevel(int detailLevel) {
131     }
132 
133     /***
134      * Init digester for components syntax.
135      * This is an old set of rules, left for backward compatibility.
136      *
137      * @param digester Digester instance to use.
138      * @deprecated
139      */
140     private void initDigesterForComponentsDefinitionsSyntax(Digester digester) {
141         // Common constants
142         String PACKAGE_NAME = "com.macvu.tiles.xmlDefinition";
143         String TILES_PACKAGE_NAME = "org.apache.struts.tiles.xmlDefinition";
144 
145         String DEFINITION_TAG = "component-definitions/definition";
146         String definitionHandlerClass = PACKAGE_NAME + ".XmlCacheDefinition";
147 
148         String PUT_TAG = DEFINITION_TAG + "/put";
149         String putAttributeHandlerClass = TILES_PACKAGE_NAME + ".XmlAttribute";
150 
151         String LIST_TAG = DEFINITION_TAG + "/putList";
152         String listHandlerClass = TILES_PACKAGE_NAME + ".XmlListAttribute";
153 
154         String ADD_LIST_ELE_TAG = LIST_TAG + "/add";
155 
156         // syntax rules
157         digester.addObjectCreate(DEFINITION_TAG, definitionHandlerClass);
158         digester.addSetProperties(DEFINITION_TAG);
159         digester.addSetNext(DEFINITION_TAG, "putDefinition", definitionHandlerClass);
160         // put / putAttribute rules
161         digester.addObjectCreate(PUT_TAG, putAttributeHandlerClass);
162         digester.addSetNext(PUT_TAG, "addAttribute", putAttributeHandlerClass);
163         digester.addSetProperties(PUT_TAG);
164         digester.addCallMethod(PUT_TAG, "setBody", 0);
165         // list rules
166         digester.addObjectCreate(LIST_TAG, listHandlerClass);
167         digester.addSetProperties(LIST_TAG);
168         digester.addSetNext(LIST_TAG, "addAttribute", putAttributeHandlerClass);
169         // list elements rules
170         // We use Attribute class to avoid rewriting a new class.
171         // Name part can't be used in listElement attribute.
172         digester.addObjectCreate(ADD_LIST_ELE_TAG, putAttributeHandlerClass);
173         digester.addSetNext(ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
174         digester.addSetProperties(ADD_LIST_ELE_TAG);
175         digester.addCallMethod(ADD_LIST_ELE_TAG, "setBody", 0);
176     }
177 
178     /***
179      * Init digester in order to parse instances definition file syntax.
180      * Instances is an old name for "definition". This method is left for
181      * backwards compatibility.
182      *
183      * @param digester Digester instance to use.
184      * @deprecated
185      */
186     private void initDigesterForInstancesSyntax(Digester digester) {
187         // Build a digester to process our configuration resource
188         String PACKAGE_NAME = "org.apache.struts.tiles.xmlDefinition";
189         String INSTANCE_TAG = "component-instances/instance";
190         String instanceHandlerClass = PACKAGE_NAME + ".XmlDefinition";
191 
192         String PUT_TAG = INSTANCE_TAG + "/put";
193         String PUTATTRIBUTE_TAG = INSTANCE_TAG + "/putAttribute";
194         String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute";
195 
196         String LIST_TAG = INSTANCE_TAG + "/putList";
197         String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute";
198 
199         String ADD_LIST_ELE_TAG = LIST_TAG + "/add";
200 
201         // component instance rules
202         digester.addObjectCreate(INSTANCE_TAG, instanceHandlerClass);
203         digester.addSetProperties(INSTANCE_TAG);
204         digester.addSetNext(INSTANCE_TAG, "putDefinition", instanceHandlerClass);
205         // put / putAttribute rules
206         digester.addObjectCreate(PUTATTRIBUTE_TAG, putAttributeHandlerClass);
207         digester.addSetProperties(PUTATTRIBUTE_TAG);
208         digester.addSetNext(PUTATTRIBUTE_TAG, "addAttribute", putAttributeHandlerClass);
209         // put / putAttribute rules
210         digester.addObjectCreate(PUT_TAG, putAttributeHandlerClass);
211         digester.addSetProperties(PUT_TAG);
212         digester.addSetNext(PUT_TAG, "addAttribute", putAttributeHandlerClass);
213         // list rules
214         digester.addObjectCreate(LIST_TAG, listHandlerClass);
215         digester.addSetProperties(LIST_TAG);
216         digester.addSetNext(LIST_TAG, "addAttribute", putAttributeHandlerClass);
217         // list elements rules
218         // We use Attribute class to avoid rewriting a new class.
219         // Name part can't be used in listElement attribute.
220         digester.addObjectCreate(ADD_LIST_ELE_TAG, putAttributeHandlerClass);
221         digester.addSetProperties(ADD_LIST_ELE_TAG);
222         digester.addSetNext(ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
223     }
224 
225     /***
226      * Init digester for Tiles syntax.
227      * Same as components, but with first element = tiles-definitions
228      *
229      * @param digester Digester instance to use.
230      */
231     private void initDigesterForTilesDefinitionsSyntax(Digester digester) {
232         // Common constants
233         String PACKAGE_NAME = "com.macvu.tiles.xmlDefinition";
234         String TILES_PACKAGE_NAME = "org.apache.struts.tiles.xmlDefinition";
235         String DEFINITION_TAG = "tiles-definitions/definition";
236         String definitionHandlerClass = PACKAGE_NAME + ".XmlCacheDefinition";
237 
238         String PUT_TAG = DEFINITION_TAG + "/put";
239         String putAttributeHandlerClass = TILES_PACKAGE_NAME + ".XmlAttribute";
240 
241         String CACHE_INFORMATION_TAG = DEFINITION_TAG + "/cacheInformation";
242         String cacheInformationHandlerClass = PACKAGE_NAME + ".XmlCacheInformation";
243 
244         String CACHE_ATTRIBUTE_TAG = CACHE_INFORMATION_TAG + "/key";
245         String cacheKeyHandlerClass = PACKAGE_NAME + ".XmlCacheAttribute";
246 
247         //String LIST_TAG = DEFINITION_TAG + "/putList";
248         // List tag value
249         String LIST_TAG = "putList";
250         String DEF_LIST_TAG = DEFINITION_TAG + "/" + LIST_TAG;
251         String listHandlerClass = TILES_PACKAGE_NAME + ".XmlListAttribute";
252         // Tag value for adding an element in a list
253         String ADD_LIST_ELE_TAG = "*/" + LIST_TAG + "/add";
254 
255         // syntax rules
256         digester.addObjectCreate(DEFINITION_TAG, definitionHandlerClass);
257         digester.addSetProperties(DEFINITION_TAG);
258         digester.addSetNext(DEFINITION_TAG, "putDefinition", definitionHandlerClass);
259         // put / putAttribute rules
260         // Rules for a same pattern are called in order, but rule.end() are called
261         // in reverse order.
262         // SetNext and CallMethod use rule.end() method. So, placing SetNext in
263         // first position ensure it will be called last (sic).
264         digester.addObjectCreate(PUT_TAG, putAttributeHandlerClass);
265         digester.addSetNext(PUT_TAG, "addAttribute", putAttributeHandlerClass);
266         digester.addSetProperties(PUT_TAG);
267         digester.addCallMethod(PUT_TAG, "setBody", 0);
268         // Definition level list rules
269         // This is rules for lists nested in a definition
270         digester.addObjectCreate(DEF_LIST_TAG, listHandlerClass);
271         digester.addSetProperties(DEF_LIST_TAG);
272         digester.addSetNext(DEF_LIST_TAG, "addAttribute", putAttributeHandlerClass);
273         // list elements rules
274         // We use Attribute class to avoid rewriting a new class.
275         // Name part can't be used in listElement attribute.
276         digester.addObjectCreate(ADD_LIST_ELE_TAG, putAttributeHandlerClass);
277         digester.addSetNext(ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
278         digester.addSetProperties(ADD_LIST_ELE_TAG);
279         digester.addCallMethod(ADD_LIST_ELE_TAG, "setBody", 0);
280 
281         // nested list elements rules
282         // Create a list handler, and add it to parent list
283         String NESTED_LIST = "*/" + LIST_TAG + "/" + LIST_TAG;
284         digester.addObjectCreate(NESTED_LIST, listHandlerClass);
285         digester.addSetProperties(NESTED_LIST);
286         digester.addSetNext(NESTED_LIST, "add", putAttributeHandlerClass);
287 
288         // item elements rules
289         // We use Attribute class to avoid rewriting a new class.
290         // Name part can't be used in listElement attribute.
291         //String ADD_WILDCARD = LIST_TAG + "/addItem";
292         // non String ADD_WILDCARD = LIST_TAG + "/addx*";
293         String ADD_WILDCARD = "*/item";
294         String menuItemDefaultClass = "org.apache.struts.tiles.beans.SimpleMenuItem";
295         digester.addObjectCreate(ADD_WILDCARD, menuItemDefaultClass, "classtype");
296         digester.addSetNext(ADD_WILDCARD, "add", "java.lang.Object");
297         digester.addSetProperties(ADD_WILDCARD);
298 
299         // bean elements rules
300         String BEAN_TAG = "*/bean";
301         String beanDefaultClass = "org.apache.struts.tiles.beans.SimpleMenuItem";
302         digester.addObjectCreate(BEAN_TAG, beanDefaultClass, "classtype");
303         digester.addSetNext(BEAN_TAG, "add", "java.lang.Object");
304         digester.addSetProperties(BEAN_TAG);
305 
306         // Set properties to surrounding element
307         digester.addSetProperty(BEAN_TAG + "/set-property", "property", "value");
308 
309         digester.addObjectCreate(CACHE_INFORMATION_TAG, cacheInformationHandlerClass);
310         digester.addSetProperties(CACHE_INFORMATION_TAG);
311         digester.addSetNext(CACHE_INFORMATION_TAG, "addCacheInformation", cacheInformationHandlerClass);
312 
313         digester.addObjectCreate(CACHE_ATTRIBUTE_TAG, cacheKeyHandlerClass);
314         digester.addSetProperties(CACHE_ATTRIBUTE_TAG);
315         digester.addSetNext(CACHE_ATTRIBUTE_TAG, "addCacheAttribute", cacheKeyHandlerClass);
316     }
317 
318     /***
319      * Init digester.
320      *
321      * @param digester Digester instance to use.
322      */
323     protected void initDigester(Digester digester) {
324         initDigesterForTilesDefinitionsSyntax(digester);
325         initDigesterForComponentsDefinitionsSyntax(digester);
326         initDigesterForInstancesSyntax(digester);
327     }
328 
329     /***
330      * Parse input reader and add encountered definitions to definitions set.
331      *
332      * @param in          Input stream.
333      * @param definitions Xml Definitions set to which encountered definition are added.
334      * @throws java.io.IOException      On errors during file parsing.
335      * @throws org.xml.sax.SAXException On errors parsing XML.
336      */
337     public void parse(InputStream in, XmlCacheDefinitionSet definitions) throws IOException, SAXException {
338         try {
339             // set first object in stack
340             //digester.clear();
341             digester.push(definitions);
342             // parse
343             digester.parse(in);
344             in.close();
345         } catch (SAXException e) {
346             //throw new ServletException( "Error while parsing " + mappingConfig, e);
347             throw e;
348         }
349 
350     }
351 }