001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package de.schlund.pfixxml.config;
020:
021: import java.io.File;
022: import java.io.FileInputStream;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.util.Properties;
026:
027: import javax.xml.parsers.ParserConfigurationException;
028: import javax.xml.parsers.SAXParser;
029: import javax.xml.parsers.SAXParserFactory;
030:
031: import org.apache.commons.digester.Digester;
032: import org.apache.commons.digester.Rule;
033: import org.apache.commons.digester.RulesBase;
034: import org.apache.commons.digester.WithDefaultsRulesWrapper;
035: import org.apache.log4j.Logger;
036: import org.xml.sax.Attributes;
037: import org.xml.sax.SAXException;
038:
039: import de.schlund.pfixxml.config.impl.DefaultMatchRule;
040: import de.schlund.pfixxml.resources.FileResource;
041:
042: /**
043: * Loads properties from a XML file
044: *
045: * @author Sebastian Marsching <sebastian.marsching@1und1.de>
046: */
047: public abstract class XMLPropertiesUtil {
048: private static final String PROPS_NS = "http://pustefix.sourceforge.net/properties200401";
049:
050: private static final String CUS_NS = "http://www.schlund.de/pustefix/customize";
051:
052: private static final Logger LOG = Logger
053: .getLogger(XMLPropertiesUtil.class);
054:
055: // Define PropertyRule inline
056: public static class PropertyRule extends Rule {
057:
058: private Properties props;
059:
060: private String propName;
061:
062: private String propValue;
063:
064: public PropertyRule(Properties props) {
065: this .props = props;
066: }
067:
068: /* (non-Javadoc)
069: * @see org.apache.commons.digester.Rule#begin(java.lang.String, java.lang.String, org.xml.sax.Attributes)
070: */
071: public void begin(String namespace, String name,
072: Attributes attributes) throws Exception {
073: this .propName = attributes.getValue("name");
074: this .propValue = "";
075: if (propName == null) {
076: throw new SAXException(
077: "Mandatory attribute \"name\" is missing!");
078: }
079: }
080:
081: /* (non-Javadoc)
082: * @see org.apache.commons.digester.Rule#end(java.lang.String, java.lang.String)
083: */
084: public void end(String namespace, String name) throws Exception {
085: if (props.getProperty(propName) != null) {
086: LOG.warn("Overwriting already set property \""
087: + propName + "\" with value \""
088: + propValue.trim() + "\"!");
089: }
090: props.setProperty(propName, unesacpePropertyValue(propValue
091: .trim()));
092: }
093:
094: /* (non-Javadoc)
095: * @see org.apache.commons.digester.Rule#body(java.lang.String, java.lang.String, java.lang.String)
096: */
097: public void body(String namespace, String name, String text)
098: throws Exception {
099: this .propValue += text;
100: }
101:
102: }
103:
104: public static Properties loadPropertiesFromXMLFile(File file)
105: throws SAXException, IOException {
106: Properties props = new Properties();
107: loadPropertiesFromXMLFile(file, props);
108: return props;
109: }
110:
111: public static Properties loadPropertiesFromXMLFile(FileResource file)
112: throws SAXException, IOException {
113: Properties props = new Properties();
114: loadPropertiesFromXMLFile(file, props);
115: return props;
116: }
117:
118: public static void loadPropertiesFromXMLFile(FileResource file,
119: Properties props) throws SAXException, IOException {
120: loadPropertiesFromXMLStream(file.getInputStream(), props);
121: }
122:
123: public static void loadPropertiesFromXMLFile(File file,
124: Properties props) throws SAXException, IOException {
125: loadPropertiesFromXMLStream(new FileInputStream(file), props);
126: }
127:
128: public static void loadPropertiesFromXMLStream(InputStream input,
129: Properties props) throws SAXException, IOException {
130: Digester digester = new Digester();
131:
132: WithDefaultsRulesWrapper rules = new WithDefaultsRulesWrapper(
133: new RulesBase());
134: rules.addDefault(new DefaultMatchRule());
135: digester.setRules(rules);
136: digester.setRuleNamespaceURI(PROPS_NS);
137:
138: Rule propertyRule = new PropertyRule(props);
139: Rule dummyRule = new Rule() {
140: };
141:
142: digester.addRule("standardprops", dummyRule);
143: digester.addRule("standardprops/properties", dummyRule);
144: digester.addRule("standardprops/properties/prop", propertyRule);
145:
146: CustomizationHandler cushandler = new CustomizationHandler(
147: digester, PROPS_NS, CUS_NS,
148: new String[] { "/standardprops/properties" });
149: SAXParser parser;
150: try {
151: SAXParserFactory spfac = SAXParserFactory.newInstance();
152: spfac.setNamespaceAware(true);
153: parser = spfac.newSAXParser();
154: parser.parse(input, cushandler);
155: } catch (ParserConfigurationException e) {
156: throw new RuntimeException(
157: "Could not initialize SAXParser!");
158: }
159: }
160:
161: protected static String unesacpePropertyValue(String value) {
162: StringBuffer newValue = new StringBuffer(value.length());
163: char aChar;
164: int off = 0;
165: int end = value.length();
166:
167: while (off < end) {
168: aChar = value.charAt(off++);
169: if (aChar == '\\') {
170: aChar = value.charAt(off++);
171: if (aChar == 'u') {
172: // Read the xxxx
173: int val = 0;
174: for (int i = 0; i < 4; i++) {
175: try {
176: aChar = value.charAt(off++);
177: } catch (StringIndexOutOfBoundsException e) {
178: throw new IllegalArgumentException(
179: "Malformed \\uxxxx encoding.");
180: }
181: switch (aChar) {
182: case '0':
183: case '1':
184: case '2':
185: case '3':
186: case '4':
187: case '5':
188: case '6':
189: case '7':
190: case '8':
191: case '9':
192: val = (val << 4) + aChar - '0';
193: break;
194: case 'a':
195: case 'b':
196: case 'c':
197: case 'd':
198: case 'e':
199: case 'f':
200: val = (val << 4) + 10 + aChar - 'a';
201: break;
202: case 'A':
203: case 'B':
204: case 'C':
205: case 'D':
206: case 'E':
207: case 'F':
208: val = (val << 4) + 10 + aChar - 'A';
209: break;
210: default:
211: throw new IllegalArgumentException(
212: "Malformed \\uxxxx encoding.");
213: }
214: }
215: newValue.append((char) val);
216: } else {
217: if (aChar == 't')
218: aChar = '\t';
219: else if (aChar == 'r')
220: aChar = '\r';
221: else if (aChar == 'n')
222: aChar = '\n';
223: else if (aChar == 'f')
224: aChar = '\f';
225: newValue.append(aChar);
226: }
227: } else {
228: newValue.append(aChar);
229: }
230: }
231:
232: return newValue.toString();
233: }
234: }
|