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 import java.io.File; 019 import java.io.FileInputStream; 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.util.ArrayList; 023 import java.util.List; 024 import java.util.Properties; 025 import java.util.Set; 026 027 import org.apache.commons.io.IOUtils; 028 import org.apache.commons.lang.StringUtils; 029 import org.apache.maven.plugin.AbstractMojo; 030 import org.apache.maven.plugin.MojoExecutionException; 031 import org.apache.maven.project.MavenProject; 032 import org.kuali.maven.common.PropertiesUtils; 033 import org.springframework.core.io.DefaultResourceLoader; 034 import org.springframework.core.io.Resource; 035 import org.springframework.core.io.ResourceLoader; 036 037 /** 038 * The read-project-properties goal reads property files and stores the properties as project properties. It serves as 039 * an alternate to specifying properties in pom.xml.<br> 040 * 041 * Properties files handled by this plugin, have their property values resolved using Spring's expression parser. This 042 * means anything you can do with Spring property values you can do with property values handled by this plugin. For 043 * example, nested properties are supported: eg foo=${a.${b}.c} 044 * 045 * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a> 046 * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a> 047 * @auther Jeff Caddel 048 * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $ 049 * @goal read-project-properties 050 */ 051 public class ReadPropertiesMojo extends AbstractMojo { 052 PropertiesUtils utils = new PropertiesUtils(); 053 054 /** 055 * @parameter default-value="${project}" 056 * @required 057 * @readonly 058 */ 059 private MavenProject project; 060 061 /** 062 * Locations where properties files can be found. Any url Spring resource loading can understand is valid. eg 063 * <code>classpath:myprops.properties</code>. Both, .properties and .xml style properties are supported. 064 * 065 * @parameter 066 * @required 067 */ 068 private String[] locations; 069 070 /** 071 * If true, the plugin will silently ignore any non-existent properties files, and the build will continue 072 * 073 * @parameter expression="${properties.quiet}" default-value="false" 074 */ 075 private boolean quiet; 076 077 /** 078 * If true, the plugin will operate silently without emitting any log messages 079 * 080 * @parameter expression="${properties.silent}" default-value="false" 081 */ 082 private boolean silent; 083 084 /** 085 * If true, the plugin will emit more verbose logging messages. 086 * 087 * @parameter expression="${properties.verbose}" default-value="false" 088 */ 089 private boolean verbose; 090 091 /** 092 * Comma separated list of property values to ignore 093 * 094 * @parameter expression="${properties.ignore}" 095 */ 096 private String ignore; 097 098 @Override 099 public void execute() throws MojoExecutionException { 100 // Figure out if there are properties we need to ignore 101 List<String> ignoreList = getIgnoreList(); 102 103 // Update project properties by loading in properties from the locations they've specified 104 updateProjectProperties(ignoreList); 105 106 // Project + system + env properties 107 Properties allProperties = utils.getMavenProperties(project); 108 resolveValues(project.getProperties(), allProperties); 109 110 } 111 112 protected void resolveValues(Properties p1, Properties p2) { 113 for (String name : p1.stringPropertyNames()) { 114 String originalValue = p1.getProperty(name); 115 String resolvedValue = utils.getResolvedValue(originalValue, p2); 116 p1.setProperty(name, resolvedValue); 117 } 118 } 119 120 /** 121 * Copy properties from p2 into p1, overwriting p1 values as we go. 122 * 123 * Ignore any properties with a key that appears in the ignore list 124 * 125 * @param p1 126 * @param p2 127 * @param ignore 128 */ 129 protected void updateProperties(Properties p1, Properties p2, List<String> ignore) { 130 Set<String> names = p2.stringPropertyNames(); 131 for (String name : names) { 132 if (!ignore.contains(name)) { 133 String value = p2.getProperty(name); 134 p1.setProperty(name, value); 135 } 136 } 137 } 138 139 protected static final List<String> getListFromCSV(String csv) { 140 if (StringUtils.isBlank(csv)) { 141 return new ArrayList<String>(); 142 } 143 List<String> list = new ArrayList<String>(); 144 String[] tokens = StringUtils.split(csv, ","); 145 for (String token : tokens) { 146 list.add(token.trim()); 147 } 148 return list; 149 } 150 151 protected String toEmpty(String s) { 152 if (StringUtils.isBlank(s)) { 153 return ""; 154 } else { 155 return s; 156 } 157 } 158 159 protected boolean exists(String location) { 160 if (StringUtils.isBlank(location)) { 161 return false; 162 } 163 File file = new File(location); 164 if (file.exists()) { 165 return true; 166 } 167 ResourceLoader loader = new DefaultResourceLoader(); 168 Resource resource = loader.getResource(location); 169 return resource.exists(); 170 } 171 172 protected boolean validate(String location) throws MojoExecutionException { 173 boolean exists = exists(location); 174 if (exists) { 175 return true; 176 } 177 if (quiet) { 178 if (verbose && !silent) { 179 getLog().info("Ignoring non-existent properties file '" + toEmpty(location) + "'"); 180 } 181 return false; 182 } else { 183 throw new MojoExecutionException("Non-existent properties file '" + location + "'"); 184 } 185 } 186 187 protected InputStream getInputStream(String location) throws IOException { 188 File file = new File(location); 189 if (file.exists()) { 190 return new FileInputStream(location); 191 } 192 ResourceLoader loader = new DefaultResourceLoader(); 193 Resource resource = loader.getResource(location); 194 return resource.getInputStream(); 195 } 196 197 protected Properties getProperties(String location) throws MojoExecutionException { 198 InputStream in = null; 199 try { 200 Properties properties = new Properties(); 201 in = getInputStream(location); 202 if (location.toLowerCase().endsWith(".xml")) { 203 properties.loadFromXML(in); 204 } else { 205 properties.load(in); 206 } 207 return properties; 208 } catch (IOException e) { 209 throw new MojoExecutionException("Error reading properties file " + location, e); 210 } finally { 211 IOUtils.closeQuietly(in); 212 } 213 } 214 215 public boolean isQuiet() { 216 return quiet; 217 } 218 219 public void setQuiet(boolean quiet) { 220 this.quiet = quiet; 221 } 222 223 public String getIgnore() { 224 return ignore; 225 } 226 227 public void setIgnore(String ignoreProperties) { 228 this.ignore = ignoreProperties; 229 } 230 231 public MavenProject getProject() { 232 return project; 233 } 234 235 public String[] getLocations() { 236 return locations; 237 } 238 239 public void setLocations(String[] locations) { 240 this.locations = locations; 241 } 242 243 public boolean isVerbose() { 244 return verbose; 245 } 246 247 public void setVerbose(boolean verbose) { 248 this.verbose = verbose; 249 } 250 251 public boolean isSilent() { 252 return silent; 253 } 254 255 public void setSilent(boolean silent) { 256 this.silent = silent; 257 } 258 259 protected List<String> getIgnoreList() { 260 List<String> ignoreList = getListFromCSV(ignore); 261 if (!silent && verbose && !StringUtils.isBlank(ignore)) { 262 getLog().info("Ignoring " + ignore); 263 } 264 return ignoreList; 265 } 266 267 protected void updateProjectProperties(List<String> ignoreList) throws MojoExecutionException { 268 Properties projectProperties = project.getProperties(); 269 for (int i = 0; i < locations.length; i++) { 270 Properties allProperties = utils.getMavenProperties(project); 271 String originalLocation = locations[i]; 272 String resolvedLocation = utils.getResolvedValue(originalLocation, allProperties); 273 getLog().debug("o=" + originalLocation + " r=" + resolvedLocation); 274 if (!validate(resolvedLocation)) { 275 continue; 276 } 277 if (!silent) { 278 getLog().info("Loading " + resolvedLocation); 279 } 280 281 // Load properties from this location 282 Properties p = getProperties(resolvedLocation); 283 284 // Update project properties from the properties we just loaded 285 updateProperties(projectProperties, p, ignoreList); 286 } 287 } 288 289 }