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 /*
19 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
20 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
21 * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
22 * License. You may obtain a copy of the License at
23 *
24 * http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
27 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
28 * specific language governing permissions and limitations under the License.
29 */
30
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Properties;
38 import java.util.Set;
39
40 import org.apache.commons.io.IOUtils;
41 import org.apache.maven.plugin.AbstractMojo;
42 import org.apache.maven.plugin.MojoExecutionException;
43 import org.apache.maven.project.MavenProject;
44 import org.codehaus.plexus.util.StringUtils;
45 import org.codehaus.plexus.util.cli.CommandLineUtils;
46
47 /**
48 * The read-project-properties goal reads property files and stores the properties as project properties. It serves as
49 * an alternate to specifying properties in pom.xml.
50 *
51 * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a>
52 * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a>
53 * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $
54 * @goal read-project-properties
55 */
56 public class ReadPropertiesMojo extends AbstractMojo {
57
58 /**
59 * @parameter default-value="${project}"
60 * @required
61 * @readonly
62 */
63 private MavenProject project;
64
65 /**
66 * The properties files that will be used when reading properties. Can use both .properties and .xml files
67 *
68 * @parameter
69 * @required
70 */
71 private File[] files;
72
73 /**
74 * If true, the plugin will silently ignore any non-existent properties files, and the build will continue
75 *
76 * @parameter expression="${properties.quiet}" default-value="false"
77 */
78 private boolean quiet;
79
80 /**
81 * Comma separated list of property values to ignore
82 *
83 * @parameter expression="${properties.ignore}"
84 */
85 private String ignore;
86
87 @Override
88 public void execute() throws MojoExecutionException {
89 List<String> ignoreList = getListFromCSV(ignore);
90 Properties projectProperties = project.getProperties();
91 for (int i = 0; i < files.length; i++) {
92 File file = files[i];
93 if (validate(file)) {
94 getLog().info("Loading " + file);
95 if (!StringUtils.isBlank(ignore)) {
96 getLog().info("Ignoring " + ignore);
97 }
98 Properties p = getProperties(file);
99 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 }