1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codehaus.mojo.properties;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.Set;
29
30 import org.apache.commons.io.FileUtils;
31 import org.apache.maven.plugin.MojoExecutionException;
32 import org.apache.maven.plugin.MojoFailureException;
33 import org.codehaus.plexus.util.StringUtils;
34 import org.springframework.util.PropertyPlaceholderHelper;
35
36
37
38
39
40
41
42
43 public class WriteProjectProperties extends AbstractWritePropertiesMojo {
44 private static final String CR = "\r";
45 private static final String LF = "\n";
46 private static final String TAB = "\t";
47 private static final String BACKSLASH = "\\";
48 private static final String[] ANT_ESCAPE_CHARS = { CR, LF, TAB, BACKSLASH, ":", "#", "=" };
49
50
51
52
53
54
55
56 private String escapeChars;
57
58
59
60
61
62
63
64
65
66 private boolean antEchoPropertiesMode;
67
68
69
70
71
72
73
74 private boolean includeSystemProperties;
75
76
77
78
79
80
81
82 private boolean includeEnvironmentVariables;
83
84
85
86
87
88
89 private String exclude;
90
91
92
93
94
95
96
97 private String include;
98
99
100
101
102
103
104 private boolean resolvePlaceholders;
105
106 @Override
107 public void execute() throws MojoExecutionException, MojoFailureException {
108 Properties properties = new Properties();
109
110 properties.putAll(project.getProperties());
111 if (includeEnvironmentVariables) {
112
113 properties.putAll(getEnvironmentVariables());
114 }
115 if (includeSystemProperties) {
116
117 properties.putAll(System.getProperties());
118 }
119
120
121 trim(properties, exclude, include);
122
123 if (resolvePlaceholders) {
124 properties = getResolvedProperties(properties);
125 }
126
127 String comment = "# " + new Date() + "\n";
128 List<String> escapeTokens = getEscapeChars(escapeChars);
129 if (antEchoPropertiesMode) {
130 escapeTokens = Arrays.asList(ANT_ESCAPE_CHARS);
131 comment = getAntHeader();
132 properties.remove("DSTAMP");
133 properties.remove("TODAY");
134 properties.remove("TSTAMP");
135 }
136
137 getLog().info("Creating " + outputFile);
138 writeProperties(outputFile, comment, properties, escapeTokens);
139 }
140
141 protected Properties getResolvedProperties(Properties props) {
142 PropertyPlaceholderHelper pph = new PropertyPlaceholderHelper("${", "}");
143 List<String> keys = new ArrayList<String>(props.stringPropertyNames());
144 Collections.sort(keys);
145 Properties newProps = new Properties();
146 for (String key : keys) {
147 String originalValue = props.getProperty(key);
148 String resolvedValue = pph.replacePlaceholders(originalValue, props);
149 newProps.setProperty(key, resolvedValue);
150 }
151 return newProps;
152
153 }
154
155 protected static Properties getEnvironmentVariables() {
156 String prefix = "env";
157 Map<String, String> map = System.getenv();
158 Properties props = new Properties();
159 for (String key : map.keySet()) {
160 String newKey = prefix + "." + key;
161 String value = map.get(key);
162 props.setProperty(newKey, value);
163 }
164 return props;
165 }
166
167 protected void trim(Properties properties, String excludeCSV, String includeCSV) {
168 List<String> omitKeys = ReadPropertiesMojo.getListFromCSV(excludeCSV);
169 for (String key : omitKeys) {
170 properties.remove(key);
171 }
172 if (StringUtils.isBlank(includeCSV)) {
173 return;
174 }
175 List<String> includeKeys = ReadPropertiesMojo.getListFromCSV(includeCSV);
176 Set<String> keys = properties.stringPropertyNames();
177 for (String key : keys) {
178 if (!includeKeys.contains(key)) {
179 properties.remove(key);
180 }
181 }
182 }
183
184 protected String getAntHeader() {
185 SimpleDateFormat dstamp = new SimpleDateFormat("yyyyMMdd");
186 SimpleDateFormat today = new SimpleDateFormat("MMMM d yyyy");
187 SimpleDateFormat tstamp = new SimpleDateFormat("HHmm");
188 Date now = new Date();
189 StringBuilder sb = new StringBuilder();
190 sb.append("# Ant properties\n");
191 sb.append("# " + now + "\n");
192 sb.append("DSTAMP=" + dstamp.format(now) + "\n");
193 sb.append("TODAY=" + today.format(now) + "\n");
194 sb.append("TSTAMP=" + tstamp.format(now) + "\n");
195 return sb.toString();
196 }
197
198 protected List<String> getEscapeChars(String escapeChars) {
199 List<String> tokens = ReadPropertiesMojo.getListFromCSV(escapeChars);
200 List<String> realTokens = new ArrayList<String>();
201 for (String token : tokens) {
202 String realToken = getRealToken(token);
203 realTokens.add(realToken);
204 }
205 return realTokens;
206 }
207
208 protected String getRealToken(String token) {
209 if (token.equalsIgnoreCase("CR")) {
210 return CR;
211 } else if (token.equalsIgnoreCase("LF")) {
212 return LF;
213 } else if (token.equalsIgnoreCase("TAB")) {
214 return TAB;
215 } else if (token.equalsIgnoreCase("BACKSLASH")) {
216 return BACKSLASH;
217 } else {
218 return token;
219 }
220 }
221
222 protected String getContent(String comment, Properties properties, List<String> escapeTokens) {
223 List<String> names = new ArrayList<String>(properties.stringPropertyNames());
224 Collections.sort(names);
225 StringBuilder sb = new StringBuilder();
226 if (!StringUtils.isBlank(comment)) {
227 sb.append(comment);
228 }
229 for (String name : names) {
230 String value = properties.getProperty(name);
231 String escapedValue = escape(value, escapeTokens);
232 sb.append(name + "=" + escapedValue + "\n");
233 }
234 return sb.toString();
235 }
236
237 protected void writeProperties(File file, String comment, Properties properties, List<String> escapeTokens) throws MojoExecutionException {
238 try {
239 String content = getContent(comment, properties, escapeTokens);
240 FileUtils.writeStringToFile(file, content);
241 } catch (IOException e) {
242 throw new MojoExecutionException("Error creating properties file", e);
243 }
244 }
245
246 protected String escape(String s, List<String> escapeChars) {
247 for (String escapeChar : escapeChars) {
248 String replacementToken = getReplacementToken(escapeChar);
249 s = s.replace(escapeChar, replacementToken);
250 }
251 return s;
252 }
253
254 protected String getReplacementToken(String escapeChar) {
255 if (escapeChar.equals(CR)) {
256 return "\\r";
257 } else if (escapeChar.equals(LF)) {
258 return "\\n";
259 } else if (escapeChar.equals(TAB)) {
260 return "\\t";
261 } else
262 return "\\" + escapeChar;
263 }
264
265 public boolean isAntEchoPropertiesMode() {
266 return antEchoPropertiesMode;
267 }
268
269 public void setAntEchoPropertiesMode(boolean antEchoPropertiesMode) {
270 this.antEchoPropertiesMode = antEchoPropertiesMode;
271 }
272
273 public boolean isIncludeSystemProperties() {
274 return includeSystemProperties;
275 }
276
277 public void setIncludeSystemProperties(boolean includeSystemProperties) {
278 this.includeSystemProperties = includeSystemProperties;
279 }
280
281 public String getEscapeChars() {
282 return escapeChars;
283 }
284
285 public void setEscapeChars(String escapeChars) {
286 this.escapeChars = escapeChars;
287 }
288
289 public boolean isIncludeEnvironmentVariables() {
290 return includeEnvironmentVariables;
291 }
292
293 public void setIncludeEnvironmentVariables(boolean includeEnvironmentVariables) {
294 this.includeEnvironmentVariables = includeEnvironmentVariables;
295 }
296
297 public String getExclude() {
298 return exclude;
299 }
300
301 public void setExclude(String exclude) {
302 this.exclude = exclude;
303 }
304
305 public String getInclude() {
306 return include;
307 }
308
309 public void setInclude(String include) {
310 this.include = include;
311 }
312
313 public boolean isResolvePlaceholders() {
314 return resolvePlaceholders;
315 }
316
317 public void setResolvePlaceholders(boolean resolvePlaceholders) {
318 this.resolvePlaceholders = resolvePlaceholders;
319 }
320 }