eu.dnetlib.maven.plugin.properties.WritePredefinedProjectProperties.java Source code

Java tutorial

Introduction

Here is the source code for eu.dnetlib.maven.plugin.properties.WritePredefinedProjectProperties.java

Source

/**
 * 
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package eu.dnetlib.maven.plugin.properties;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

/**
 * Writes project properties for the keys listed in specified properties files.
 * Based on: 
 * http://site.kuali.org/maven/plugins/properties-maven-plugin/1.3.2/write-project-properties-mojo.html
    
 * @author mhorst
 * @goal write-project-properties
 */
public class WritePredefinedProjectProperties extends AbstractMojo {

    private static final String CR = "\r";
    private static final String LF = "\n";
    private static final String TAB = "\t";
    private static final String[] ANT_ESCAPE_CHARS = { CR, LF, TAB, ":", "#", "=" };

    /**
     * @parameter expression="${properties.includePropertyKeysFromFiles}"
     */
    private String[] includePropertyKeysFromFiles;

    /**
     * @parameter default-value="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * The file that properties will be written to
     * 
     * @parameter expression="${properties.outputFile}"
     *            default-value="${project.build.directory}/properties/project.properties";
     * @required
     */
    private File outputFile;

    /**
      * If true, the plugin will silently ignore any non-existent properties files, and the build will continue
      *
      * @parameter expression="${properties.quiet}" default-value="true"
      */
    private boolean quiet;

    /**
     * Comma separated list of characters to escape when writing property values. cr=carriage return, lf=linefeed,
     * tab=tab. Any other values are taken literally.
     * 
     * @parameter default-value="cr,lf,tab" expression="${properties.escapeChars}"
     */
    private String escapeChars;

    /**
     * If true, the plugin will create the properties file formatted the same way Ant formats properties files using the
     * <code>echoproperties</code> task. This mode adds 3 custom properties at the top of the file, DSTAMP, TODAY, and
     * TSTAMP. In this mode <code>escapeChars</code> is ignored and the 6 characters Ant escapes are used instead
     * <code>CR</code>,<code>LF</code>,<code>TAB</code>,<code>:</code>,<code>#</code>,<code>=</code>
     * 
     * @parameter default-value="false" expression="${properties.antEchoPropertiesMode}"
     */
    private boolean antEchoPropertiesMode;

    /**
     * If true, the plugin will include system properties when writing the properties file. System properties override
     * both environment variables and project properties.
     * 
     * @parameter default-value="false" expression="${properties.includeSystemProperties}"
     */
    private boolean includeSystemProperties;

    /**
     * If true, the plugin will include environment variables when writing the properties file. Environment variables
     * are prefixed with "env". Environment variables override project properties.
     * 
     * @parameter default-value="false" expression="${properties.includeEnvironmentVariables}"
     */
    private boolean includeEnvironmentVariables;

    /**
     * Comma separated set of properties to exclude when writing the properties file
     * 
     * @parameter expression="${properties.exclude}"
     */
    private String exclude;

    /**
     * Comma separated set of properties to write to the properties file. If provided, only the properties matching
     * those supplied here will be written to the properties file.
     * 
     * @parameter expression="${properties.include}"
     */
    private String include;

    /* (non-Javadoc)
     * @see org.apache.maven.plugin.AbstractMojo#execute()
     */
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        Properties properties = new Properties();
        // Add project properties
        properties.putAll(project.getProperties());
        if (includeEnvironmentVariables) {
            // Add environment variables, overriding any existing properties with the same key
            properties.putAll(getEnvironmentVariables());
        }
        if (includeSystemProperties) {
            // Add system properties, overriding any existing properties with the same key
            properties.putAll(System.getProperties());
        }

        // Remove properties as appropriate
        trim(properties, exclude, include);

        String comment = "# " + new Date() + "\n";
        List<String> escapeTokens = getEscapeChars(escapeChars);
        if (antEchoPropertiesMode) {
            escapeTokens = Arrays.asList(ANT_ESCAPE_CHARS);
            comment = getAntHeader();
            properties.remove("DSTAMP");
            properties.remove("TODAY");
            properties.remove("TSTAMP");
        }

        getLog().info("Creating " + outputFile);
        writeProperties(outputFile, comment, properties, escapeTokens);
    }

    /**
     * Provides environment variables.
     * @return environment variables
     */
    protected static Properties getEnvironmentVariables() {
        String prefix = "env";
        Map<String, String> map = System.getenv();
        Properties props = new Properties();
        for (String key : map.keySet()) {
            String newKey = prefix + "." + key;
            String value = map.get(key);
            props.setProperty(newKey, value);
        }
        return props;
    }

    /**
     * Removes properties which should not be written.
     * @param properties
     * @param omitCSV
     * @param includeCSV
     * @throws MojoExecutionException
     */
    protected void trim(Properties properties, String omitCSV, String includeCSV) throws MojoExecutionException {
        List<String> omitKeys = getListFromCSV(omitCSV);
        for (String key : omitKeys) {
            properties.remove(key);
        }

        List<String> includeKeys = getListFromCSV(includeCSV);
        //      mh: including keys from predefined properties
        if (includePropertyKeysFromFiles != null && includePropertyKeysFromFiles.length > 0) {
            for (String currentIncludeLoc : includePropertyKeysFromFiles) {
                if (validate(currentIncludeLoc)) {
                    Properties p = getProperties(currentIncludeLoc);
                    for (String key : p.stringPropertyNames()) {
                        includeKeys.add(key);
                    }
                }
            }
        }
        if (includeKeys != null && !includeKeys.isEmpty()) {
            //           removing only when include keys provided
            Set<String> keys = properties.stringPropertyNames();
            for (String key : keys) {
                if (!includeKeys.contains(key)) {
                    properties.remove(key);
                }
            }
        }
    }

    protected String toEmpty(String s) {
        if (StringUtils.isBlank(s)) {
            return "";
        } else {
            return s;
        }
    }

    /**
     * Checks whether file exists.
     * @param location
     * @return true when exists, false otherwise.
     */
    protected boolean exists(String location) {
        if (StringUtils.isBlank(location)) {
            return false;
        }
        File file = new File(location);
        if (file.exists()) {
            return true;
        }
        ResourceLoader loader = new DefaultResourceLoader();
        Resource resource = loader.getResource(location);
        return resource.exists();
    }

    /**
     * Validates resource location.
     * @param location
     * @return true when valid, false otherwise
     * @throws MojoExecutionException
     */
    protected boolean validate(String location) throws MojoExecutionException {
        boolean exists = exists(location);
        if (exists) {
            return true;
        }
        if (quiet) {
            getLog().info("Ignoring non-existent properties file '" + toEmpty(location) + "'");
            return false;
        } else {
            throw new MojoExecutionException("Non-existent properties file '" + location + "'");
        }
    }

    /**
     * Provides input stream.
     * @param location
     * @return input stream
     * @throws IOException
     */
    protected InputStream getInputStream(String location) throws IOException {
        File file = new File(location);
        if (file.exists()) {
            return new FileInputStream(location);
        }
        ResourceLoader loader = new DefaultResourceLoader();
        Resource resource = loader.getResource(location);
        return resource.getInputStream();
    }

    /**
     * Creates properties for given location.
     * @param location
     * @return properties for given location
     * @throws MojoExecutionException
     */
    protected Properties getProperties(String location) throws MojoExecutionException {
        InputStream in = null;
        try {
            Properties properties = new Properties();
            in = getInputStream(location);
            if (location.toLowerCase().endsWith(".xml")) {
                properties.loadFromXML(in);
            } else {
                properties.load(in);
            }
            return properties;
        } catch (IOException e) {
            throw new MojoExecutionException("Error reading properties file " + location, e);
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    /**
     * Provides ant header.
     * @return ant header
     */
    protected String getAntHeader() {
        SimpleDateFormat dstamp = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat today = new SimpleDateFormat("MMMM d yyyy");
        SimpleDateFormat tstamp = new SimpleDateFormat("HHmm");
        Date now = new Date();
        StringBuilder sb = new StringBuilder();
        sb.append("# Ant properties\n");
        sb.append("# " + now + "\n");
        sb.append("DSTAMP=" + dstamp.format(now) + "\n");
        sb.append("TODAY=" + today.format(now) + "\n");
        sb.append("TSTAMP=" + tstamp.format(now) + "\n");
        return sb.toString();
    }

    /**
     * Provides escape characters.
     * @param escapeChars
     * @return escape characters
     */
    protected List<String> getEscapeChars(String escapeChars) {
        List<String> tokens = getListFromCSV(escapeChars);
        List<String> realTokens = new ArrayList<String>();
        for (String token : tokens) {
            String realToken = getRealToken(token);
            realTokens.add(realToken);
        }
        return realTokens;
    }

    /**
     * Provides real token.
     * @param token
     * @return real token
     */
    protected String getRealToken(String token) {
        if (token.equalsIgnoreCase("CR")) {
            return CR;
        } else if (token.equalsIgnoreCase("LF")) {
            return LF;
        } else if (token.equalsIgnoreCase("TAB")) {
            return TAB;
        } else {
            return token;
        }
    }

    /**
     * Returns content.
     * @param comment
     * @param properties
     * @param escapeTokens
     * @return content
     */
    protected String getContent(String comment, Properties properties, List<String> escapeTokens) {
        List<String> names = new ArrayList<String>(properties.stringPropertyNames());
        Collections.sort(names);
        StringBuilder sb = new StringBuilder();
        if (!StringUtils.isBlank(comment)) {
            sb.append(comment);
        }
        for (String name : names) {
            String value = properties.getProperty(name);
            String escapedValue = escape(value, escapeTokens);
            sb.append(name + "=" + escapedValue + "\n");
        }
        return sb.toString();
    }

    /**
     * Writes properties to given file.
     * @param file
     * @param comment
     * @param properties
     * @param escapeTokens
     * @throws MojoExecutionException
     */
    protected void writeProperties(File file, String comment, Properties properties, List<String> escapeTokens)
            throws MojoExecutionException {
        try {
            String content = getContent(comment, properties, escapeTokens);
            FileUtils.writeStringToFile(file, content);
        } catch (IOException e) {
            throw new MojoExecutionException("Error creating properties file", e);
        }
    }

    /**
     * Writes properties.
     * @param properties
     * @param file
     * @throws MojoExecutionException
     */
    protected void writeProperties(Properties properties, File file) throws MojoExecutionException {
        OutputStream out = null;
        try {
            out = FileUtils.openOutputStream(outputFile);
            properties.store(out, "Properties");
        } catch (IOException e) {
            throw new MojoExecutionException("Error creating properties file", e);
        } finally {
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * Escapes characters.
     * @param s
     * @param escapeChars
     * @return
     */
    protected String escape(String s, List<String> escapeChars) {
        String result = s;
        for (String escapeChar : escapeChars) {
            result = result.replace(escapeChar, getReplacementToken(escapeChar));
        }
        return result;
    }

    /**
     * Provides replacement token.
     * @param escapeChar
     * @return replacement token
     */
    protected String getReplacementToken(String escapeChar) {
        if (escapeChar.equals(CR)) {
            return "\\r";
        } else if (escapeChar.equals(LF)) {
            return "\\n";
        } else if (escapeChar.equals(TAB)) {
            return "\\t";
        } else {
            return "\\" + escapeChar;
        }
    }

    /**
    * Returns list from csv.
    * @param csv
    * @return list of values generated from CSV
    */
    protected static final List<String> getListFromCSV(String csv) {
        if (StringUtils.isBlank(csv)) {
            return new ArrayList<String>();
        }
        List<String> list = new ArrayList<String>();
        String[] tokens = StringUtils.split(csv, ",");
        for (String token : tokens) {
            list.add(token.trim());
        }
        return list;
    }

    public boolean isAntEchoPropertiesMode() {
        return antEchoPropertiesMode;
    }

    public void setAntEchoPropertiesMode(boolean antEchoPropertiesMode) {
        this.antEchoPropertiesMode = antEchoPropertiesMode;
    }

    public boolean isIncludeSystemProperties() {
        return includeSystemProperties;
    }

    public void setIncludeSystemProperties(boolean includeSystemProperties) {
        this.includeSystemProperties = includeSystemProperties;
    }

    public String getEscapeChars() {
        return escapeChars;
    }

    public void setEscapeChars(String escapeChars) {
        this.escapeChars = escapeChars;
    }

    public boolean isIncludeEnvironmentVariables() {
        return includeEnvironmentVariables;
    }

    public void setIncludeEnvironmentVariables(boolean includeEnvironmentVariables) {
        this.includeEnvironmentVariables = includeEnvironmentVariables;
    }

    public String getExclude() {
        return exclude;
    }

    public void setExclude(String exclude) {
        this.exclude = exclude;
    }

    public String getInclude() {
        return include;
    }

    public void setInclude(String include) {
        this.include = include;
    }

    public boolean isQuiet() {
        return quiet;
    }

    public void setQuiet(boolean quiet) {
        this.quiet = quiet;
    }

    /**
     * Sets property files for which keys properties should be included.
     * @param includePropertyKeysFromFiles
     */
    public void setIncludePropertyKeysFromFiles(String[] includePropertyKeysFromFiles) {
        if (includePropertyKeysFromFiles != null) {
            this.includePropertyKeysFromFiles = Arrays.copyOf(includePropertyKeysFromFiles,
                    includePropertyKeysFromFiles.length);
        }
    }
}