1 package org.apache.maven.plugin.resources; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import org.codehaus.plexus.util.IOUtil; 23 24 import java.io.File; 25 import java.io.FileInputStream; 26 import java.io.FileNotFoundException; 27 import java.io.IOException; 28 import java.util.Properties; 29 30 /** 31 * @deprecated use classes in the component maven-filtering 32 * TODO remove the class ? 33 * @author <a href="mailto:kenney@neonics.com">Kenney Westerhof</a> 34 * @author William Ferguson 35 * 36 */ 37 public final class PropertyUtils 38 { 39 private PropertyUtils() 40 { 41 // prevent instantiation 42 } 43 44 /** 45 * Reads a property file, resolving all internal variables, using the supplied base properties. 46 * <p> 47 * The properties are resolved iteratively, so if the value of property A refers to property B, then after 48 * resolution the value of property B will contain the value of property B. 49 * </p> 50 * 51 * @param propFile The property file to load. 52 * @param baseProps Properties containing the initial values to subsitute into the properties file. 53 * @return Properties object containing the properties in the file with their values fully resolved. 54 * @throws IOException if profile does not exist, or cannot be read. 55 */ 56 public static Properties loadPropertyFile( File propFile, Properties baseProps ) 57 throws IOException 58 { 59 if ( !propFile.exists() ) 60 { 61 throw new FileNotFoundException( propFile.toString() ); 62 } 63 64 final Properties fileProps = new Properties(); 65 final FileInputStream inStream = new FileInputStream( propFile ); 66 try 67 { 68 fileProps.load( inStream ); 69 } 70 finally 71 { 72 IOUtil.close( inStream ); 73 } 74 75 final Properties combinedProps = new Properties(); 76 combinedProps.putAll( baseProps ); 77 combinedProps.putAll( fileProps ); 78 79 // The algorithm iterates only over the fileProps which is all that is required to resolve 80 // the properties defined within the file. This is slighlty different to current, however 81 // I suspect that this was the actual original intent. 82 // 83 // The difference is that #loadPropertyFile(File, boolean, boolean) also resolves System properties 84 // whose values contain expressions. I believe this is unexpected and is not validated by the test cases, 85 // as can be verified by replacing the implementation of #loadPropertyFile(File, boolean, boolean) 86 // with the commented variant I have provided that reuses this method. 87 88 for (Object o : fileProps.keySet()) { 89 final String k = (String) o; 90 final String propValue = getPropertyValue(k, combinedProps); 91 fileProps.setProperty(k, propValue); 92 } 93 94 return fileProps; 95 } 96 97 /** 98 * Reads a property file, resolving all internal variables. 99 * 100 * @param propfile The property file to load 101 * @param fail wheter to throw an exception when the file cannot be loaded or to return null 102 * @param useSystemProps wheter to incorporate System.getProperties settings into the returned Properties object. 103 * @return the loaded and fully resolved Properties object 104 */ 105 public static Properties loadPropertyFile( File propfile, boolean fail, boolean useSystemProps ) 106 throws IOException 107 { 108 109 final Properties baseProps = new Properties(); 110 111 if ( useSystemProps ) 112 { 113 baseProps.putAll( System.getProperties() ); 114 } 115 116 final Properties resolvedProps = new Properties(); 117 try 118 { 119 resolvedProps.putAll( loadPropertyFile( propfile, baseProps ) ); 120 } 121 catch ( FileNotFoundException e ) 122 { 123 if ( fail ) 124 { 125 throw new FileNotFoundException( propfile.toString() ); 126 } 127 } 128 129 if ( useSystemProps ) 130 { 131 resolvedProps.putAll( baseProps ); 132 } 133 134 return resolvedProps; 135 } 136 137 /** 138 * Retrieves a property value, replacing values like ${token} 139 * using the Properties to look them up. 140 * 141 * It will leave unresolved properties alone, trying for System 142 * properties, and implements reparsing (in the case that 143 * the value of a property contains a key), and will 144 * not loop endlessly on a pair like 145 * test = ${test}. 146 */ 147 private static String getPropertyValue( String k, Properties p ) 148 { 149 // This can also be done using InterpolationFilterReader, 150 // but it requires reparsing the file over and over until 151 // it doesn't change. 152 153 String v = p.getProperty( k ); 154 String ret = ""; 155 int idx, idx2; 156 157 while ( ( idx = v.indexOf( "${" ) ) >= 0 ) 158 { 159 // append prefix to result 160 ret += v.substring( 0, idx ); 161 162 // strip prefix from original 163 v = v.substring( idx + 2 ); 164 165 // if no matching } then bail 166 idx2 = v.indexOf( '}' ); 167 if ( idx2 < 0 ) 168 { 169 break; 170 } 171 172 // strip out the key and resolve it 173 // resolve the key/value for the ${statement} 174 String nk = v.substring( 0, idx2 ); 175 v = v.substring( idx2 + 1 ); 176 String nv = p.getProperty( nk ); 177 178 // try global environment.. 179 if ( nv == null ) 180 { 181 nv = System.getProperty( nk ); 182 } 183 184 // if the key cannot be resolved, 185 // leave it alone ( and don't parse again ) 186 // else prefix the original string with the 187 // resolved property ( so it can be parsed further ) 188 // taking recursion into account. 189 if ( nv == null || nv.equals( k ) ) 190 { 191 ret += "${" + nk + "}"; 192 } 193 else 194 { 195 v = nv + v; 196 } 197 } 198 return ret + v; 199 } 200 }