001 /** 002 * Copyright 2009-2013 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.List; 023 import java.util.Properties; 024 import java.util.Set; 025 026 import org.apache.commons.io.IOUtils; 027 import org.apache.commons.lang.StringUtils; 028 import org.apache.maven.plugin.AbstractMojo; 029 import org.apache.maven.plugin.MojoExecutionException; 030 import org.apache.maven.project.MavenProject; 031 import org.kuali.common.util.CollectionUtils; 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 an alternate to 039 * 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 means anything you 042 * can do with Spring property values you can do with property values handled by this plugin. For example, nested properties are supported: 043 * 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 String toEmpty(String s) { 140 if (StringUtils.isBlank(s)) { 141 return ""; 142 } else { 143 return s; 144 } 145 } 146 147 protected boolean exists(String location) { 148 if (StringUtils.isBlank(location)) { 149 return false; 150 } 151 File file = new File(location); 152 if (file.exists()) { 153 return true; 154 } 155 ResourceLoader loader = new DefaultResourceLoader(); 156 Resource resource = loader.getResource(location); 157 return resource.exists(); 158 } 159 160 protected boolean validate(String location) throws MojoExecutionException { 161 boolean exists = exists(location); 162 if (exists) { 163 return true; 164 } 165 if (quiet) { 166 if (verbose && !silent) { 167 getLog().info("Ignoring non-existent properties file '" + toEmpty(location) + "'"); 168 } 169 return false; 170 } else { 171 throw new MojoExecutionException("Non-existent properties file '" + location + "'"); 172 } 173 } 174 175 protected InputStream getInputStream(String location) throws IOException { 176 File file = new File(location); 177 if (file.exists()) { 178 return new FileInputStream(location); 179 } 180 ResourceLoader loader = new DefaultResourceLoader(); 181 Resource resource = loader.getResource(location); 182 return resource.getInputStream(); 183 } 184 185 protected Properties getProperties(String location) throws MojoExecutionException { 186 InputStream in = null; 187 try { 188 Properties properties = new Properties(); 189 in = getInputStream(location); 190 if (location.toLowerCase().endsWith(".xml")) { 191 properties.loadFromXML(in); 192 } else { 193 properties.load(in); 194 } 195 return properties; 196 } catch (IOException e) { 197 throw new MojoExecutionException("Error reading properties file " + location, e); 198 } finally { 199 IOUtils.closeQuietly(in); 200 } 201 } 202 203 public boolean isQuiet() { 204 return quiet; 205 } 206 207 public void setQuiet(boolean quiet) { 208 this.quiet = quiet; 209 } 210 211 public String getIgnore() { 212 return ignore; 213 } 214 215 public void setIgnore(String ignoreProperties) { 216 this.ignore = ignoreProperties; 217 } 218 219 public MavenProject getProject() { 220 return project; 221 } 222 223 public String[] getLocations() { 224 return locations; 225 } 226 227 public void setLocations(String[] locations) { 228 this.locations = locations; 229 } 230 231 public boolean isVerbose() { 232 return verbose; 233 } 234 235 public void setVerbose(boolean verbose) { 236 this.verbose = verbose; 237 } 238 239 public boolean isSilent() { 240 return silent; 241 } 242 243 public void setSilent(boolean silent) { 244 this.silent = silent; 245 } 246 247 protected List<String> getIgnoreList() { 248 List<String> ignoreList = CollectionUtils.getTrimmedListFromCSV(ignore); 249 if (!silent && verbose && !StringUtils.isBlank(ignore)) { 250 getLog().info("Ignoring " + ignore); 251 } 252 return ignoreList; 253 } 254 255 protected void updateProjectProperties(List<String> ignoreList) throws MojoExecutionException { 256 Properties projectProperties = project.getProperties(); 257 for (int i = 0; i < locations.length; i++) { 258 Properties allProperties = utils.getMavenProperties(project); 259 String originalLocation = locations[i]; 260 String resolvedLocation = utils.getResolvedValue(originalLocation, allProperties); 261 getLog().debug("o=" + originalLocation + " r=" + resolvedLocation); 262 if (!validate(resolvedLocation)) { 263 continue; 264 } 265 if (!silent) { 266 getLog().info("Loading " + resolvedLocation); 267 } 268 269 // Load properties from this location 270 Properties p = getProperties(resolvedLocation); 271 272 // Update project properties from the properties we just loaded 273 updateProperties(projectProperties, p, ignoreList); 274 } 275 } 276 277 }