View Javadoc

1   /**
2    * Copyright 2009-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.codehaus.mojo.properties;
17  
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.util.List;
23  import java.util.Properties;
24  import java.util.Set;
25  
26  import org.apache.commons.io.IOUtils;
27  import org.apache.commons.lang.StringUtils;
28  import org.apache.maven.plugin.AbstractMojo;
29  import org.apache.maven.plugin.MojoExecutionException;
30  import org.apache.maven.project.MavenProject;
31  import org.kuali.common.util.CollectionUtils;
32  import org.kuali.maven.common.PropertiesUtils;
33  import org.springframework.core.io.DefaultResourceLoader;
34  import org.springframework.core.io.Resource;
35  import org.springframework.core.io.ResourceLoader;
36  
37  /**
38   * The read-project-properties goal reads property files and stores the properties as project properties. It serves as an alternate to
39   * specifying properties in pom.xml.<br>
40   *
41   * Properties files handled by this plugin, have their property values resolved using Spring's expression parser. This means anything you
42   * can do with Spring property values you can do with property values handled by this plugin. For example, nested properties are supported:
43   * eg foo=${a.${b}.c}
44   *
45   * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a>
46   * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a>
47   * @auther Jeff Caddel
48   * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $
49   * @goal read-project-properties
50   */
51  public class ReadPropertiesMojo extends AbstractMojo {
52  	PropertiesUtils utils = new PropertiesUtils();
53  
54  	/**
55  	 * @parameter default-value="${project}"
56  	 * @required
57  	 * @readonly
58  	 */
59  	private MavenProject project;
60  
61  	/**
62  	 * Locations where properties files can be found. Any url Spring resource loading can understand is valid. eg
63  	 * <code>classpath:myprops.properties</code>. Both, .properties and .xml style properties are supported.
64  	 *
65  	 * @parameter
66  	 * @required
67  	 */
68  	private String[] locations;
69  
70  	/**
71  	 * If true, the plugin will silently ignore any non-existent properties files, and the build will continue
72  	 *
73  	 * @parameter expression="${properties.quiet}" default-value="false"
74  	 */
75  	private boolean quiet;
76  
77  	/**
78  	 * If true, the plugin will operate silently without emitting any log messages
79  	 *
80  	 * @parameter expression="${properties.silent}" default-value="false"
81  	 */
82  	private boolean silent;
83  
84  	/**
85  	 * If true, the plugin will emit more verbose logging messages.
86  	 *
87  	 * @parameter expression="${properties.verbose}" default-value="false"
88  	 */
89  	private boolean verbose;
90  
91  	/**
92  	 * Comma separated list of property values to ignore
93  	 *
94  	 * @parameter expression="${properties.ignore}"
95  	 */
96  	private String ignore;
97  
98  	@Override
99  	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 }