1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.chain.config; 18 19 import java.net.URL; 20 21 import org.apache.commons.chain.Catalog; 22 import org.apache.commons.digester.Digester; 23 import org.apache.commons.digester.RuleSet; 24 25 /** 26 * Class to parse the contents of an XML configuration file (using 27 * Commons Digester) that defines and configures commands and command chains 28 * to be registered in a {@link Catalog}. Advanced users can configure the 29 * detailed parsing behavior by configuring the properties of an instance 30 * of this class prior to calling the {@code parse()} method. It 31 * is legal to call the {@code parse()} method more than once, in order 32 * to parse more than one configuration document. 33 * 34 * @author Craig R. McClanahan 35 * @version $Revision$ $Date$ 36 */ 37 public class ConfigParser { 38 39 // ----------------------------------------------------- Instance Variables 40 41 /** 42 * The {@code Digester} to be used for parsing. 43 */ 44 private Digester digester = null; 45 46 /** 47 * The {@code RuleSet} to be used for configuring our Digester 48 * parsing rules. 49 */ 50 private RuleSet ruleSet = null; 51 52 /** 53 * Should Digester use the context class loader? 54 */ 55 private boolean useContextClassLoader = true; 56 57 // ----------------------------------------------------------- Constructors 58 59 /** 60 * The Default-Constructor for this class. 61 */ 62 public ConfigParser() { 63 } 64 65 // ------------------------------------------------------------- Properties 66 67 /** 68 * Return the {@code Digester} instance to be used for 69 * parsing, creating one if necessary. 70 * 71 * @return A Digester instance. 72 */ 73 public Digester getDigester() { 74 if (digester == null) { 75 digester = new Digester(); 76 RuleSet ruleSet = getRuleSet(); 77 digester.setNamespaceAware(ruleSet.getNamespaceURI() != null); 78 digester.setUseContextClassLoader(getUseContextClassLoader()); 79 digester.setValidating(false); 80 digester.addRuleSet(ruleSet); 81 } 82 return digester; 83 } 84 85 /** 86 * Return the {@code RuleSet} to be used for configuring 87 * our {@code Digester} parsing rules, creating one if necessary. 88 * 89 * @return The RuleSet for configuring a Digester instance. 90 */ 91 public RuleSet getRuleSet() { 92 if (ruleSet == null) { 93 ruleSet = new ConfigRuleSet(); 94 } 95 return ruleSet; 96 } 97 98 /** 99 * 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 }