Source code: org/apache/struts/tiles/xmlDefinition/XmlParser.java
1 /*
2 * $Id: XmlParser.java 54929 2004-10-16 16:38:42Z germuska $
3 *
4 * Copyright 1999-2004 The Apache Software Foundation.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19
20 package org.apache.struts.tiles.xmlDefinition;
21
22 import java.io.BufferedInputStream;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.URL;
27
28 import org.apache.commons.digester.Digester;
29 import org.xml.sax.SAXException;
30
31 /**
32 * Parse an XML definitions file.
33 */
34 public class XmlParser
35 {
36
37 /** Associated digester. */
38 protected Digester digester;
39 /**
40 * Should we use a validating XML parser to read the configuration file.
41 * Default is <code>false</code>.
42 */
43 protected boolean validating = false;
44 /**
45 * The set of public identifiers, and corresponding resource names for
46 * the versions of the configuration file DTDs we know about. There
47 * <strong>MUST</strong> be an even number of Strings in this list!
48 */
49 protected String registrations[] = {
50 "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN",
51 "/org/apache/struts/resources/tiles-config_1_1.dtd",
52 };
53
54 /**
55 * Constructor.
56 * Creates a digester parser and initializes syntax rules.
57 */
58 public XmlParser()
59 {
60 digester = new Digester();
61 digester.setValidating(validating);
62 digester.setNamespaceAware(true);
63 digester.setUseContextClassLoader(true);
64 // Register our local copy of the DTDs that we can find
65 for (int i = 0; i < registrations.length; i += 2) {
66 URL url = this.getClass().getResource(registrations[i+1]);
67 if (url != null)
68 {
69 digester.register(registrations[i], url.toString());
70 }
71 }
72 // Init syntax rules
73 initDigester( digester );
74 }
75
76 /**
77 * Set digester validating flag.
78 */
79 public void setValidating( boolean validating )
80 {
81 digester.setValidating( validating);
82 }
83
84
85 /**
86 * Init digester for components syntax.
87 * This is an old set of rules, left for backward compatibility.
88 * @param digester Digester instance to use.
89 */
90 private void initDigesterForComponentsDefinitionsSyntax( Digester digester )
91 {
92 // Common constants
93 String PACKAGE_NAME = "org.apache.struts.tiles.xmlDefinition";
94 String DEFINITION_TAG = "component-definitions/definition";
95 String definitionHandlerClass = PACKAGE_NAME + ".XmlDefinition";
96
97 String PUT_TAG = DEFINITION_TAG + "/put";
98 String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute";
99
100 String LIST_TAG = DEFINITION_TAG + "/putList";
101 String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute";
102
103 String ADD_LIST_ELE_TAG = LIST_TAG + "/add";
104
105 // syntax rules
106 digester.addObjectCreate( DEFINITION_TAG, definitionHandlerClass );
107 digester.addSetProperties( DEFINITION_TAG);
108 digester.addSetNext( DEFINITION_TAG, "putDefinition", definitionHandlerClass);
109 // put / putAttribute rules
110 digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass);
111 digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass);
112 digester.addSetProperties( PUT_TAG);
113 digester.addCallMethod( PUT_TAG, "setBody", 0);
114 // list rules
115 digester.addObjectCreate( LIST_TAG, listHandlerClass);
116 digester.addSetProperties( LIST_TAG);
117 digester.addSetNext( LIST_TAG, "addAttribute", putAttributeHandlerClass);
118 // list elements rules
119 // We use Attribute class to avoid rewriting a new class.
120 // Name part can't be used in listElement attribute.
121 digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass);
122 digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
123 digester.addSetProperties( ADD_LIST_ELE_TAG);
124 digester.addCallMethod( ADD_LIST_ELE_TAG, "setBody", 0);
125 }
126
127 /**
128 * Init digester for Tiles syntax.
129 * Same as components, but with first element = tiles-definitions
130 * @param digester Digester instance to use.
131 */
132 private void initDigesterForTilesDefinitionsSyntax( Digester digester )
133 {
134 // Common constants
135 String PACKAGE_NAME = "org.apache.struts.tiles.xmlDefinition";
136 String DEFINITION_TAG = "tiles-definitions/definition";
137 String definitionHandlerClass = PACKAGE_NAME + ".XmlDefinition";
138
139 String PUT_TAG = DEFINITION_TAG + "/put";
140 String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute";
141
142 //String LIST_TAG = DEFINITION_TAG + "/putList";
143 // List tag value
144 String LIST_TAG = "putList";
145 String DEF_LIST_TAG = DEFINITION_TAG + "/" + LIST_TAG;
146 String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute";
147 // Tag value for adding an element in a list
148 String ADD_LIST_ELE_TAG = "*/" + LIST_TAG + "/add";
149
150 // syntax rules
151 digester.addObjectCreate( DEFINITION_TAG, definitionHandlerClass );
152 digester.addSetProperties( DEFINITION_TAG);
153 digester.addSetNext( DEFINITION_TAG, "putDefinition", definitionHandlerClass);
154 // put / putAttribute rules
155 // Rules for a same pattern are called in order, but rule.end() are called
156 // in reverse order.
157 // SetNext and CallMethod use rule.end() method. So, placing SetNext in
158 // first position ensure it will be called last (sic).
159 digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass);
160 digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass);
161 digester.addSetProperties( PUT_TAG);
162 digester.addCallMethod( PUT_TAG, "setBody", 0);
163 // Definition level list rules
164 // This is rules for lists nested in a definition
165 digester.addObjectCreate( DEF_LIST_TAG, listHandlerClass);
166 digester.addSetProperties( DEF_LIST_TAG);
167 digester.addSetNext( DEF_LIST_TAG, "addAttribute", putAttributeHandlerClass);
168 // list elements rules
169 // We use Attribute class to avoid rewriting a new class.
170 // Name part can't be used in listElement attribute.
171 digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass);
172 digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
173 digester.addSetProperties( ADD_LIST_ELE_TAG);
174 digester.addCallMethod( ADD_LIST_ELE_TAG, "setBody", 0);
175
176 // nested list elements rules
177 // Create a list handler, and add it to parent list
178 String NESTED_LIST = "*/" + LIST_TAG + "/" + LIST_TAG;
179 digester.addObjectCreate( NESTED_LIST, listHandlerClass);
180 digester.addSetProperties( NESTED_LIST);
181 digester.addSetNext( NESTED_LIST, "add", putAttributeHandlerClass);
182
183 // item elements rules
184 // We use Attribute class to avoid rewriting a new class.
185 // Name part can't be used in listElement attribute.
186 //String ADD_WILDCARD = LIST_TAG + "/addItem";
187 // non String ADD_WILDCARD = LIST_TAG + "/addx*";
188 String ADD_WILDCARD = "*/item";
189 String menuItemDefaultClass = "org.apache.struts.tiles.beans.SimpleMenuItem";
190 digester.addObjectCreate( ADD_WILDCARD, menuItemDefaultClass, "classtype");
191 digester.addSetNext( ADD_WILDCARD, "add", "java.lang.Object");
192 digester.addSetProperties( ADD_WILDCARD);
193
194 // bean elements rules
195 String BEAN_TAG = "*/bean";
196 String beanDefaultClass = "org.apache.struts.tiles.beans.SimpleMenuItem";
197 digester.addObjectCreate( BEAN_TAG, beanDefaultClass, "classtype");
198 digester.addSetNext( BEAN_TAG, "add", "java.lang.Object");
199 digester.addSetProperties( BEAN_TAG);
200
201 // Set properties to surrounding element
202 digester.addSetProperty(BEAN_TAG+ "/set-property", "property", "value");
203 }
204
205 /**
206 * Init digester in order to parse instances definition file syntax.
207 * Instances is an old name for "definition". This method is left for
208 * backwards compatibility.
209 * @param digester Digester instance to use.
210 */
211 private void initDigesterForInstancesSyntax( Digester digester )
212 {
213 // Build a digester to process our configuration resource
214 String PACKAGE_NAME = "org.apache.struts.tiles.xmlDefinition";
215 String INSTANCE_TAG = "component-instances/instance";
216 String instanceHandlerClass = PACKAGE_NAME + ".XmlDefinition";
217
218 String PUT_TAG = INSTANCE_TAG + "/put";
219 String PUTATTRIBUTE_TAG = INSTANCE_TAG + "/putAttribute";
220 String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute";
221
222 String LIST_TAG = INSTANCE_TAG + "/putList";
223 String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute";
224
225 String ADD_LIST_ELE_TAG = LIST_TAG + "/add";
226
227 // component instance rules
228 digester.addObjectCreate( INSTANCE_TAG, instanceHandlerClass );
229 digester.addSetProperties( INSTANCE_TAG);
230 digester.addSetNext( INSTANCE_TAG, "putDefinition", instanceHandlerClass);
231 // put / putAttribute rules
232 digester.addObjectCreate( PUTATTRIBUTE_TAG, putAttributeHandlerClass);
233 digester.addSetProperties( PUTATTRIBUTE_TAG);
234 digester.addSetNext( PUTATTRIBUTE_TAG, "addAttribute", putAttributeHandlerClass);
235 // put / putAttribute rules
236 digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass);
237 digester.addSetProperties( PUT_TAG);
238 digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass);
239 // list rules
240 digester.addObjectCreate( LIST_TAG, listHandlerClass);
241 digester.addSetProperties( LIST_TAG);
242 digester.addSetNext( LIST_TAG, "addAttribute", putAttributeHandlerClass);
243 // list elements rules
244 // We use Attribute class to avoid rewriting a new class.
245 // Name part can't be used in listElement attribute.
246 digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass);
247 digester.addSetProperties( ADD_LIST_ELE_TAG);
248 digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
249 }
250
251 /**
252 * Init digester.
253 * @param digester Digester instance to use.
254 */
255 protected void initDigester( Digester digester )
256 {
257 initDigesterForTilesDefinitionsSyntax( digester );
258 initDigesterForComponentsDefinitionsSyntax( digester );
259 initDigesterForInstancesSyntax( digester );
260 }
261
262 /**
263 * Parse input reader and add encountered definitions to definitions set.
264 * @param in Input stream.
265 * @param definitions Xml Definitions set to which encountered definition are added.
266 * @throws IOException On errors during file parsing.
267 * @throws SAXException On errors parsing XML.
268 */
269 public void parse( InputStream in, XmlDefinitionsSet definitions ) throws IOException, SAXException
270 {
271 try
272 {
273 // set first object in stack
274 //digester.clear();
275 digester.push(definitions);
276 // parse
277 digester.parse(in);
278 in.close();
279 }
280 catch (SAXException e)
281 {
282 //throw new ServletException( "Error while parsing " + mappingConfig, e);
283 throw e;
284 }
285
286 }
287
288 /**
289 * Main method to check file syntax.
290 */
291 public static void main(String[] args)
292 {
293 //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-struts/WEB-INF/tiles-examples-defs.xml";
294 String filename = "E:/programs/jakarta-tomcat-4.0.3/webapps/wtiles-struts/WEB-INF/tiles-examples-defs.xml";
295 //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-struts/WEB-INF/tilesDefinitions.xml";
296 //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-channel/WEB-INF/componentDefinitions.xml";
297 //String filename2 = "E:/programs/jakarta-tomcat/webapps/wtiles-tutorial/WEB-INF/componentDefinitions.xml";
298
299
300 if( args.length > 1 )
301 {
302 filename = args[1];
303 } // end if
304
305 System.out.println( "Read file '" + filename +"'" );
306
307 InputStream input = null;
308 // InputStream input2 = null;
309 // Open file
310 try
311 {
312 input = new BufferedInputStream(
313 new FileInputStream( filename) );
314 // input2 = new BufferedInputStream(
315 // new FileInputStream( filename2) );
316 }
317 catch( IOException ex )
318 {
319 System.out.println( "can't open file '" + filename + "' : " + ex.getMessage() );
320 }
321 // Check file syntax
322 try
323 {
324 XmlParser parser = new XmlParser();
325 parser.setValidating(true);
326 XmlDefinitionsSet definitions = new XmlDefinitionsSet();
327 System.out.println( " Parse file" );
328 parser.parse( input, definitions);
329 // System.out.println( " Check file 2" );
330 //parser.parse( input2, definitions);
331 System.out.println( " done." );
332 System.out.println( " Result : " + definitions.toString() );
333 }
334 catch( Exception ex )
335 {
336 System.out.println( "Error during parsing '" + filename + "' : " + ex.getMessage() );
337 ex.printStackTrace();
338 }
339 }
340
341 }