Created
December 28, 2017 21:21
-
-
Save anonymous/5fe2a01e5673e92beb8bd05d5b96cf7e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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