001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.chain.config; 018 019import java.net.URL; 020 021import org.apache.commons.chain.Catalog; 022import org.apache.commons.digester.Digester; 023import org.apache.commons.digester.RuleSet; 024 025/** 026 * Class to parse the contents of an XML configuration file (using 027 * Commons Digester) that defines and configures commands and command chains 028 * to be registered in a {@link Catalog}. Advanced users can configure the 029 * detailed parsing behavior by configuring the properties of an instance 030 * of this class prior to calling the {@code parse()} method. It 031 * is legal to call the {@code parse()} method more than once, in order 032 * to parse more than one configuration document. 033 * 034 * @author Craig R. McClanahan 035 * @version $Revision$ $Date$ 036 */ 037public class ConfigParser { 038 039 // ----------------------------------------------------- Instance Variables 040 041 /** 042 * The {@code Digester} to be used for parsing. 043 */ 044 private Digester digester = null; 045 046 /** 047 * The {@code RuleSet} to be used for configuring our Digester 048 * parsing rules. 049 */ 050 private RuleSet ruleSet = null; 051 052 /** 053 * Should Digester use the context class loader? 054 */ 055 private boolean useContextClassLoader = true; 056 057 // ----------------------------------------------------------- Constructors 058 059 /** 060 * The Default-Constructor for this class. 061 */ 062 public ConfigParser() { 063 } 064 065 // ------------------------------------------------------------- Properties 066 067 /** 068 * Return the {@code Digester} instance to be used for 069 * parsing, creating one if necessary. 070 * 071 * @return A Digester instance. 072 */ 073 public Digester getDigester() { 074 if (digester == null) { 075 digester = new Digester(); 076 RuleSet ruleSet = getRuleSet(); 077 digester.setNamespaceAware(ruleSet.getNamespaceURI() != null); 078 digester.setUseContextClassLoader(getUseContextClassLoader()); 079 digester.setValidating(false); 080 digester.addRuleSet(ruleSet); 081 } 082 return digester; 083 } 084 085 /** 086 * Return the {@code RuleSet} to be used for configuring 087 * our {@code Digester} parsing rules, creating one if necessary. 088 * 089 * @return The RuleSet for configuring a Digester instance. 090 */ 091 public RuleSet getRuleSet() { 092 if (ruleSet == null) { 093 ruleSet = new ConfigRuleSet(); 094 } 095 return ruleSet; 096 } 097 098 /** 099 * Set the {@code RuleSet} to be used for configuring 100 * our {@code Digester} parsing rules. 101 * 102 * @param ruleSet The new RuleSet to use 103 */ 104 public void setRuleSet(RuleSet ruleSet) { 105 this.digester = null; 106 this.ruleSet = ruleSet; 107 } 108 109 /** 110 * Return the "use context class loader" flag. If set to 111 * {@code true}, Digester will attempt to instantiate new 112 * command and chain instances from the context class loader. 113 * 114 * @return {@code true} if Digester should use the context class loader. 115 */ 116 public boolean getUseContextClassLoader() { 117 return this.useContextClassLoader; 118 } 119 120 /** 121 * Set the "use context class loader" flag. 122 * 123 * @param useContextClassLoader The new flag value 124 */ 125 public void setUseContextClassLoader(boolean useContextClassLoader) { 126 this.useContextClassLoader = useContextClassLoader; 127 } 128 129 // --------------------------------------------------------- Public Methods 130 131 /** 132 * Parse the XML document at the specified URL, using the configured 133 * {@code RuleSet}, registering top level commands into the specified 134 * {@link Catalog}. Use this method <strong>only</strong> if you have 135 * <strong>NOT</strong> included any {@code factory} element in your 136 * configuration resource, and wish to supply the catalog explicitly. 137 * 138 * @param catalog {@link Catalog} into which configured chains are 139 * to be registered 140 * @param url {@code URL} of the XML document to be parsed 141 * 142 * @throws Exception if a parsing error occurs 143 * 144 * @deprecated Use parse(URL) on a configuration resource with "factory" 145 * element(s) embedded 146 */ 147 @Deprecated 148 public void parse(Catalog<?> catalog, URL url) throws Exception { 149 // Prepare our Digester instance 150 Digester digester = getDigester(); 151 digester.clear(); 152 digester.push(catalog); 153 154 // Parse the configuration document 155 digester.parse(url); 156 } 157 158 /** 159 * Parse the XML document at the specified URL using the configured 160 * {@code RuleSet}, registering catalogs with nested chains and 161 * commands as they are encountered. Use this method <strong>only</strong> 162 * if you have included one or more {@code factory} elements in your 163 * configuration resource. 164 * 165 * @param url {@code URL} of the XML document to be parsed 166 * 167 * @throws Exception if a parsing error occurs 168 */ 169 public void parse(URL url) throws Exception { 170 // Prepare our Digester instance 171 Digester digester = getDigester(); 172 digester.clear(); 173 174 // Parse the configuration document 175 digester.parse(url); 176 } 177}