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