View Javadoc
1 /* 2 * Copyright (C) The Spice Group. All rights reserved. 3 * 4 * This software is published under the terms of the Spice 5 * Software License version 1.1, a copy of which has been included 6 * with this distribution in the LICENSE.txt file. 7 */ 8 package org.codehaus.spice.configkit; 9 10 import java.util.Iterator; 11 import java.util.Map; 12 import java.util.Properties; 13 import org.w3c.dom.Attr; 14 import org.w3c.dom.Element; 15 import org.w3c.dom.NamedNodeMap; 16 import org.w3c.dom.Node; 17 import org.w3c.dom.NodeList; 18 import org.w3c.dom.Text; 19 20 /*** 21 * This is a utility class designed for expanding propertys in configuration 22 * files. Propertys are stored in Map objects and any section that begins with 23 * "${" and ends with "}" will have inner name replaced with property value from 24 * map. 25 * 26 * @author Peter Donald 27 * @version $Revision: 1.1 $ $Date: 2003/12/03 03:19:28 $ 28 */ 29 public final class PropertyExpander 30 { 31 /*** 32 * Flag indicating that undefined propertys should be not be replaced. ie 33 * "${myUnresolvedProperty}" 34 */ 35 public static final int LEAVE_UNDEFINED = 1; 36 37 /*** 38 * Flag indicating that undefined propertys should cause an exception to be 39 * thrown. 40 */ 41 public static final int EXCEPT_ON_UNDEFINED = 2; 42 43 /*** 44 * Flag indicating that undefined propertys should be replaced with a empty 45 * string "". 46 */ 47 public static final int EMPTY_ON_UNDEFINED = 3; 48 49 /*** 50 * The flag for behaviour when undefined property is encountered. Must be 51 * one of the *_UNDEFINED propertys. 52 */ 53 private final int m_onUndefined; 54 55 /*** 56 * Create property expander with EXCEPT_ON_UNDEFINED policy for undefined 57 * propertys. 58 */ 59 public PropertyExpander() 60 { 61 this( EXCEPT_ON_UNDEFINED ); 62 } 63 64 /*** 65 * Create property expander with specified policy for undefined propertys. 66 * 67 * @param onUndefined the flag indicating behaviour when undefined property 68 * is encountered. Must be one of the *_UNDEFINED constants. 69 */ 70 public PropertyExpander( final int onUndefined ) 71 { 72 m_onUndefined = onUndefined; 73 } 74 75 /*** 76 * Expand all propertys in the input Properties object. 77 * 78 * @param input the Properties object to resolve 79 * @param data the data that holds property values 80 * @throws Exception if an error occurs 81 */ 82 public Properties expandValues( final Properties input, final Map data ) 83 throws Exception 84 { 85 final Properties result = new Properties(); 86 final Iterator iterator = input.keySet().iterator(); 87 while( iterator.hasNext() ) 88 { 89 final String key = (String)iterator.next(); 90 final String value = input.getProperty( key ); 91 final String newKey = expandValues( key, data ); 92 final String newValue = expandValues( value, data ); 93 result.setProperty( newKey, newValue ); 94 } 95 return result; 96 } 97 98 /*** 99 * Expand all propertys in the input XML attributes and text contents. 100 * 101 * @param input the DOM element to resolve 102 * @param data the data that holds property values 103 * @throws Exception if an error occurs 104 */ 105 public void expandValues( final Element input, final Map data ) 106 throws Exception 107 { 108 final NamedNodeMap attributes = input.getAttributes(); 109 final int attributeCount = attributes.getLength(); 110 for( int i = 0; i < attributeCount; i++ ) 111 { 112 final Attr attr = (Attr)attributes.item( i ); 113 final String value = attr.getValue(); 114 final String newValue = expandValues( value, data ); 115 attr.setValue( newValue ); 116 } 117 final NodeList nodes = input.getChildNodes(); 118 final int childCount = nodes.getLength(); 119 for( int i = 0; i < childCount; i++ ) 120 { 121 final Node node = nodes.item( i ); 122 if( node instanceof Element ) 123 { 124 expandValues( (Element)node, data ); 125 } 126 else if( node instanceof Text ) 127 { 128 final Text text = (Text)node; 129 final String content = text.getData(); 130 final String newContent = expandValues( content, data ); 131 text.setData( newContent ); 132 } 133 } 134 } 135 136 /*** 137 * Expand all propertys in input string. 138 * 139 * @param input the string to resolve 140 * @param data the data that holds property values 141 * @return the resolved string 142 * @throws Exception if an error occurs 143 */ 144 public String expandValues( final String input, final Map data ) 145 throws Exception 146 { 147 int start = findBeginning( input, 0 ); 148 if( -1 == start ) 149 { 150 return input; 151 } 152 153 int end = findEnding( input, start ); 154 155 final int length = input.length(); 156 if( 0 == start && end == ( length - 1 ) ) 157 { 158 return getValue( input.substring( start + 2, end ), 159 data ); 160 } 161 162 final StringBuffer sb = new StringBuffer( length * 2 ); 163 int lastPlace = 0; 164 165 while( true ) 166 { 167 final String value = 168 getValue( input.substring( start + 2, end ), data ); 169 170 sb.append( input.substring( lastPlace, start ) ); 171 sb.append( value ); 172 173 lastPlace = end + 1; 174 175 start = findBeginning( input, lastPlace ); 176 if( -1 == start ) 177 { 178 break; 179 } 180 181 end = findEnding( input, start ); 182 } 183 184 sb.append( input.substring( lastPlace, length ) ); 185 186 return sb.toString(); 187 } 188 189 /*** 190 * Helper method to find the start of a input definition. 191 * 192 * @param input the input string 193 * @param index the current index into input 194 * @return the index of start of property definition 195 */ 196 private int findBeginning( final String input, final int index ) 197 { 198 return input.indexOf( "${", index ); 199 } 200 201 /*** 202 * Helper method to find the end of a property definition. 203 * 204 * @param input the input string 205 * @param index the current index into input 206 * @return the index of end of property definition 207 * @throws Exception if unable to locate end of property 208 */ 209 private int findEnding( final String input, final int index ) 210 throws Exception 211 { 212 final int end = input.indexOf( '}', index ); 213 if( -1 == end ) 214 { 215 final String message = "Malformed input with mismatched }'s"; 216 throw new Exception( message ); 217 } 218 219 return end; 220 } 221 222 /*** 223 * Return value from data map. If null is retrieved from data map then 224 * behave as defined by {@link #m_onUndefined} flag. 225 * 226 * @param key the key of value in data 227 * @param data the data map 228 * @return the stringized value of value in map 229 * @throws Exception if an error occurs 230 */ 231 private String getValue( final String key, final Map data ) 232 throws Exception 233 { 234 final Object value = data.get( key ); 235 if( null == value ) 236 { 237 if( LEAVE_UNDEFINED == m_onUndefined ) 238 { 239 return "${" + key + "}"; 240 } 241 else if( EMPTY_ON_UNDEFINED == m_onUndefined ) 242 { 243 return ""; 244 } 245 else// if( EXCEPT_ON_UNDEFINED == m_onUndefined ) 246 { 247 final String message = "Unable to find " + 248 key + 249 " to expand during property resolution."; 250 throw new Exception( message ); 251 } 252 } 253 254 return String.valueOf( value ); 255 } 256 }

This page was automatically generated by Maven