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    import java.io.File;
019    import java.io.IOException;
020    import java.io.OutputStream;
021    import java.util.ArrayList;
022    import java.util.Collections;
023    import java.util.Date;
024    import java.util.List;
025    import java.util.Map;
026    import java.util.Properties;
027    import java.util.Set;
028    
029    import org.apache.commons.io.FileUtils;
030    import org.apache.commons.io.IOUtils;
031    import org.apache.maven.plugin.MojoExecutionException;
032    import org.apache.maven.plugin.MojoFailureException;
033    import org.codehaus.plexus.util.StringUtils;
034    import org.springframework.util.PropertyPlaceholderHelper;
035    
036    /**
037     * Write project properties to a file.
038     * 
039     * @author Jeff Caddel
040     * 
041     * @goal write-project-properties
042     */
043    public class WriteProjectProperties extends AbstractWritePropertiesMojo {
044    
045            /**
046             * If true, the plugin will include system properties when writing the properties file. System properties override both environment
047             * variables and project properties.
048             * 
049             * @parameter default-value="false" expression="${properties.includeSystemProperties}"
050             */
051            private boolean includeSystemProperties;
052    
053            /**
054             * If true, the plugin will include environment variables when writing the properties file. Environment variables are prefixed with
055             * "env". Environment variables override project properties.
056             * 
057             * @parameter default-value="false" expression="${properties.includeEnvironmentVariables}"
058             */
059            private boolean includeEnvironmentVariables;
060    
061            /**
062             * Comma separated set of properties to exclude when writing the properties file
063             * 
064             * @parameter expression="${properties.exclude}"
065             */
066            private String exclude;
067    
068            /**
069             * Comma separated set of properties to write to the properties file. If provided, only the properties matching those supplied here will
070             * be written to the properties file.
071             * 
072             * @parameter expression="${properties.include}"
073             */
074            private String include;
075    
076            /**
077             * If true placeholders are resolved before writing properties to the file
078             * 
079             * @parameter expression="${properties.resolvePlaceholders}"
080             */
081            private boolean resolvePlaceholders;
082    
083            @Override
084            public void execute() throws MojoExecutionException, MojoFailureException {
085                    Properties properties = new Properties();
086                    // Add project properties
087                    properties.putAll(project.getProperties());
088                    if (includeEnvironmentVariables) {
089                            // Add environment variables, overriding any existing properties with the same key
090                            properties.putAll(getEnvironmentVariables());
091                    }
092                    if (includeSystemProperties) {
093                            // Add system properties, overriding any existing properties with the same key
094                            properties.putAll(System.getProperties());
095                    }
096    
097                    // Remove properties as appropriate
098                    trim(properties, exclude, include);
099    
100                    if (resolvePlaceholders) {
101                            properties = getResolvedProperties(properties);
102                    }
103    
104                    String comment = "# " + new Date() + "\n";
105                    getLog().info("Creating " + outputFile);
106                    writeProperties(outputFile, comment, properties);
107            }
108    
109            protected Properties getResolvedProperties(Properties props) {
110                    PropertyPlaceholderHelper pph = new PropertyPlaceholderHelper("${", "}");
111                    List<String> keys = new ArrayList<String>(props.stringPropertyNames());
112                    Collections.sort(keys);
113                    Properties newProps = new Properties();
114                    for (String key : keys) {
115                            String originalValue = props.getProperty(key);
116                            String resolvedValue = pph.replacePlaceholders(originalValue, props);
117                            newProps.setProperty(key, resolvedValue);
118                    }
119                    return newProps;
120    
121            }
122    
123            protected static Properties getEnvironmentVariables() {
124                    String prefix = "env";
125                    Map<String, String> map = System.getenv();
126                    Properties props = new Properties();
127                    for (String key : map.keySet()) {
128                            String newKey = prefix + "." + key;
129                            String value = map.get(key);
130                            props.setProperty(newKey, value);
131                    }
132                    return props;
133            }
134    
135            protected void trim(Properties properties, String excludeCSV, String includeCSV) {
136                    List<String> omitKeys = ReadPropertiesMojo.getListFromCSV(excludeCSV);
137                    for (String key : omitKeys) {
138                            properties.remove(key);
139                    }
140                    if (StringUtils.isBlank(includeCSV)) {
141                            return;
142                    }
143                    List<String> includeKeys = ReadPropertiesMojo.getListFromCSV(includeCSV);
144                    Set<String> keys = properties.stringPropertyNames();
145                    for (String key : keys) {
146                            if (!includeKeys.contains(key)) {
147                                    properties.remove(key);
148                            }
149                    }
150            }
151    
152            protected void writeProperties(File file, String comment, Properties properties) throws MojoExecutionException {
153                    SortedProperties sp = new SortedProperties();
154                    sp.putAll(properties);
155                    OutputStream out = null;
156                    try {
157                            out = FileUtils.openOutputStream(file);
158                            sp.store(out, comment);
159                    } catch (IOException e) {
160                            throw new MojoExecutionException("Error creating properties file", e);
161                    } finally {
162                            IOUtils.closeQuietly(out);
163                    }
164            }
165    
166            public boolean isIncludeSystemProperties() {
167                    return includeSystemProperties;
168            }
169    
170            public void setIncludeSystemProperties(boolean includeSystemProperties) {
171                    this.includeSystemProperties = includeSystemProperties;
172            }
173    
174            public boolean isIncludeEnvironmentVariables() {
175                    return includeEnvironmentVariables;
176            }
177    
178            public void setIncludeEnvironmentVariables(boolean includeEnvironmentVariables) {
179                    this.includeEnvironmentVariables = includeEnvironmentVariables;
180            }
181    
182            public String getExclude() {
183                    return exclude;
184            }
185    
186            public void setExclude(String exclude) {
187                    this.exclude = exclude;
188            }
189    
190            public String getInclude() {
191                    return include;
192            }
193    
194            public void setInclude(String include) {
195                    this.include = include;
196            }
197    
198            public boolean isResolvePlaceholders() {
199                    return resolvePlaceholders;
200            }
201    
202            public void setResolvePlaceholders(boolean resolvePlaceholders) {
203                    this.resolvePlaceholders = resolvePlaceholders;
204            }
205    }