001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2012 Paul Ferraro 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Lesser General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package net.sf.hajdbc.xml; 019 020import java.util.Properties; 021import java.util.regex.Matcher; 022import java.util.regex.Pattern; 023 024import net.sf.hajdbc.util.Strings; 025import net.sf.hajdbc.util.SystemProperties; 026 027import org.xml.sax.Attributes; 028import org.xml.sax.SAXException; 029import org.xml.sax.XMLReader; 030import org.xml.sax.helpers.AttributesImpl; 031import org.xml.sax.helpers.XMLFilterImpl; 032 033/** 034 * @author Paul Ferraro 035 */ 036public class PropertyReplacementFilter extends XMLFilterImpl 037{ 038 private static final Pattern PATTERN = Pattern.compile("\\$\\{([^\\}]+)\\}"); 039 private final Properties properties; 040 041 public PropertyReplacementFilter() 042 { 043 super(); 044 this.properties = SystemProperties.getSystemProperties(); 045 } 046 047 public PropertyReplacementFilter(XMLReader parent) 048 { 049 this(parent, SystemProperties.getSystemProperties()); 050 } 051 052 public PropertyReplacementFilter(XMLReader parent, Properties properties) 053 { 054 super(parent); 055 this.properties = properties; 056 } 057 058 /** 059 * {@inheritDoc} 060 * @see org.xml.sax.helpers.XMLFilterImpl#characters(char[], int, int) 061 */ 062 @Override 063 public void characters(char[] data, int start, int length) throws SAXException 064 { 065 char[] value = this.replace(String.copyValueOf(data, start, length)).toCharArray(); 066 super.characters(value, 0, value.length); 067 } 068 069 /** 070 * {@inheritDoc} 071 * @see org.xml.sax.helpers.XMLFilterImpl#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) 072 */ 073 @Override 074 public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException 075 { 076 AttributesImpl attributes = (attrs instanceof AttributesImpl) ? (AttributesImpl) attrs : new AttributesImpl(attrs); 077 078 int length = attributes.getLength(); 079 for (int i = 0; i < length; ++i) 080 { 081 attributes.setValue(i, this.replace(attributes.getValue(i))); 082 } 083 084 super.startElement(uri, localName, qName, attributes); 085 } 086 087 private String replace(String input) 088 { 089 StringBuilder builder = new StringBuilder(); 090 Matcher matcher = PATTERN.matcher(input); 091 092 int tail = 0; 093 094 while (matcher.find()) 095 { 096 builder.append(input, tail, matcher.start()); 097 098 String group = matcher.group(1); 099 100 if (group.equals("/")) 101 { 102 builder.append(Strings.FILE_SEPARATOR); 103 } 104 else if (group.equals(":")) 105 { 106 builder.append(Strings.PATH_SEPARATOR); 107 } 108 else 109 { 110 String key = group; 111 String defaultValue = null; 112 113 int index = group.indexOf(":"); 114 115 if (index > 0) 116 { 117 key = group.substring(0, index); 118 defaultValue = group.substring(index + 1); 119 } 120 121 String value = this.getProperty(key.split(","), defaultValue); 122 123 builder.append((value != null) ? value : matcher.group()); 124 } 125 126 tail = matcher.end(); 127 } 128 129 builder.append(input, tail, input.length()); 130 131 return builder.toString(); 132 } 133 134 private String getProperty(String[] keys, String defaultValue) 135 { 136 for (String key: keys) 137 { 138 String value = this.properties.getProperty(key.trim()); 139 140 if (value != null) return value; 141 } 142 143 return defaultValue; 144 } 145}