
com.google.code.maven_replacer_plugin.ReplacerMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-replacer-plugin Show documentation
Show all versions of maven-replacer-plugin Show documentation
Maven plugin to replace tokens in a given file with a value
The newest version!
package com.google.code.maven_replacer_plugin;
import static org.apache.commons.lang.StringUtils.isEmpty;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.PatternSyntaxException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import com.google.code.maven_replacer_plugin.file.FileUtils;
import com.google.code.maven_replacer_plugin.include.FileSelector;
/**
* Goal replaces token with value inside file
*
* @goal replace
*
* @phase compile
*
* @threadSafe
*
*/
public class ReplacerMojo extends AbstractMojo {
private static final String INVALID_IGNORE_MISSING_FILE_MESSAGE = " only useable with ";
private static final String REGEX_PATTERN_WITH_DELIMITERS_MESSAGE = "Error: %s. " +
"Check that your delimiters do not contain regex characters. (e.g. '$'). " +
"Either remove the regex characters from your delimiters or set false " +
" in your configuration.";
private final FileUtils fileUtils;
private final ReplacerFactory replacerFactory;
private final TokenValueMapFactory tokenValueMapFactory;
private final FileSelector fileSelector;
private final PatternFlagsFactory patternFlagsFactory;
private final OutputFilenameBuilder outputFilenameBuilder;
private final SummaryBuilder summaryBuilder;
private final ReplacementProcessor processor;
/**
* File to check and replace tokens.
* Path to single file to replace tokens in.
* The file must be text (ascii).
* Based on current execution path.
*
* @parameter expression=""
*/
private String file;
/**
* List of files to include for multiple (or single) replacement.
* In Ant format (*\/directory/**.properties)
* Cannot use with outputFile.
*
* @parameter expression=""
*/
private List includes = new ArrayList();
/**
* List of files to exclude for multiple (or single) replacement.
* In Ant format (*\/directory/**.properties)
* Cannot use with outputFile.
*
* @parameter expression=""
*/
private List excludes = new ArrayList();
/**
* Comma separated list of includes.
* This is split up and used the same way a array of includes would be.
* In Ant format (*\/directory/**.properties).
* Files not found are ignored by default.
*
* @parameter expression=""
*/
private String filesToInclude;
/**
* List of comma separated files to exclude (must have some includes) for multiple (or single) replacement.
* This is split up and used the same way a array of excludes would be.
* In Ant format (**\/directory/do-not-replace.properties).
* The files replaced will be derived from the list of includes and excludes.
*
* @parameter expression=""
*/
private String filesToExclude;
/**
* Token to replace.
* The text to replace within the given file.
* This may or may not be a regular expression (see regex notes above).
*
* @parameter expression=""
*/
private String token;
/**
* Token file containing a token to be replaced in the target file/s.
* May be multiple words or lines.
* This is useful if you do not wish to expose the token within your pom or the token is long.
*
* @parameter expression=""
*/
private String tokenFile;
/**
* Ignore missing target file.
* Use only with file configuration (not includes etc).
* Set to true to not fail build if the file is not found.
* First checks if file exists and exits without attempting to replace anything.
*
* @parameter expression=""
*/
private boolean ignoreMissingFile;
/**
* Value to replace token with.
* The text to be written over any found tokens.
* If no value is given, the tokens found are replaced with an empty string (effectively removing any tokens found).
* You can also reference grouped regex matches made in the token here by $1, $2, etc.
*
* @parameter expression=""
*/
private String value;
/**
* A file containing a value to replace the given token with.
* May be multiple words or lines.
* This is useful if you do not wish to expose the value within your pom or the value is long.
*
* @parameter expression=""
*/
private String valueFile;
/**
* Indicates if the token should be located with regular expressions.
* This should be set to false if the token contains regex characters which may miss the desired tokens or even replace the wrong tokens.
*
* @parameter expression=""
*/
private boolean regex = true;
/**
* Output to another file.
* The input file is read and the final output (after replacing tokens) is written to this file.
* The path and file are created if it does not exist.
* If it does exist, the contents are overwritten.
* You should not use outputFile when using a list of includes.
*
* @parameter expression=""
*/
private String outputFile;
/**
* Output to another dir.
* Destination directory relative to the execution directory for all replaced files to be written to.
* Use with outputDir to have files written to a specific base location.
*
* @parameter expression=""
*/
private String outputDir;
/**
* Map of tokens and respective values to replace with.
* A file containing tokens and respective values to replace with.
* This file may contain multiple entries to support a single file containing different tokens to have replaced.
* Each token/value pair should be in the format: "token=value" (without quotations).
* If your token contains ='s you must escape the = character to \=. e.g. tok\=en=value
*
* @parameter expression=""
*/
private String tokenValueMap;
/**
* Optional base directory for each file to replace.
* Path to base relative files for replacements from.
* This feature is useful for multi-module projects.
* Default "." which is the default Maven basedir.
*
* @parameter expression="${basedir}"
*/
private String basedir = ".";
/**
* List of standard Java regular expression Pattern flags (see Java Doc).
* Must contain one or more of:
* * CANON_EQ
* * CASE_INSENSITIVE
* * COMMENTS
* * DOTALL
* * LITERAL
* * MULTILINE
* * UNICODE_CASE
* * UNIX_LINES
*
* @parameter expression=""
*/
private List regexFlags;
/**
* List of replacements with token/value pairs.
* Each replacement element to contain sub-elements as token/value pairs.
* Each token within the given file will be replaced by it's respective value.
*
* @parameter expression=""
*/
private List replacements;
/**
* Comments enabled in the tokenValueMapFile.
* Comment lines start with '#'.
* If your token starts with an '#' then you must supply the commentsEnabled parameter and with a value of false.
* Default is true.
*
* @parameter expression=""
*/
private boolean commentsEnabled = true;
/**
* Base directory (appended) to use for outputDir.
* Having this existing but blank will cause the outputDir
* to be based on the execution directory.
*
* @parameter expression=""
*/
private String outputBasedir;
/**
* Parent directory is preserved when replacing files found from includes and
* being written to an outputDir.
* Default is true.
*
* @parameter expression=""
*/
private boolean preserveDir = true;
/**
* Stops printing a summary of files that have had replacements performed upon them when true.
* Default is false.
*
* @parameter expression=""
*/
private boolean quiet = false;
/**
* Unescape tokens and values to Java format.
* e.g. token\n is unescaped to token(carriage return).
* Default is false.
*
* @parameter expression=""
*/
private boolean unescape;
/**
* Add a list of delimiters which are added on either side of tokens to match against.
* You may also use the '' character to place the token in the desired location for matching.
* e.g. @ would match @token@.
* e.g. ${} would match ${token}.
*
* @parameter expression=""
*/
private List delimiters = new ArrayList();
/**
* Variable tokenValueMap. Same as the tokenValueMap but can be an include configuration rather than an outside property file.
* Similar to tokenValueMap but incline configuration inside the pom.
* This parameter may contain multiple entries to support a single file containing different tokens to have replaced.
* Format is comma separated. e.g. token=value,token2=value2
* Comments are not supported.
*
* @parameter expression=""
*/
private String variableTokenValueMap;
/**
* Ignore any errors produced by this plugin such as
* files not being found and continue with the build.
*
* First checks if file exists and exits without attempting to replace anything.
* Only usable with file parameter.
*
* Default is false.
*
* @parameter expression=""
*/
private boolean ignoreErrors;
/**
* X-Path expression for locating node's whose content you wish to replace.
* This is useful if you have the same token appearing in many nodes but
* wish to only replace the contents of one or more of them.
*
* @parameter expression=""
*/
private String xpath;
/**
* File encoding used when reading and writing files.
* Default system encoding used when not specified.
*
* @parameter expression=""
*/
private String encoding;
public ReplacerMojo() {
super();
this.fileUtils = new FileUtils();
this.replacerFactory = new ReplacerFactory();
this.tokenValueMapFactory = new TokenValueMapFactory(fileUtils);
this.fileSelector = new FileSelector();
this.patternFlagsFactory = new PatternFlagsFactory();
this.outputFilenameBuilder = new OutputFilenameBuilder();
this.summaryBuilder = new SummaryBuilder();
this.processor = new ReplacementProcessor(fileUtils, replacerFactory);
}
public ReplacerMojo(FileUtils fileUtils, ReplacementProcessor processor, ReplacerFactory replacerFactory,
TokenValueMapFactory tokenValueMapFactory, FileSelector fileSelector,
PatternFlagsFactory patternFlagsFactory, OutputFilenameBuilder outputFilenameBuilder,
SummaryBuilder summaryBuilder) {
super();
this.fileUtils = fileUtils;
this.processor = processor;
this.replacerFactory = replacerFactory;
this.tokenValueMapFactory = tokenValueMapFactory;
this.fileSelector = fileSelector;
this.patternFlagsFactory = patternFlagsFactory;
this.outputFilenameBuilder = outputFilenameBuilder;
this.summaryBuilder = summaryBuilder;
}
public void execute() throws MojoExecutionException {
fileUtils.setEncoding(encoding);
try {
if (checkFileExists()) {
getLog().info("Ignoring missing file");
return;
}
List replacements = getDelimiterReplacements(buildReplacements());
addIncludesFilesAndExcludedFiles();
if (includes.isEmpty()) {
replaceContents(processor, replacements, file);
return;
}
for (String file : fileSelector.listIncludes(basedir, includes, excludes)) {
replaceContents(processor, replacements, file);
}
} catch (Exception e) {
getLog().error(e.getMessage());
if (!isIgnoreErrors()) {
throw new MojoExecutionException(e.getMessage(), e);
}
} finally {
if (!quiet) {
summaryBuilder.print(getLog());
}
}
}
private boolean checkFileExists() throws MojoExecutionException {
if (ignoreMissingFile && file == null) {
getLog().error(INVALID_IGNORE_MISSING_FILE_MESSAGE);
throw new MojoExecutionException(INVALID_IGNORE_MISSING_FILE_MESSAGE);
}
return ignoreMissingFile && fileUtils.fileNotExists(getBaseDirPrefixedFilename(file));
}
private String getBaseDirPrefixedFilename(String file) {
if (isEmpty(basedir)) {
return file;
}
return basedir + File.separator + file;
}
private void addIncludesFilesAndExcludedFiles() {
if (filesToInclude != null) {
String[] splitFiles = filesToInclude.split(",");
addToList(Arrays.asList(splitFiles), includes);
}
if (filesToExclude != null) {
String[] splitFiles = filesToExclude.split(",");
addToList(Arrays.asList(splitFiles), excludes);
}
}
private void addToList(List toAdds, List destination) {
for (String toAdd : toAdds) {
destination.add(toAdd.trim());
}
}
private void replaceContents(ReplacementProcessor processor, List replacements, String inputFile) throws IOException {
String outputFileName = outputFilenameBuilder.buildFrom(inputFile, this);
try {
processor.replace(replacements, regex, getBaseDirPrefixedFilename(inputFile), outputFileName, patternFlagsFactory.buildFlags(regexFlags));
} catch (PatternSyntaxException e) {
if (!delimiters.isEmpty()) {
getLog().error(String.format(REGEX_PATTERN_WITH_DELIMITERS_MESSAGE, e.getMessage()));
throw e;
}
}
summaryBuilder.add(getBaseDirPrefixedFilename(inputFile), outputFileName, getLog());
}
private List buildReplacements() throws IOException {
if (replacements != null) {
return replacements;
}
if (variableTokenValueMap != null) {
return tokenValueMapFactory.replacementsForVariable(variableTokenValueMap, isCommentsEnabled(), unescape);
}
if (tokenValueMap == null) {
Replacement replacement = new Replacement(fileUtils, token, value, unescape, xpath);
replacement.setTokenFile(tokenFile);
replacement.setValueFile(valueFile);
return Arrays.asList(replacement);
}
return tokenValueMapFactory.replacementsForFile(getBaseDirPrefixedFilename(tokenValueMap), isCommentsEnabled(), unescape);
}
private List getDelimiterReplacements(List replacements) {
if (delimiters.isEmpty()) {
return replacements;
}
List newReplacements = new ArrayList();
for (Replacement replacement : replacements) {
for (DelimiterBuilder delimiter : buildDelimiters()) {
Replacement withDelimiter = Replacement.from(replacement).withDelimiter(delimiter);
newReplacements.add(withDelimiter);
}
}
return newReplacements;
}
private List buildDelimiters() {
List built = new ArrayList();
for (String delimiter : delimiters) {
built.add(new DelimiterBuilder(delimiter));
}
return built;
}
public void setRegex(boolean regex) {
this.regex = regex;
}
public void setFile(String file) {
this.file = file;
}
public String getFile() {
return file;
}
public void setToken(String token) {
this.token = token;
}
public void setValue(String value) {
this.value = value;
}
public void setTokenFile(String tokenFile) {
this.tokenFile = tokenFile;
}
public void setValueFile(String valueFile) {
this.valueFile = valueFile;
}
public void setIgnoreMissingFile(boolean ignoreMissingFile) {
this.ignoreMissingFile = ignoreMissingFile;
}
public void setOutputFile(String outputFile) {
this.outputFile = outputFile;
}
public void setTokenValueMap(String tokenValueMap) {
this.tokenValueMap = tokenValueMap;
}
public void setFilesToInclude(String filesToInclude) {
this.filesToInclude = filesToInclude;
}
public void setFilesToExclude(String filesToExclude) {
this.filesToExclude = filesToExclude;
}
public void setBasedir(String baseDir) {
this.basedir = baseDir;
}
public void setReplacements(List replacements) {
this.replacements = replacements;
}
public void setRegexFlags(List regexFlags) {
this.regexFlags = regexFlags;
}
public void setIncludes(List includes) {
this.includes = includes;
}
public List getIncludes() {
return includes;
}
public void setExcludes(List excludes) {
this.excludes = excludes;
}
public List getExcludes() {
return excludes;
}
public String getFilesToInclude() {
return filesToInclude;
}
public String getFilesToExclude() {
return filesToExclude;
}
public void setOutputDir(String outputDir) {
this.outputDir = outputDir;
}
public boolean isCommentsEnabled() {
return commentsEnabled;
}
public void setCommentsEnabled(boolean commentsEnabled) {
this.commentsEnabled = commentsEnabled;
}
public void setOutputBasedir(String outputBasedir) {
this.outputBasedir = outputBasedir;
}
public boolean isPreserveDir() {
return preserveDir;
}
public void setPreserveDir(boolean preserveDir) {
this.preserveDir = preserveDir;
}
public String getBasedir() {
return basedir;
}
public String getOutputDir() {
return outputDir;
}
public String getOutputBasedir() {
return outputBasedir;
}
public String getOutputFile() {
return outputFile;
}
public void setQuiet(boolean quiet) {
this.quiet = quiet;
}
public void setDelimiters(List delimiters) {
this.delimiters = delimiters;
}
public List getDelimiters() {
return delimiters;
}
public void setUnescape(boolean unescape) {
this.unescape = unescape;
}
public boolean isUnescape() {
return unescape;
}
public void setVariableTokenValueMap(String variableTokenValueMap) {
this.variableTokenValueMap = variableTokenValueMap;
}
public String getVariableTokenValueMap() {
return variableTokenValueMap;
}
public void setIgnoreErrors(boolean ignoreErrors) {
this.ignoreErrors = ignoreErrors;
}
public boolean isIgnoreErrors() {
return ignoreErrors;
}
public void setXpath(String xpath) {
this.xpath = xpath;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy