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.ArrayList;
23  import java.util.List;
24  import java.util.Properties;
25  import java.util.Set;
26  
27  import org.apache.commons.io.IOUtils;
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.maven.plugin.AbstractMojo;
30  import org.apache.maven.plugin.MojoExecutionException;
31  import org.apache.maven.project.MavenProject;
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
39   * an alternate to 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
42   * means anything you can do with Spring property values you can do with property values handled by this plugin. For
43   * example, nested properties are supported: 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 static final List<String> getListFromCSV(String csv) {
140         if (StringUtils.isBlank(csv)) {
141             return new ArrayList<String>();
142         }
143         List<String> list = new ArrayList<String>();
144         String[] tokens = StringUtils.split(csv, ",");
145         for (String token : tokens) {
146             list.add(token.trim());
147         }
148         return list;
149     }
150 
151     protected String toEmpty(String s) {
152         if (StringUtils.isBlank(s)) {
153             return "";
154         } else {
155             return s;
156         }
157     }
158 
159     protected boolean exists(String location) {
160         if (StringUtils.isBlank(location)) {
161             return false;
162         }
163         File file = new File(location);
164         if (file.exists()) {
165             return true;
166         }
167         ResourceLoader loader = new DefaultResourceLoader();
168         Resource resource = loader.getResource(location);
169         return resource.exists();
170     }
171 
172     protected boolean validate(String location) throws MojoExecutionException {
173         boolean exists = exists(location);
174         if (exists) {
175             return true;
176         }
177         if (quiet) {
178             if (verbose && !silent) {
179                 getLog().info("Ignoring non-existent properties file '" + toEmpty(location) + "'");
180             }
181             return false;
182         } else {
183             throw new MojoExecutionException("Non-existent properties file '" + location + "'");
184         }
185     }
186 
187     protected InputStream getInputStream(String location) throws IOException {
188         File file = new File(location);
189         if (file.exists()) {
190             return new FileInputStream(location);
191         }
192         ResourceLoader loader = new DefaultResourceLoader();
193         Resource resource = loader.getResource(location);
194         return resource.getInputStream();
195     }
196 
197     protected Properties getProperties(String location) throws MojoExecutionException {
198         InputStream in = null;
199         try {
200             Properties properties = new Properties();
201             in = getInputStream(location);
202             if (location.toLowerCase().endsWith(".xml")) {
203                 properties.loadFromXML(in);
204             } else {
205                 properties.load(in);
206             }
207             return properties;
208         } catch (IOException e) {
209             throw new MojoExecutionException("Error reading properties file " + location, e);
210         } finally {
211             IOUtils.closeQuietly(in);
212         }
213     }
214 
215     public boolean isQuiet() {
216         return quiet;
217     }
218 
219     public void setQuiet(boolean quiet) {
220         this.quiet = quiet;
221     }
222 
223     public String getIgnore() {
224         return ignore;
225     }
226 
227     public void setIgnore(String ignoreProperties) {
228         this.ignore = ignoreProperties;
229     }
230 
231     public MavenProject getProject() {
232         return project;
233     }
234 
235     public String[] getLocations() {
236         return locations;
237     }
238 
239     public void setLocations(String[] locations) {
240         this.locations = locations;
241     }
242 
243     public boolean isVerbose() {
244         return verbose;
245     }
246 
247     public void setVerbose(boolean verbose) {
248         this.verbose = verbose;
249     }
250 
251     public boolean isSilent() {
252         return silent;
253     }
254 
255     public void setSilent(boolean silent) {
256         this.silent = silent;
257     }
258 
259     protected List<String> getIgnoreList() {
260         List<String> ignoreList = getListFromCSV(ignore);
261         if (!silent && verbose && !StringUtils.isBlank(ignore)) {
262             getLog().info("Ignoring " + ignore);
263         }
264         return ignoreList;
265     }
266 
267     protected void updateProjectProperties(List<String> ignoreList) throws MojoExecutionException {
268         Properties projectProperties = project.getProperties();
269         for (int i = 0; i < locations.length; i++) {
270             Properties allProperties = utils.getMavenProperties(project);
271             String originalLocation = locations[i];
272             String resolvedLocation = utils.getResolvedValue(originalLocation, allProperties);
273             getLog().debug("o=" + originalLocation + " r=" + resolvedLocation);
274             if (!validate(resolvedLocation)) {
275                 continue;
276             }
277             if (!silent) {
278                 getLog().info("Loading " + resolvedLocation);
279             }
280 
281             // Load properties from this location
282             Properties p = getProperties(resolvedLocation);
283 
284             // Update project properties from the properties we just loaded
285             updateProperties(projectProperties, p, ignoreList);
286         }
287     }
288 
289 }