001 /** 002 * Copyright 2009-2012 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.codehaus.mojo.properties; 017 018 /* 019 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE 020 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file 021 * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the 022 * License. You may obtain a copy of the License at 023 * 024 * http://www.apache.org/licenses/LICENSE-2.0 025 * 026 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 027 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 028 * specific language governing permissions and limitations under the License. 029 */ 030 031 import java.io.File; 032 import java.io.FileInputStream; 033 import java.io.IOException; 034 import java.io.InputStream; 035 import java.util.ArrayList; 036 import java.util.List; 037 import java.util.Properties; 038 import java.util.Set; 039 040 import org.apache.commons.io.IOUtils; 041 import org.apache.maven.plugin.AbstractMojo; 042 import org.apache.maven.plugin.MojoExecutionException; 043 import org.apache.maven.project.MavenProject; 044 import org.codehaus.plexus.util.StringUtils; 045 import org.codehaus.plexus.util.cli.CommandLineUtils; 046 047 /** 048 * The read-project-properties goal reads property files and stores the properties as project properties. It serves as 049 * an alternate to specifying properties in pom.xml. 050 * 051 * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a> 052 * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a> 053 * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $ 054 * @goal read-project-properties 055 */ 056 public class ReadPropertiesMojo extends AbstractMojo { 057 058 /** 059 * @parameter default-value="${project}" 060 * @required 061 * @readonly 062 */ 063 private MavenProject project; 064 065 /** 066 * The properties files that will be used when reading properties. Can use both .properties and .xml files 067 * 068 * @parameter 069 * @required 070 */ 071 private File[] files; 072 073 /** 074 * If true, the plugin will silently ignore any non-existent properties files, and the build will continue 075 * 076 * @parameter expression="${properties.quiet}" default-value="false" 077 */ 078 private boolean quiet; 079 080 /** 081 * Comma separated list of property values to ignore 082 * 083 * @parameter expression="${properties.ignore}" 084 */ 085 private String ignore; 086 087 @Override 088 public void execute() throws MojoExecutionException { 089 List<String> ignoreList = getListFromCSV(ignore); 090 Properties projectProperties = project.getProperties(); 091 for (int i = 0; i < files.length; i++) { 092 File file = files[i]; 093 if (validate(file)) { 094 getLog().info("Loading " + file); 095 if (!StringUtils.isBlank(ignore)) { 096 getLog().info("Ignoring " + ignore); 097 } 098 Properties p = getProperties(file); 099 updateProperties(projectProperties, p, ignoreList); 100 } 101 } 102 103 Properties env = getEnvironment(); 104 for (String name : projectProperties.stringPropertyNames()) { 105 String value = getPropertyValue(name, projectProperties, env); 106 projectProperties.setProperty(name, value); 107 } 108 } 109 110 protected Properties getEnvironment() throws MojoExecutionException { 111 try { 112 return CommandLineUtils.getSystemEnvVars(); 113 } catch (IOException e) { 114 throw new MojoExecutionException("Error get environment variables", e); 115 } 116 } 117 118 protected void updateProperties(Properties p1, Properties p2, List<String> ignore) { 119 Set<String> names = p2.stringPropertyNames(); 120 for (String name : names) { 121 if (!ignore.contains(name)) { 122 String value = p2.getProperty(name); 123 p1.setProperty(name, value); 124 } 125 } 126 } 127 128 protected static final List<String> getListFromCSV(String csv) { 129 if (StringUtils.isBlank(csv)) { 130 return new ArrayList<String>(); 131 } 132 List<String> list = new ArrayList<String>(); 133 String[] tokens = StringUtils.split(csv, ","); 134 for (String token : tokens) { 135 list.add(token.trim()); 136 } 137 return list; 138 } 139 140 /** 141 * Retrieves a property value, replacing values like ${token} using the Properties to look them up. Shamelessly 142 * adapted from: 143 * http://maven.apache.org/plugins/maven-war-plugin/xref/org/apache/maven/plugin/war/PropertyUtils.html 144 * 145 * It will leave unresolved properties alone, trying for System properties, and environment variables and implements 146 * reparsing (in the case that the value of a property contains a key), and will not loop endlessly on a pair like 147 * test = ${test} 148 * 149 * @param k 150 * property key 151 * @param p 152 * project properties 153 * @param environment 154 * environment variables 155 * @return resolved property value 156 */ 157 protected String getPropertyValue(String k, Properties p, Properties environment) { 158 String v = p.getProperty(k); 159 String ret = ""; 160 int idx, idx2; 161 162 while ((idx = v.indexOf("${")) >= 0) { 163 // append prefix to result 164 ret += v.substring(0, idx); 165 166 // strip prefix from original 167 v = v.substring(idx + 2); 168 169 idx2 = v.indexOf("}"); 170 171 // if no matching } then bail 172 if (idx2 < 0) { 173 break; 174 } 175 176 // strip out the key and resolve it 177 // resolve the key/value for the ${statement} 178 String nk = v.substring(0, idx2); 179 v = v.substring(idx2 + 1); 180 String nv = p.getProperty(nk); 181 182 // try global environment 183 if (nv == null) { 184 nv = System.getProperty(nk); 185 } 186 187 // try environment variable 188 if (nv == null && nk.startsWith("env.") && environment != null) { 189 nv = environment.getProperty(nk.substring(4)); 190 } 191 192 // if the key cannot be resolved, 193 // leave it alone ( and don't parse again ) 194 // else prefix the original string with the 195 // resolved property ( so it can be parsed further ) 196 // taking recursion into account. 197 if (nv == null || nv.equals(nk)) { 198 ret += "${" + nk + "}"; 199 } else { 200 v = nv + v; 201 } 202 } 203 return ret + v; 204 } 205 206 protected boolean validate(File file) throws MojoExecutionException { 207 boolean exists = file != null && file.exists(); 208 if (exists) { 209 return true; 210 } 211 if (quiet) { 212 getLog().info("Ignoring non-existent properties file '" + file + "'"); 213 return false; 214 } else { 215 throw new MojoExecutionException("Non-existent properties file '" + file + "'"); 216 } 217 } 218 219 protected Properties getProperties(File file) throws MojoExecutionException { 220 InputStream in = null; 221 try { 222 Properties properties = new Properties(); 223 in = new FileInputStream(file); 224 String filename = file.getName().toLowerCase(); 225 if (filename.endsWith(".xml")) { 226 properties.loadFromXML(in); 227 } else { 228 properties.load(in); 229 } 230 return properties; 231 } catch (IOException e) { 232 throw new MojoExecutionException("Error reading properties file " + file.getAbsolutePath(), e); 233 } finally { 234 IOUtils.closeQuietly(in); 235 } 236 } 237 238 public File[] getFiles() { 239 return files; 240 } 241 242 public void setFiles(File[] files) { 243 this.files = files; 244 } 245 246 public boolean isQuiet() { 247 return quiet; 248 } 249 250 public void setQuiet(boolean quiet) { 251 this.quiet = quiet; 252 } 253 254 public String getIgnore() { 255 return ignore; 256 } 257 258 public void setIgnore(String ignoreProperties) { 259 this.ignore = ignoreProperties; 260 } 261 262 public MavenProject getProject() { 263 return project; 264 } 265 266 }