001 package org.codehaus.mojo.properties;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
005 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
007 * License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
012 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
013 * specific language governing permissions and limitations under the License.
014 */
015
016 import java.io.File;
017 import java.io.FileInputStream;
018 import java.io.IOException;
019 import java.util.Enumeration;
020 import java.util.Properties;
021
022 import org.apache.maven.plugin.AbstractMojo;
023 import org.apache.maven.plugin.MojoExecutionException;
024 import org.apache.maven.project.MavenProject;
025 import org.codehaus.plexus.util.cli.CommandLineUtils;
026
027 /**
028 * The read-project-properties goal reads property files and stores the properties as project properties. It serves as
029 * an alternate to specifying properties in pom.xml.
030 *
031 * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a>
032 * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a>
033 * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $
034 * @goal read-project-properties
035 */
036 public class ReadPropertiesMojo extends AbstractMojo {
037 /**
038 * @parameter default-value="${project}"
039 * @required
040 * @readonly
041 */
042 private MavenProject project;
043
044 /**
045 * The properties files that will be used when reading properties. Can use both .properties and .xml files
046 *
047 * @parameter
048 * @required
049 */
050 private File[] files;
051
052 /**
053 * If the plugin should be quiet if any of the files was not found
054 *
055 * @parameter default-value="false"
056 */
057 private boolean quiet;
058
059 public void execute() throws MojoExecutionException {
060 Properties projectProperties = new Properties();
061 for (int i = 0; i < files.length; i++) {
062 File file = files[i];
063
064 if (file.exists()) {
065 try {
066 getLog().debug("Loading property file: " + file);
067
068 FileInputStream stream = new FileInputStream(file);
069 projectProperties = project.getProperties();
070
071 try {
072 String filename = file.getName().toLowerCase();
073 if (filename.endsWith(".xml")) {
074 projectProperties.loadFromXML(stream);
075 } else {
076 projectProperties.load(stream);
077 }
078 } finally {
079 if (stream != null) {
080 stream.close();
081 }
082 }
083 } catch (IOException e) {
084 throw new MojoExecutionException("Error reading properties file " + file.getAbsolutePath(), e);
085 }
086 } else {
087 if (quiet) {
088 getLog().warn("Ignoring missing properties file: " + file.getAbsolutePath());
089 } else {
090 throw new MojoExecutionException("Properties file not found: " + file.getAbsolutePath());
091 }
092 }
093 }
094
095 boolean useEnvVariables = false;
096 for (Enumeration n = projectProperties.propertyNames(); n.hasMoreElements();) {
097 String k = (String) n.nextElement();
098 String p = (String) projectProperties.get(k);
099 if (p.indexOf("${env.") != -1) {
100 useEnvVariables = true;
101 break;
102 }
103 }
104 Properties environment = null;
105 if (useEnvVariables) {
106 try {
107 environment = CommandLineUtils.getSystemEnvVars();
108 } catch (IOException e) {
109 throw new MojoExecutionException("Error getting system envorinment variables: ", e);
110 }
111 }
112 for (Enumeration n = projectProperties.propertyNames(); n.hasMoreElements();) {
113 String k = (String) n.nextElement();
114 projectProperties.setProperty(k, getPropertyValue(k, projectProperties, environment));
115 }
116 }
117
118 /**
119 * Retrieves a property value, replacing values like ${token} using the Properties to look them up. Shamelessly
120 * adapted from:
121 * http://maven.apache.org/plugins/maven-war-plugin/xref/org/apache/maven/plugin/war/PropertyUtils.html
122 *
123 * It will leave unresolved properties alone, trying for System properties, and environment variables and implements
124 * reparsing (in the case that the value of a property contains a key), and will not loop endlessly on a pair like
125 * test = ${test}
126 *
127 * @param k
128 * property key
129 * @param p
130 * project properties
131 * @param environment
132 * environment variables
133 * @return resolved property value
134 */
135 private String getPropertyValue(String k, Properties p, Properties environment) {
136 String v = p.getProperty(k);
137 String ret = "";
138 int idx, idx2;
139
140 while ((idx = v.indexOf("${")) >= 0) {
141 // append prefix to result
142 ret += v.substring(0, idx);
143
144 // strip prefix from original
145 v = v.substring(idx + 2);
146
147 idx2 = v.indexOf("}");
148
149 // if no matching } then bail
150 if (idx2 < 0) {
151 break;
152 }
153
154 // strip out the key and resolve it
155 // resolve the key/value for the ${statement}
156 String nk = v.substring(0, idx2);
157 v = v.substring(idx2 + 1);
158 String nv = p.getProperty(nk);
159
160 // try global environment
161 if (nv == null) {
162 nv = System.getProperty(nk);
163 }
164
165 // try environment variable
166 if (nv == null && nk.startsWith("env.") && environment != null) {
167 nv = environment.getProperty(nk.substring(4));
168 }
169
170 // if the key cannot be resolved,
171 // leave it alone ( and don't parse again )
172 // else prefix the original string with the
173 // resolved property ( so it can be parsed further )
174 // taking recursion into account.
175 if (nv == null || nv.equals(nk)) {
176 ret += "${" + nk + "}";
177 } else {
178 v = nv + v;
179 }
180 }
181 return ret + v;
182 }
183 }