| /* |
| * Copyright 2004-2005 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.tiles.xmlDefinition; |
| |
| import java.io.BufferedInputStream; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URL; |
| |
| import org.apache.commons.digester.Digester; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Parse an XML definitions file. |
| * |
| * @author Cedric Dumoulin |
| * @author David Geary |
| */ |
| public class XmlParser { |
| /** Associated digester. */ |
| protected Digester digester; |
| /** |
| * Should we use a validating XML parser to read the configuration file. |
| * Default is <code>false</code>. |
| */ |
| protected boolean validating = false; |
| /** |
| * The set of public identifiers, and corresponding resource names for |
| * the versions of the configuration file DTDs we know about. There |
| * <strong>MUST</strong> be an even number of Strings in this list! |
| */ |
| protected String registrations[] = { |
| // pre 1.1 |
| "-//Apache Software Foundation//DTD Tiles Configuration//EN", |
| "/org/apache/struts/resources/tiles-config_1_1.dtd", |
| "-//Apache Software Foundation//DTD Components Configuration//EN", |
| "/org/apache/struts/resources/tiles-config.dtd", |
| // version 1.1 |
| "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN", |
| "/org/apache/struts/resources/tiles-config_1_1.dtd", |
| // version 1.2 |
| "-//Apache Software Foundation//DTD Tiles Configuration 1.2//EN", |
| "/org/apache/tiles/resources/tiles-config_1_2.dtd" |
| }; |
| |
| /** |
| * Constructor. |
| * Creates a digester parser and initializes syntax rules. |
| */ |
| public XmlParser() |
| { |
| digester = new Digester(); |
| digester.setValidating(validating); |
| digester.setNamespaceAware(true); |
| digester.setUseContextClassLoader(true); |
| // Register our local copy of the DTDs that we can find |
| for (int i = 0; i < registrations.length; i += 2) { |
| URL url = this.getClass().getResource(registrations[i+1]); |
| if (url != null) |
| { |
| digester.register(registrations[i], url.toString()); |
| } |
| } |
| // Init syntax rules |
| initDigester( digester ); |
| } |
| |
| /** |
| * Set digester validating flag. |
| */ |
| public void setValidating( boolean validating ) |
| { |
| digester.setValidating( validating); |
| } |
| |
| |
| /** |
| * Init digester for components syntax. |
| * This is an old set of rules, left for backward compatibility. |
| * @param digester Digester instance to use. |
| */ |
| private void initDigesterForComponentsDefinitionsSyntax( Digester digester ) |
| { |
| // Common constants |
| String PACKAGE_NAME = "org.apache.tiles.xmlDefinition"; |
| String DEFINITION_TAG = "component-definitions/definition"; |
| String definitionHandlerClass = PACKAGE_NAME + ".XmlDefinition"; |
| |
| String PUT_TAG = DEFINITION_TAG + "/put"; |
| String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute"; |
| |
| String LIST_TAG = DEFINITION_TAG + "/putList"; |
| String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute"; |
| |
| String ADD_LIST_ELE_TAG = LIST_TAG + "/add"; |
| |
| // syntax rules |
| digester.addObjectCreate( DEFINITION_TAG, definitionHandlerClass ); |
| digester.addSetProperties( DEFINITION_TAG); |
| digester.addSetNext( DEFINITION_TAG, "putDefinition", definitionHandlerClass); |
| // put / putAttribute rules |
| digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass); |
| digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass); |
| digester.addSetProperties( PUT_TAG); |
| digester.addCallMethod( PUT_TAG, "setBody", 0); |
| // list rules |
| digester.addObjectCreate( LIST_TAG, listHandlerClass); |
| digester.addSetProperties( LIST_TAG); |
| digester.addSetNext( LIST_TAG, "addAttribute", putAttributeHandlerClass); |
| // list elements rules |
| // We use Attribute class to avoid rewriting a new class. |
| // Name part can't be used in listElement attribute. |
| digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass); |
| digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass); |
| digester.addSetProperties( ADD_LIST_ELE_TAG); |
| digester.addCallMethod( ADD_LIST_ELE_TAG, "setBody", 0); |
| } |
| |
| /** |
| * Init digester for Tiles syntax. |
| * Same as components, but with first element = tiles-definitions |
| * @param digester Digester instance to use. |
| */ |
| private void initDigesterForTilesDefinitionsSyntax( Digester digester ) |
| { |
| // Common constants |
| String PACKAGE_NAME = "org.apache.tiles.xmlDefinition"; |
| String DEFINITION_TAG = "tiles-definitions/definition"; |
| String definitionHandlerClass = PACKAGE_NAME + ".XmlDefinition"; |
| |
| String PUT_TAG = DEFINITION_TAG + "/put"; |
| String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute"; |
| |
| //String LIST_TAG = DEFINITION_TAG + "/putList"; |
| // List tag value |
| String LIST_TAG = "putList"; |
| String DEF_LIST_TAG = DEFINITION_TAG + "/" + LIST_TAG; |
| String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute"; |
| // Tag value for adding an element in a list |
| String ADD_LIST_ELE_TAG = "*/" + LIST_TAG + "/add"; |
| |
| // syntax rules |
| digester.addObjectCreate( DEFINITION_TAG, definitionHandlerClass ); |
| digester.addSetProperties( DEFINITION_TAG); |
| digester.addSetNext( DEFINITION_TAG, "putDefinition", definitionHandlerClass); |
| // put / putAttribute rules |
| // Rules for a same pattern are called in order, but rule.end() are called |
| // in reverse order. |
| // SetNext and CallMethod use rule.end() method. So, placing SetNext in |
| // first position ensure it will be called last (sic). |
| digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass); |
| digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass); |
| digester.addSetProperties( PUT_TAG); |
| digester.addCallMethod( PUT_TAG, "setBody", 0); |
| // Definition level list rules |
| // This is rules for lists nested in a definition |
| digester.addObjectCreate( DEF_LIST_TAG, listHandlerClass); |
| digester.addSetProperties( DEF_LIST_TAG); |
| digester.addSetNext( DEF_LIST_TAG, "addAttribute", putAttributeHandlerClass); |
| // list elements rules |
| // We use Attribute class to avoid rewriting a new class. |
| // Name part can't be used in listElement attribute. |
| digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass); |
| digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass); |
| digester.addSetProperties( ADD_LIST_ELE_TAG); |
| digester.addCallMethod( ADD_LIST_ELE_TAG, "setBody", 0); |
| |
| // nested list elements rules |
| // Create a list handler, and add it to parent list |
| String NESTED_LIST = "*/" + LIST_TAG + "/" + LIST_TAG; |
| digester.addObjectCreate( NESTED_LIST, listHandlerClass); |
| digester.addSetProperties( NESTED_LIST); |
| digester.addSetNext( NESTED_LIST, "add", putAttributeHandlerClass); |
| |
| // item elements rules |
| // We use Attribute class to avoid rewriting a new class. |
| // Name part can't be used in listElement attribute. |
| //String ADD_WILDCARD = LIST_TAG + "/addItem"; |
| // non String ADD_WILDCARD = LIST_TAG + "/addx*"; |
| String ADD_WILDCARD = "*/item"; |
| String menuItemDefaultClass = "org.apache.tiles.beans.SimpleMenuItem"; |
| digester.addObjectCreate( ADD_WILDCARD, menuItemDefaultClass, "classtype"); |
| digester.addSetNext( ADD_WILDCARD, "add", "java.lang.Object"); |
| digester.addSetProperties( ADD_WILDCARD); |
| |
| // bean elements rules |
| String BEAN_TAG = "*/bean"; |
| String beanDefaultClass = "org.apache.tiles.beans.SimpleMenuItem"; |
| digester.addObjectCreate( BEAN_TAG, beanDefaultClass, "classtype"); |
| digester.addSetNext( BEAN_TAG, "add", "java.lang.Object"); |
| digester.addSetProperties( BEAN_TAG); |
| |
| // Set properties to surrounding element |
| digester.addSetProperty(BEAN_TAG+ "/set-property", "property", "value"); |
| } |
| |
| /** |
| * Init digester in order to parse instances definition file syntax. |
| * Instances is an old name for "definition". This method is left for |
| * backwards compatibility. |
| * @param digester Digester instance to use. |
| */ |
| private void initDigesterForInstancesSyntax( Digester digester ) |
| { |
| // Build a digester to process our configuration resource |
| String PACKAGE_NAME = "org.apache.tiles.xmlDefinition"; |
| String INSTANCE_TAG = "component-instances/instance"; |
| String instanceHandlerClass = PACKAGE_NAME + ".XmlDefinition"; |
| |
| String PUT_TAG = INSTANCE_TAG + "/put"; |
| String PUTATTRIBUTE_TAG = INSTANCE_TAG + "/putAttribute"; |
| String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute"; |
| |
| String LIST_TAG = INSTANCE_TAG + "/putList"; |
| String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute"; |
| |
| String ADD_LIST_ELE_TAG = LIST_TAG + "/add"; |
| |
| // component instance rules |
| digester.addObjectCreate( INSTANCE_TAG, instanceHandlerClass ); |
| digester.addSetProperties( INSTANCE_TAG); |
| digester.addSetNext( INSTANCE_TAG, "putDefinition", instanceHandlerClass); |
| // put / putAttribute rules |
| digester.addObjectCreate( PUTATTRIBUTE_TAG, putAttributeHandlerClass); |
| digester.addSetProperties( PUTATTRIBUTE_TAG); |
| digester.addSetNext( PUTATTRIBUTE_TAG, "addAttribute", putAttributeHandlerClass); |
| // put / putAttribute rules |
| digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass); |
| digester.addSetProperties( PUT_TAG); |
| digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass); |
| // list rules |
| digester.addObjectCreate( LIST_TAG, listHandlerClass); |
| digester.addSetProperties( LIST_TAG); |
| digester.addSetNext( LIST_TAG, "addAttribute", putAttributeHandlerClass); |
| // list elements rules |
| // We use Attribute class to avoid rewriting a new class. |
| // Name part can't be used in listElement attribute. |
| digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass); |
| digester.addSetProperties( ADD_LIST_ELE_TAG); |
| digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass); |
| } |
| |
| /** |
| * Init digester. |
| * @param digester Digester instance to use. |
| */ |
| protected void initDigester( Digester digester ) |
| { |
| initDigesterForTilesDefinitionsSyntax( digester ); |
| initDigesterForComponentsDefinitionsSyntax( digester ); |
| initDigesterForInstancesSyntax( digester ); |
| } |
| |
| /** |
| * Parse input reader and add encountered definitions to definitions set. |
| * @param in Input stream. |
| * @param definitions Xml Definitions set to which encountered definition are added. |
| * @throws IOException On errors during file parsing. |
| * @throws SAXException On errors parsing XML. |
| */ |
| public void parse( InputStream in, XmlDefinitionsSet definitions ) throws IOException, SAXException |
| { |
| try |
| { |
| // set first object in stack |
| //digester.clear(); |
| digester.push(definitions); |
| // parse |
| digester.parse(in); |
| in.close(); |
| } |
| catch (SAXException e) |
| { |
| //throw new ServletException( "Error while parsing " + mappingConfig, e); |
| throw e; |
| } |
| |
| } |
| |
| /** |
| * Main method to check file syntax. |
| */ |
| public static void main(String[] args) |
| { |
| //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-struts/WEB-INF/tiles-examples-defs.xml"; |
| String filename = "E:/programs/jakarta-tomcat-4.0.3/webapps/wtiles-struts/WEB-INF/tiles-examples-defs.xml"; |
| //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-struts/WEB-INF/tilesDefinitions.xml"; |
| //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-channel/WEB-INF/componentDefinitions.xml"; |
| //String filename2 = "E:/programs/jakarta-tomcat/webapps/wtiles-tutorial/WEB-INF/componentDefinitions.xml"; |
| |
| |
| if( args.length > 1 ) |
| { |
| filename = args[1]; |
| } // end if |
| |
| System.out.println( "Read file '" + filename +"'" ); |
| |
| InputStream input = null; |
| // InputStream input2 = null; |
| // Open file |
| try |
| { |
| input = new BufferedInputStream( |
| new FileInputStream( filename) ); |
| // input2 = new BufferedInputStream( |
| // new FileInputStream( filename2) ); |
| } |
| catch( IOException ex ) |
| { |
| System.out.println( "can't open file '" + filename + "' : " + ex.getMessage() ); |
| } |
| // Check file syntax |
| try |
| { |
| XmlParser parser = new XmlParser(); |
| parser.setValidating(true); |
| XmlDefinitionsSet definitions = new XmlDefinitionsSet(); |
| System.out.println( " Parse file" ); |
| parser.parse( input, definitions); |
| // System.out.println( " Check file 2" ); |
| //parser.parse( input2, definitions); |
| System.out.println( " done." ); |
| System.out.println( " Result : " + definitions.toString() ); |
| } |
| catch( Exception ex ) |
| { |
| System.out.println( "Error during parsing '" + filename + "' : " + ex.getMessage() ); |
| ex.printStackTrace(); |
| } |
| } |
| |
| } |