com.ariht.maven.plugins.config.generator.ConfigGeneratorImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of config-generation-maven-plugin Show documentation
Show all versions of config-generation-maven-plugin Show documentation
Generates config and scripts for multiple target environments using
template placeholder substitution from values in multiple filter files.
The newest version!
/*
* Copyright 2014 Software Design Studio Ltd.
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
*
* 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 com.ariht.maven.plugins.config.generator;
import com.ariht.maven.plugins.config.io.FileInfo;
import com.ariht.maven.plugins.config.io.DirectoryDeleter;
import com.ariht.maven.plugins.config.io.DirectoryReader;
import com.ariht.maven.plugins.config.parameters.ConfigGeneratorParameters;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.ConfigurationConverter;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ConfigGeneratorImpl {
private final Log log;
private final ConfigGeneratorParameters configGeneratorParameters;
public ConfigGeneratorImpl(final Log log, final ConfigGeneratorParameters configGeneratorParameters) {
Preconditions.checkNotNull(log);
Preconditions.checkNotNull(configGeneratorParameters);
this.log = log;
this.configGeneratorParameters = configGeneratorParameters;
}
private static final String PATH_SEPARATOR = "/";
private static final String MISSING_PROPERTY_PREFIX = "<<<<<<< ";
private static final String MISSING_PROPERTY_SUFFIX = " >>>>>>>";
private static final String MISSING_PROPERTY_PATTERN = "(?<=" + MISSING_PROPERTY_PREFIX + ").*?(?=" + MISSING_PROPERTY_SUFFIX + ")";
private static final Pattern missingPropertyPattern = Pattern.compile(MISSING_PROPERTY_PATTERN);
/**
* Clear target io and create new scripts and config io.
*/
public void processFiltersIntoTemplates() throws MojoExecutionException, MojoFailureException {
logConfigurationParameters();
new DirectoryDeleter().clearTargetDirectory(configGeneratorParameters.getOutputBasePath(), log);
try {
processTemplatesAndGenerateConfig();
} catch (Exception e) {
log.error("Error generating config: " + String.valueOf(e.getMessage()));
throw new MojoFailureException(e.getMessage(), e);
}
}
/**
* Merge templates with filters to generate config, scripts and property io.
*/
private void processTemplatesAndGenerateConfig() throws Exception {
final DirectoryReader directoryReader = new DirectoryReader(log);
final List filters = directoryReader.readFiles(configGeneratorParameters.getFiltersBasePath(), configGeneratorParameters.getFiltersToIgnore());
for (FileInfo fileInfo : filters) {
fileInfo.lookForExternalFiles(configGeneratorParameters.getExternalFilterBasePaths());
}
final List templates = directoryReader.readFiles(configGeneratorParameters.getTemplatesBasePath(), configGeneratorParameters.getTemplatesToIgnore());
logOutputPath();
// Get list of all properties in all filter io.
final Set allProperties = getAllProperties(filters);
// Collection stores missing properties by file so this can be logged once at the end.
final Map> missingPropertiesByFilename = new LinkedHashMap>();
for (final FileInfo filter : filters) {
final Properties properties = readFilterIntoProperties(filter);
final LinkedHashMap valueMap = Maps.newLinkedHashMap(Maps.fromProperties(properties));
// No point checking for missing properties if all were found in the filter file
boolean missingPropertyFound = false;
for (String missingProperty : Sets.difference(allProperties, valueMap.keySet()).immutableCopy()) {
valueMap.put(missingProperty, MISSING_PROPERTY_PREFIX + missingProperty + MISSING_PROPERTY_SUFFIX);
missingPropertyFound = true;
}
final StrSubstitutor strSubstitutor = new StrSubstitutor(valueMap, configGeneratorParameters.getPropertyPrefix(), configGeneratorParameters.getPropertySuffix());
for (final FileInfo template : templates) {
generateConfig(template, filter, configGeneratorParameters.getOutputBasePath(), strSubstitutor, missingPropertiesByFilename, missingPropertyFound);
}
}
if (!missingPropertiesByFilename.keySet().isEmpty()) {
final StringBuilder sb = new StringBuilder("Missing properties identified:\n");
for (String filename : missingPropertiesByFilename.keySet()) {
sb.append(filename).append(": ");
sb.append(StringUtils.join(missingPropertiesByFilename.get(filename), ", ")).append("\n");
}
log.warn(sb.toString());
if (configGeneratorParameters.isFailOnMissingProperty()) {
throw new MojoExecutionException(sb.toString());
}
}
}
/**
* Read properties from filter file and substitute template place-holders.
*
* Typical output is to .../filter-dir/filter-name-no-extension/template-dir/template.name
*/
private void generateConfig(final FileInfo template,
final FileInfo filter,
final String outputBasePath,
final StrSubstitutor strSubstitutor,
final Map> missingPropertiesByFilename,
final boolean missingPropertyFound) throws IOException, ConfigurationException, MojoFailureException {
final String outputDirectory = createOutputDirectory(template, filter, outputBasePath);
final String templateFilename = template.getFile().getName();
final String outputFilename = FilenameUtils.separatorsToUnix(outputDirectory + templateFilename);
if (configGeneratorParameters.isLogOutput()) {
log.info("Creating : " + StringUtils.replace(outputFilename, outputBasePath, ""));
} else if (log.isDebugEnabled()) {
log.debug("Creating : " + String.valueOf(outputFilename));
}
log.debug("Applying filter : " + filter.toString() + " to template : " + template.toString());
final String rawTemplate = FileUtils.readFileToString(template.getFile());
final String processedTemplate = strSubstitutor.replace(rawTemplate);
// No point in running regex against long strings if properties are all present
if (missingPropertyFound) {
checkForMissingProperties(filter.getFile().getAbsolutePath(), processedTemplate, missingPropertiesByFilename);
}
// Only write out the generated io if there were no errors or errors are specifically ignored
if (StringUtils.isNotBlank(configGeneratorParameters.getEncoding())) {
FileUtils.writeStringToFile(new File(outputFilename), processedTemplate, configGeneratorParameters.getEncoding());
} else {
FileUtils.writeStringToFile(new File(outputFilename), processedTemplate);
}
}
/**
* Check if there are any properties that haven't been substituted and add to map for logging out later.
*/
private void checkForMissingProperties(final String filename,
final String processedTemplate,
final Map> missingPropertiesByFilename) throws MojoFailureException {
final Matcher matcher = missingPropertyPattern.matcher(processedTemplate);
final Set missingProperties = new LinkedHashSet();
while(matcher.find()) {
final String propertyName = matcher.group();
if (!StringUtils.isBlank(propertyName)) {
missingProperties.add(propertyName);
}
}
if (missingProperties.isEmpty()) {
return;
}
for (final String propertyName : missingProperties) {
Set missingPropertiesFromMap = missingPropertiesByFilename.get(filename);
if (missingPropertiesFromMap == null) {
missingPropertiesFromMap = new LinkedHashSet();
missingPropertiesByFilename.put(filename, missingPropertiesFromMap);
}
missingPropertiesFromMap.add(propertyName);
log.info(filename + " : " + propertyName);
}
}
/**
* Compile list of every property in all filter io - used to provide dummy values
* in missing properties identified in set difference check.
*/
private Set getAllProperties(List filters) throws ConfigurationException, IOException {
final Set allProperties = new LinkedHashSet();
for (final FileInfo filter : filters) {
final Properties properties = readFilterIntoProperties(filter);
final ImmutableMap valueMap = Maps.fromProperties(properties);
allProperties.addAll(valueMap.keySet());
}
return allProperties;
}
/**
* Filter io contain the properties we wish to substitute in templates.
*
* Uses Apache Commons Configuration to load filters.
*/
private Properties readFilterIntoProperties(final FileInfo filter) throws ConfigurationException, IOException {
final CompositeConfiguration composite = new CompositeConfiguration();
final List files = filter.getFiles();
for (final File file : files) {
final PropertiesConfiguration config = new PropertiesConfiguration(file);
config.setEncoding(configGeneratorParameters.getEncoding());
composite.addConfiguration(config);
}
if (StringUtils.isNotBlank(configGeneratorParameters.getFilterSourcePropertyName())) {
composite.setProperty(configGeneratorParameters.getFilterSourcePropertyName(), filter.getAllSources());
}
return ConfigurationConverter.getProperties(composite);
}
/**
* Prepare output io: base-path/filter-sub-dir/template-dir/template.name
*/
private String createOutputDirectory(final FileInfo template, final FileInfo filter, final String outputBasePath) throws IOException {
final String outputDirectory = getOutputPath(template, filter, outputBasePath);
final File outputDir = new File(outputDirectory);
if (!outputDir.exists()) {
log.debug("Creating : " + outputDir);
FileUtils.forceMkdir(outputDir);
}
return FilenameUtils.normalize(outputDirectory);
}
/**
* Concatenate filter io with template io
*/
private String getOutputPath(final FileInfo template, final FileInfo filter, final String outputBasePath) {
final String outputPath = outputBasePath + PATH_SEPARATOR
+ filter.getRelativeSubDirectory() + PATH_SEPARATOR
+ filter.getNameWithoutExtension() + PATH_SEPARATOR
+ template.getRelativeSubDirectory() + PATH_SEPARATOR;
return FilenameUtils.separatorsToUnix(FilenameUtils.normalize(outputPath));
}
private void logConfigurationParameters() {
if (StringUtils.isBlank(configGeneratorParameters.getEncoding())) {
configGeneratorParameters.setEncoding(System.getProperty("file.encoding"));
log.warn("File encoding has not been set, using platform encoding '" + configGeneratorParameters.getEncoding()
+ "', i.e. generated config is platform dependent!");
} else if (configGeneratorParameters.isLogOutput()) {
log.debug("Using file encoding '" + configGeneratorParameters.getEncoding() + "' while generating config.");
}
if (configGeneratorParameters.isLogOutput()) {
log.debug("Templates path : " + FilenameUtils.separatorsToUnix(configGeneratorParameters.getTemplatesBasePath()));
log.debug("Filters path : " + FilenameUtils.separatorsToUnix(configGeneratorParameters.getFiltersBasePath()));
log.debug("Output path : " + FilenameUtils.separatorsToUnix(configGeneratorParameters.getOutputBasePath()));
}
}
private void logOutputPath() {
final String outputPathMessage = "Config generation to: " + FilenameUtils.separatorsToUnix(configGeneratorParameters.getOutputBasePath());
if (configGeneratorParameters.isLogOutput()) {
log.info(outputPathMessage);
} else if (log.isDebugEnabled()) {
log.debug(outputPathMessage);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy