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  /*
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 }