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.Enumeration;
37  import java.util.List;
38  import java.util.Properties;
39  import java.util.Set;
40  
41  import org.apache.commons.io.IOUtils;
42  import org.apache.maven.plugin.AbstractMojo;
43  import org.apache.maven.plugin.MojoExecutionException;
44  import org.apache.maven.project.MavenProject;
45  import org.codehaus.plexus.util.StringUtils;
46  import org.codehaus.plexus.util.cli.CommandLineUtils;
47  
48  /**
49   * The read-project-properties goal reads property files and stores the properties as project properties. It serves as
50   * an alternate to specifying properties in pom.xml.
51   *
52   * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a>
53   * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a>
54   * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $
55   * @goal read-project-properties
56   */
57  public class ReadPropertiesMojo extends AbstractMojo {
58  
59      /**
60       * @parameter default-value="${project}"
61       * @required
62       * @readonly
63       */
64      private MavenProject project;
65  
66      /**
67       * The properties files that will be used when reading properties. Can use both .properties and .xml files
68       *
69       * @parameter
70       * @required
71       */
72      private File[] files;
73  
74      /**
75       * If true, the plugin will silently ignore any non-existent properties files, and the build will continue
76       *
77       * @parameter expression="${properties.quiet}" default-value="false"
78       */
79      private boolean quiet;
80  
81      /**
82       * Comma separated list of property values to ignore
83       *
84       * @parameter expression="${properties.ignore}"
85       */
86      private String ignore;
87  
88      @Override
89      public void execute() throws MojoExecutionException {
90          List<String> ignoreList = getListFromCSV(ignore);
91          Properties projectProperties = project.getProperties();
92          for (int i = 0; i < files.length; i++) {
93              File file = files[i];
94              if (validate(file)) {
95                  Properties p = getProperties(file);
96                  updateProperties(projectProperties, p, ignoreList);
97              }
98          }
99  
100         boolean useEnvVariables = false;
101         for (Enumeration<?> n = projectProperties.propertyNames(); n.hasMoreElements();) {
102             String k = (String) n.nextElement();
103             String p = (String) projectProperties.get(k);
104             if (p.indexOf("${env.") != -1) {
105                 useEnvVariables = true;
106                 break;
107             }
108         }
109         Properties environment = null;
110         if (useEnvVariables) {
111             try {
112                 environment = CommandLineUtils.getSystemEnvVars();
113             } catch (IOException e) {
114                 throw new MojoExecutionException("Error getting system envorinment variables: ", e);
115             }
116         }
117         for (Enumeration<?> n = projectProperties.propertyNames(); n.hasMoreElements();) {
118             String k = (String) n.nextElement();
119             projectProperties.setProperty(k, getPropertyValue(k, projectProperties, environment));
120         }
121     }
122 
123     protected void updateProperties(Properties p1, Properties p2, List<String> ignore) {
124         Set<String> names = p2.stringPropertyNames();
125         for (String name : names) {
126             if (!ignore.contains(name)) {
127                 String value = p2.getProperty(name);
128                 p1.setProperty(name, value);
129             }
130         }
131     }
132 
133     protected List<String> getListFromCSV(String csv) {
134         if (StringUtils.isBlank(csv)) {
135             return new ArrayList<String>();
136         }
137         List<String> list = new ArrayList<String>();
138         String[] tokens = StringUtils.split(csv, ",");
139         for (String token : tokens) {
140             list.add(token.trim());
141         }
142         return list;
143     }
144 
145     /**
146      * Retrieves a property value, replacing values like ${token} using the Properties to look them up. Shamelessly
147      * adapted from:
148      * http://maven.apache.org/plugins/maven-war-plugin/xref/org/apache/maven/plugin/war/PropertyUtils.html
149      *
150      * It will leave unresolved properties alone, trying for System properties, and environment variables and implements
151      * reparsing (in the case that the value of a property contains a key), and will not loop endlessly on a pair like
152      * test = ${test}
153      *
154      * @param k
155      *            property key
156      * @param p
157      *            project properties
158      * @param environment
159      *            environment variables
160      * @return resolved property value
161      */
162     protected String getPropertyValue(String k, Properties p, Properties environment) {
163         String v = p.getProperty(k);
164         String ret = "";
165         int idx, idx2;
166 
167         while ((idx = v.indexOf("${")) >= 0) {
168             // append prefix to result
169             ret += v.substring(0, idx);
170 
171             // strip prefix from original
172             v = v.substring(idx + 2);
173 
174             idx2 = v.indexOf("}");
175 
176             // if no matching } then bail
177             if (idx2 < 0) {
178                 break;
179             }
180 
181             // strip out the key and resolve it
182             // resolve the key/value for the ${statement}
183             String nk = v.substring(0, idx2);
184             v = v.substring(idx2 + 1);
185             String nv = p.getProperty(nk);
186 
187             // try global environment
188             if (nv == null) {
189                 nv = System.getProperty(nk);
190             }
191 
192             // try environment variable
193             if (nv == null && nk.startsWith("env.") && environment != null) {
194                 nv = environment.getProperty(nk.substring(4));
195             }
196 
197             // if the key cannot be resolved,
198             // leave it alone ( and don't parse again )
199             // else prefix the original string with the
200             // resolved property ( so it can be parsed further )
201             // taking recursion into account.
202             if (nv == null || nv.equals(nk)) {
203                 ret += "${" + nk + "}";
204             } else {
205                 v = nv + v;
206             }
207         }
208         return ret + v;
209     }
210 
211     protected boolean validate(File file) throws MojoExecutionException {
212         boolean exists = file != null && file.exists();
213         if (exists) {
214             return true;
215         }
216         if (quiet) {
217             getLog().info("Ignoring non-existent properties file '" + file + "'");
218             return false;
219         } else {
220             throw new MojoExecutionException("Non-existent properties file '" + file + "'");
221         }
222     }
223 
224     protected Properties getProperties(File file) throws MojoExecutionException {
225         InputStream in = null;
226         try {
227             getLog().info("Loading " + file);
228             Properties properties = new Properties();
229             in = new FileInputStream(file);
230             String filename = file.getName().toLowerCase();
231             if (filename.endsWith(".xml")) {
232                 properties.loadFromXML(in);
233             } else {
234                 properties.load(in);
235             }
236             return properties;
237         } catch (IOException e) {
238             throw new MojoExecutionException("Error reading properties file " + file.getAbsolutePath(), e);
239         } finally {
240             IOUtils.closeQuietly(in);
241         }
242     }
243 
244     public File[] getFiles() {
245         return files;
246     }
247 
248     public void setFiles(File[] files) {
249         this.files = files;
250     }
251 
252     public boolean isQuiet() {
253         return quiet;
254     }
255 
256     public void setQuiet(boolean quiet) {
257         this.quiet = quiet;
258     }
259 
260     public String getIgnore() {
261         return ignore;
262     }
263 
264     public void setIgnore(String ignoreProperties) {
265         this.ignore = ignoreProperties;
266     }
267 
268     public MavenProject getProject() {
269         return project;
270     }
271 
272 }