Skip to content

Instantly share code, notes, and snippets.

Created December 28, 2017 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/5fe2a01e5673e92beb8bd05d5b96cf7e to your computer and use it in GitHub Desktop.
Save anonymous/5fe2a01e5673e92beb8bd05d5b96cf7e to your computer and use it in GitHub Desktop.
// org.apache.maven.shared.filtering/
package org.apache.maven.shared.filtering;
import org.codehaus.plexus.component.annotations.Component;
@Component( role = MavenResourcesFiltering.class, hint = "default" )
public class EnforcingResourceFiltering extends DefaultMavenResourcesFiltering {
@Override
public void filterResources(MavenResourcesExecution mavenResourcesExecution) throws MavenFilteringException {
EnforcingFileFilter.ReportingExceptions.clear();
super.filterResources(mavenResourcesExecution);
EnforcingFileFilter.ReportingExceptions.throwEm();
}
}
package org.apache.maven.shared.filtering;
import java.io.File;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import javax.annotation.Nonnull;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;
import org.apache.maven.shared.utils.io.FileUtils;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.interpolation.AbstractValueSource;
import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
import org.codehaus.plexus.interpolation.Interpolator;
import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
import org.codehaus.plexus.interpolation.RecursionInterceptor;
import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor;
import org.codehaus.plexus.interpolation.SingleResponseValueSource;
import org.codehaus.plexus.interpolation.ValueSource;
import org.codehaus.plexus.interpolation.multi.MultiDelimiterStringSearchInterpolator;
@Component(role = org.apache.maven.shared.filtering.MavenFileFilter.class, hint = "default")
public class EnforcingFileFilter extends DefaultMavenFileFilter {
@Override
public void copyFile(File from, File to, boolean filtering, List<FileUtils.FilterWrapper> filterWrappers, String encoding, boolean overwrite)
throws MavenFilteringException {
// make a temporary copy of filterWrappers that associate value misses with this file
List<FileUtils.FilterWrapper> tempWrappers = new ArrayList<FileUtils.FilterWrapper>(filterWrappers.size());
List<ReportingWrapper> repRapperz = new ArrayList<ReportingWrapper>(filterWrappers.size());
for (FileUtils.FilterWrapper fw : filterWrappers) {
final ReportingWrapper e = new ReportingWrapper(fw);
tempWrappers.add(e);
repRapperz.add(e);
}
super.copyFile(from, to, filtering, tempWrappers, encoding, overwrite);
// harvest the info
Set<String> combined = new HashSet<String>();
for (ReportingWrapper rapper : repRapperz) {
combined.addAll(rapper.rvs.notFound);
}
if (combined.size() > 0) {
List<ReportingExceptions> reportingExceptions = ReportingExceptions.collector.get();
if (reportingExceptions == null) {
reportingExceptions = new ArrayList<ReportingExceptions>();
ReportingExceptions.collector.set(reportingExceptions);
}
reportingExceptions.add(new ReportingExceptions(from, combined));
}
}
public static class ReportingExceptions {
private static ThreadLocal<List<ReportingExceptions>> collector = new ThreadLocal<List<ReportingExceptions>>();
private File f;
private Set<String> notFound;
public static void clear() {
collector.remove();
}
public static void throwEm() throws MavenFilteringException {
if (collector.get() != null) {
if (collector.get().size() > 0) {
StringBuilder sb = new StringBuilder();
sb.append("Filtering problem(s):\n");
for (ReportingExceptions res : collector.get()) {
sb.append(String.format("File %s - unresolved parameters: %s\n", res.f.toString(), join(res.notFound, ", ")));
}
throw new MavenFilteringException(sb.toString());
}
}
}
public ReportingExceptions(File f, Set<String> notFound) {
this.f = f;
this.notFound = notFound;
}
}
private class ReportingWrapper extends FileUtils.FilterWrapper {
private FileUtils.FilterWrapper delegate;
private ReportingValueSource rvs;
public ReportingWrapper(FileUtils.FilterWrapper delegate) {
this.delegate = delegate;
this.rvs = new ReportingValueSource(((Wrapper) delegate).propertiesValueSource);
((Wrapper) delegate).propertiesValueSource = this.rvs;
}
public Reader getReader(Reader fileReader) {
return delegate.getReader(fileReader);
}
}
private static class ReportingValueSource extends AbstractValueSource {
private ValueSource vs;
private Set<String> notFound = new HashSet<String>();
protected ReportingValueSource(ValueSource vs) {
super(true);
this.vs = vs;
}
public Object getValue(String s) {
try {
final Object value = vs.getValue(s);
if (value == null) {
notFound.add(s);
this.addFeedback(String.format("Unable to find value for <%s>", s));
}
return value;
} catch (RuntimeException e) {
notFound.add(s);
this.addFeedback(String.format("Unable to find value for <%s>", s), e);
throw e;
}
}
}
public static String join(Collection<?> col, String delim) {
StringBuilder sb = new StringBuilder();
Iterator<?> iter = col.iterator();
if (iter.hasNext()) sb.append(iter.next().toString());
while (iter.hasNext()) {
sb.append(delim);
sb.append(iter.next().toString());
}
return sb.toString();
}
// DOWN FROM HERE IS C/P DUE TO PRIVATE
@Override
@Nonnull
public List<FileUtils.FilterWrapper> getDefaultFilterWrappers(final AbstractMavenFilteringRequest req) throws MavenFilteringException {
// backup values
boolean supportMultiLineFiltering = req.isSupportMultiLineFiltering();
// compensate for null parameter value.
final AbstractMavenFilteringRequest request = req == null ? new MavenFileFilterRequest() : req;
request.setSupportMultiLineFiltering(supportMultiLineFiltering);
// Here we build some properties which will be used to read some properties files
// to interpolate the expression ${ } in this properties file
// Take a copy of filterProperties to ensure that evaluated filterTokens are not propagated
// to subsequent filter files. Note: this replicates current behaviour and seems to make sense.
final Properties baseProps = new Properties();
// Project properties
if (request.getMavenProject() != null) {
baseProps.putAll(request.getMavenProject().getProperties() == null ? Collections.emptyMap() : request.getMavenProject().getProperties());
}
// TODO this is NPE free but do we consider this as normal
// or do we have to throw an MavenFilteringException with mavenSession cannot be null
//
// khmarbaise: 2016-05-21:
// If we throw an MavenFilteringException tests will fail which is
// caused by for example:
// void copyFile( File from, final File to, boolean filtering, List<FileUtils.FilterWrapper> filterWrappers,
// String encoding )
// in MavenFileFilter interface where no MavenSession is given.
// So changing here to throw a MavenFilteringException would make
// it necessary to change the interface or we need to find a better solution.
//
if (request.getMavenSession() != null) {
// User properties have precedence over system properties
baseProps.putAll(request.getMavenSession().getSystemProperties());
baseProps.putAll(request.getMavenSession().getUserProperties());
}
// now we build properties to use for resources interpolation
final Properties filterProperties = new Properties();
File basedir = request.getMavenProject() != null ? request.getMavenProject().getBasedir() : new File(".");
loadProperties(filterProperties, basedir, request.getFileFilters(), baseProps);
if (filterProperties.size() < 1) {
filterProperties.putAll(baseProps);
}
if (request.getMavenProject() != null) {
if (request.isInjectProjectBuildFilters()) {
List<String> buildFilters = new ArrayList<String>(request.getMavenProject().getBuild().getFilters());
// JDK-8015656: (coll) unexpected NPE from removeAll
if (request.getFileFilters() != null) {
buildFilters.removeAll(request.getFileFilters());
}
loadProperties(filterProperties, basedir, buildFilters, baseProps);
}
// Project properties
filterProperties.putAll(request.getMavenProject().getProperties() == null ? Collections.emptyMap() : request.getMavenProject().getProperties());
}
if (request.getMavenSession() != null) {
// User properties have precedence over system properties
filterProperties.putAll(request.getMavenSession().getSystemProperties());
filterProperties.putAll(request.getMavenSession().getUserProperties());
}
if (request.getAdditionalProperties() != null) {
// additional properties wins
filterProperties.putAll(request.getAdditionalProperties());
}
List<FileUtils.FilterWrapper> defaultFilterWrappers =
request == null ? new ArrayList<FileUtils.FilterWrapper>(1) : new ArrayList<FileUtils.FilterWrapper>(request.getDelimiters().size() + 1);
if (getLogger().isDebugEnabled()) {
getLogger().debug("properties used " + filterProperties);
}
final ValueSource propertiesValueSource = new PropertiesBasedValueSource(filterProperties);
if (request != null) {
FileUtils.FilterWrapper wrapper =
new Wrapper(
request.getDelimiters(),
request.getMavenProject(),
request.getMavenSession(),
propertiesValueSource,
request.getProjectStartExpressions(),
request.getEscapeString(),
request.isEscapeWindowsPaths(),
request.isSupportMultiLineFiltering());
defaultFilterWrappers.add(wrapper);
}
return defaultFilterWrappers;
}
private final class Wrapper extends FileUtils.FilterWrapper {
private LinkedHashSet<String> delimiters;
private MavenProject project;
private ValueSource propertiesValueSource;
private List<String> projectStartExpressions;
private String escapeString;
private boolean escapeWindowsPaths;
private final MavenSession mavenSession;
private boolean supportMultiLineFiltering;
Wrapper(
LinkedHashSet<String> delimiters,
MavenProject project,
MavenSession mavenSession,
ValueSource propertiesValueSource,
List<String> projectStartExpressions,
String escapeString,
boolean escapeWindowsPaths,
boolean supportMultiLineFiltering) {
super();
this.delimiters = delimiters;
this.project = project;
this.mavenSession = mavenSession;
this.propertiesValueSource = propertiesValueSource;
this.projectStartExpressions = projectStartExpressions;
this.escapeString = escapeString;
this.escapeWindowsPaths = escapeWindowsPaths;
this.supportMultiLineFiltering = supportMultiLineFiltering;
}
public Reader getReader(Reader reader) {
Interpolator interpolator =
createInterpolator(delimiters, projectStartExpressions, propertiesValueSource, project, mavenSession, escapeString, escapeWindowsPaths);
MultiDelimiterInterpolatorFilterReaderLineEnding filterReader =
new MultiDelimiterInterpolatorFilterReaderLineEnding(reader, interpolator, supportMultiLineFiltering);
final RecursionInterceptor ri;
if (projectStartExpressions != null && !projectStartExpressions.isEmpty()) {
ri = new PrefixAwareRecursionInterceptor(projectStartExpressions, true);
} else {
ri = new SimpleRecursionInterceptor();
}
filterReader.setRecursionInterceptor(ri);
filterReader.setDelimiterSpecs(delimiters);
filterReader.setInterpolateWithPrefixPattern(false);
filterReader.setEscapeString(escapeString);
return filterReader;
}
}
private static Interpolator createInterpolator(
LinkedHashSet<String> delimiters,
List<String> projectStartExpressions,
ValueSource propertiesValueSource,
MavenProject project,
MavenSession mavenSession,
String escapeString,
boolean escapeWindowsPaths) {
MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator();
interpolator.setDelimiterSpecs(delimiters);
interpolator.addValueSource(propertiesValueSource);
if (project != null) {
interpolator.addValueSource(new PrefixedObjectValueSource(projectStartExpressions, project, true));
}
if (mavenSession != null) {
interpolator.addValueSource(new PrefixedObjectValueSource("session", mavenSession));
final Settings settings = mavenSession.getSettings();
if (settings != null) {
interpolator.addValueSource(new PrefixedObjectValueSource("settings", settings));
interpolator.addValueSource(new SingleResponseValueSource("localRepository", settings.getLocalRepository()));
}
}
interpolator.setEscapeString(escapeString);
if (escapeWindowsPaths) {
interpolator.addPostProcessor(
new InterpolationPostProcessor() {
public Object execute(String expression, Object value) {
if (value instanceof String) {
return FilteringUtils.escapeWindowsPath((String) value);
}
return value;
}
});
}
return interpolator;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment