From 229f4d79836b20a17dd8291e3734fae8c982b811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Boutemy?= Date: Sun, 3 May 2020 13:52:21 +0200 Subject: [PATCH] [MSHADE-363] add ReproducibleResourceTransformer to keep compatibility --- .../maven/plugins/shade/DefaultShader.java | 28 +++++++---- .../AbstractCompatibilityTransformer.java | 39 +++++++++++++++ .../ApacheLicenseResourceTransformer.java | 2 +- .../ApacheNoticeResourceTransformer.java | 2 +- .../shade/resource/AppendingTransformer.java | 2 +- .../ComponentsXmlResourceTransformer.java | 2 +- .../DontIncludeResourceTransformer.java | 2 +- .../resource/GroovyResourceTransformer.java | 2 +- .../resource/IncludeResourceTransformer.java | 2 +- .../resource/ManifestResourceTransformer.java | 2 +- .../PluginXmlResourceTransformer.java | 2 +- .../ReproducibleResourceTransformer.java | 49 +++++++++++++++++++ .../ResourceBundleAppendingTransformer.java | 2 +- .../shade/resource/ResourceTransformer.java | 4 +- .../resource/ServicesResourceTransformer.java | 2 +- .../resource/XmlAppendingTransformer.java | 2 +- .../properties/PropertiesTransformer.java | 11 ++++- .../resource/rule/TransformerTesterRule.java | 23 +++++---- 18 files changed, 142 insertions(+), 36 deletions(-) create mode 100644 src/main/java/org/apache/maven/plugins/shade/resource/AbstractCompatibilityTransformer.java create mode 100644 src/main/java/org/apache/maven/plugins/shade/resource/ReproducibleResourceTransformer.java diff --git a/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java b/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java index 15712ad6..6f3c4e6b 100644 --- a/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java +++ b/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java @@ -49,6 +49,7 @@ import org.apache.maven.plugins.shade.filter.Filter; import org.apache.maven.plugins.shade.relocation.Relocator; import org.apache.maven.plugins.shade.resource.ManifestResourceTransformer; +import org.apache.maven.plugins.shade.resource.ReproducibleResourceTransformer; import org.apache.maven.plugins.shade.resource.ResourceTransformer; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.logging.AbstractLogEnabled; @@ -76,7 +77,7 @@ public void shade( ShadeRequest shadeRequest ) { Set resources = new HashSet<>(); - ResourceTransformer manifestTransformer = null; + ManifestResourceTransformer manifestTransformer = null; List transformers = new ArrayList<>( shadeRequest.getResourceTransformers() ); for ( Iterator it = transformers.iterator(); it.hasNext(); ) @@ -84,7 +85,7 @@ public void shade( ShadeRequest shadeRequest ) ResourceTransformer transformer = it.next(); if ( transformer instanceof ManifestResourceTransformer ) { - manifestTransformer = transformer; + manifestTransformer = (ManifestResourceTransformer) transformer; it.remove(); } } @@ -265,11 +266,11 @@ else if ( shadeRequest.isShadeSourcesContent() && name.endsWith( ".java" ) ) } private void goThroughAllJarEntriesForManifestTransformer( ShadeRequest shadeRequest, Set resources, - ResourceTransformer resourceTransformer, + ManifestResourceTransformer manifestTransformer, JarOutputStream jos ) throws IOException { - if ( resourceTransformer != null ) + if ( manifestTransformer != null ) { for ( File jar : shadeRequest.getJars() ) { @@ -279,22 +280,22 @@ private void goThroughAllJarEntriesForManifestTransformer( ShadeRequest shadeReq { JarEntry entry = en.nextElement(); String resource = entry.getName(); - if ( resourceTransformer.canTransformResource( resource ) ) + if ( manifestTransformer.canTransformResource( resource ) ) { resources.add( resource ); try ( InputStream inputStream = jarFile.getInputStream( entry ) ) { - resourceTransformer.processResource( resource, inputStream, - shadeRequest.getRelocators(), entry.getTime() ); + manifestTransformer.processResource( resource, inputStream, + shadeRequest.getRelocators(), entry.getTime() ); } break; } } } } - if ( resourceTransformer.hasTransformedResource() ) + if ( manifestTransformer.hasTransformedResource() ) { - resourceTransformer.modifyOutputStream( jos ); + manifestTransformer.modifyOutputStream( jos ); } } } @@ -544,7 +545,14 @@ private boolean resourceTransformed( List resourceTransform { getLogger().debug( "Transforming " + name + " using " + transformer.getClass().getName() ); - transformer.processResource( name, is, relocators, time ); + if ( transformer instanceof ReproducibleResourceTransformer ) + { + ( (ReproducibleResourceTransformer) transformer ).processResource( name, is, relocators, time ); + } + else + { + transformer.processResource( name, is, relocators ); + } resourceTransformed = true; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/AbstractCompatibilityTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/AbstractCompatibilityTransformer.java new file mode 100644 index 00000000..392ddb96 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/shade/resource/AbstractCompatibilityTransformer.java @@ -0,0 +1,39 @@ +package org.apache.maven.plugins.shade.resource; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.apache.maven.plugins.shade.relocation.Relocator; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +/** + * An abstract class to implement once the old non-reproducible ResourceTransformer API. + */ +abstract class AbstractCompatibilityTransformer + implements ReproducibleResourceTransformer +{ + public final void processResource( String resource, InputStream is, List relocators ) + throws IOException + { + processResource( resource, is, relocators, 0 ); + } +} diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformer.java index 6fd7931b..524ffdde 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformer.java @@ -30,7 +30,7 @@ * Prevents duplicate copies of the license */ public class ApacheLicenseResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { private static final String LICENSE_PATH = "META-INF/LICENSE"; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformer.java index 173d1d93..e75062b1 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformer.java @@ -43,7 +43,7 @@ * Merges META-INF/NOTICE.TXT files. */ public class ApacheNoticeResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { Set entries = new LinkedHashSet<>(); diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/AppendingTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/AppendingTransformer.java index 61556eb4..c3cc937c 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/AppendingTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/AppendingTransformer.java @@ -33,7 +33,7 @@ * A resource processor that appends content for a resource, separated by a newline. */ public class AppendingTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { String resource; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformer.java index b82b0d70..9f836188 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformer.java @@ -42,7 +42,7 @@ * A resource processor that aggregates plexus components.xml files. */ public class ComponentsXmlResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { private Map components = new LinkedHashMap<>(); diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/DontIncludeResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/DontIncludeResourceTransformer.java index bfd1f0e5..e1b7bc2d 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/DontIncludeResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/DontIncludeResourceTransformer.java @@ -32,7 +32,7 @@ * resource into the shaded JAR. */ public class DontIncludeResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { String resource; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/GroovyResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/GroovyResourceTransformer.java index f54c0cb7..1a8d61d4 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/GroovyResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/GroovyResourceTransformer.java @@ -36,7 +36,7 @@ * Aggregate Apache Groovy extension modules descriptors */ public class GroovyResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { static final String EXT_MODULE_NAME_LEGACY = "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule"; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/IncludeResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/IncludeResourceTransformer.java index ab360d13..dfe3326b 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/IncludeResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/IncludeResourceTransformer.java @@ -35,7 +35,7 @@ * content into the shaded JAR. */ public class IncludeResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { File file; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformer.java index 6bf711bb..b66c73a3 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformer.java @@ -41,7 +41,7 @@ * @since 1.2 */ public class ManifestResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { private final List defaultAttributes = Arrays.asList( "Export-Package", "Import-Package", diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/PluginXmlResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/PluginXmlResourceTransformer.java index 9392b53a..0cbb3fae 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/PluginXmlResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/PluginXmlResourceTransformer.java @@ -44,7 +44,7 @@ * @since 3.0 */ public class PluginXmlResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { private List mojos = new ArrayList<>(); diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ReproducibleResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ReproducibleResourceTransformer.java new file mode 100644 index 00000000..eb660320 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ReproducibleResourceTransformer.java @@ -0,0 +1,49 @@ +package org.apache.maven.plugins.shade.resource; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.apache.maven.plugins.shade.relocation.Relocator; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +/** + * Transform resource ensuring reproducible output: that requires to get the timestamp of + * the initial resources to define in a reproducible way the timestamp of the transformed + * resource. + * + * @author Hervé Boutemy + * @since 3.2.4 + */ +public interface ReproducibleResourceTransformer + extends ResourceTransformer +{ + /** + * Transform an individual resource + * @param resource The resource name + * @param is An input stream for the resource, the implementation should *not* close this stream + * @param relocators A list of relocators + * @param time the time of the resource to process + * @throws IOException When the IO blows up + */ + void processResource( String resource, InputStream is, List relocators, long time ) + throws IOException; +} diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ResourceBundleAppendingTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ResourceBundleAppendingTransformer.java index 77223ee5..5ea56cfd 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/ResourceBundleAppendingTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ResourceBundleAppendingTransformer.java @@ -39,7 +39,7 @@ * @since 3.0.0 */ public class ResourceBundleAppendingTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { private Map dataMap = new HashMap<>(); diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ResourceTransformer.java index bb4400ad..7b766667 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/ResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ResourceTransformer.java @@ -36,10 +36,10 @@ public interface ResourceTransformer * @param resource The resource name * @param is An input stream for the resource, the implementation should *not* close this stream * @param relocators A list of relocators - * @param time the time of the resource to process * @throws IOException When the IO blows up + * @deprecated prefer ReproducibleResourceTransformer */ - void processResource( String resource, InputStream is, List relocators, long time ) + void processResource( String resource, InputStream is, List relocators ) throws IOException; boolean hasTransformedResource(); diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/ServicesResourceTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/ServicesResourceTransformer.java index 929c5fa7..b2f5dd68 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/ServicesResourceTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/ServicesResourceTransformer.java @@ -46,7 +46,7 @@ * shading process. */ public class ServicesResourceTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { private static final String SERVICES_PATH = "META-INF/services"; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/XmlAppendingTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/XmlAppendingTransformer.java index 608c1a23..f5f6ac8f 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/XmlAppendingTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/XmlAppendingTransformer.java @@ -44,7 +44,7 @@ * Appends multiple occurrences of some XML file. */ public class XmlAppendingTransformer - implements ResourceTransformer + extends AbstractCompatibilityTransformer { public static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance"; diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/properties/PropertiesTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/properties/PropertiesTransformer.java index 8040923d..9b927973 100644 --- a/src/main/java/org/apache/maven/plugins/shade/resource/properties/PropertiesTransformer.java +++ b/src/main/java/org/apache/maven/plugins/shade/resource/properties/PropertiesTransformer.java @@ -32,7 +32,7 @@ import java.util.jar.JarOutputStream; import org.apache.maven.plugins.shade.relocation.Relocator; -import org.apache.maven.plugins.shade.resource.ResourceTransformer; +import org.apache.maven.plugins.shade.resource.ReproducibleResourceTransformer; import org.apache.maven.plugins.shade.resource.properties.io.NoCloseOutputStream; import org.apache.maven.plugins.shade.resource.properties.io.SkipPropertiesDateLineWriter; @@ -42,7 +42,7 @@ * @since 3.2.2 */ public class PropertiesTransformer - implements ResourceTransformer + implements ReproducibleResourceTransformer { private String resource; private String alreadyMergedKey; @@ -73,6 +73,13 @@ public boolean canTransformResource( final String resource ) return Objects.equals( resource, this.resource ); } + @Override + public final void processResource( String resource, InputStream is, List relocators ) + throws IOException + { + processResource( resource, is, relocators, 0 ); + } + @Override public void processResource( final String resource, final InputStream is, final List relocators, long time ) diff --git a/src/test/java/org/apache/maven/plugins/shade/resource/rule/TransformerTesterRule.java b/src/test/java/org/apache/maven/plugins/shade/resource/rule/TransformerTesterRule.java index 1eaf2b1b..c1598418 100644 --- a/src/test/java/org/apache/maven/plugins/shade/resource/rule/TransformerTesterRule.java +++ b/src/test/java/org/apache/maven/plugins/shade/resource/rule/TransformerTesterRule.java @@ -39,7 +39,7 @@ import java.util.jar.JarOutputStream; import org.apache.maven.plugins.shade.relocation.Relocator; -import org.apache.maven.plugins.shade.resource.ResourceTransformer; +import org.apache.maven.plugins.shade.resource.ReproducibleResourceTransformer; import org.codehaus.plexus.component.configurator.ComponentConfigurationException; import org.codehaus.plexus.component.configurator.converters.ConfigurationConverter; import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; @@ -51,7 +51,8 @@ import org.junit.runner.Description; import org.junit.runners.model.Statement; -public class TransformerTesterRule implements TestRule +public class TransformerTesterRule + implements TestRule { @Override public Statement apply( final Statement base, final Description description ) @@ -71,9 +72,9 @@ public void evaluate() throws Throwable final Map jar; try { - final ResourceTransformer transformer = createTransformer(spec); - visit(spec, transformer); - jar = captureOutput(transformer); + final ReproducibleResourceTransformer transformer = createTransformer( spec ); + visit( spec, transformer ); + jar = captureOutput( transformer ); } catch ( final Exception ex ) { @@ -110,7 +111,8 @@ private void asserts( final TransformerTest spec, final Map jar) } } - private Map captureOutput(final ResourceTransformer transformer ) throws IOException + private Map captureOutput( final ReproducibleResourceTransformer transformer ) + throws IOException { final ByteArrayOutputStream out = new ByteArrayOutputStream(); try ( final JarOutputStream jar = new JarOutputStream( out ) ) @@ -130,11 +132,12 @@ private Map captureOutput(final ResourceTransformer transformer return created; } - private void visit( final TransformerTest spec, final ResourceTransformer transformer ) throws IOException + private void visit( final TransformerTest spec, final ReproducibleResourceTransformer transformer ) + throws IOException { for ( final Resource resource : spec.visited() ) { - if ( transformer.canTransformResource( resource.path() )) + if ( transformer.canTransformResource( resource.path() ) ) { transformer.processResource( resource.path(), @@ -156,7 +159,7 @@ private String read(final JarInputStream jar) throws IOException return builder.toString(); } - private ResourceTransformer createTransformer(final TransformerTest spec) + private ReproducibleResourceTransformer createTransformer(final TransformerTest spec) { final ConverterLookup lookup = new DefaultConverterLookup(); try @@ -167,7 +170,7 @@ private ResourceTransformer createTransformer(final TransformerTest spec) { configuration.addChild( property.name(), property.value() ); } - return ResourceTransformer.class.cast( + return ReproducibleResourceTransformer.class.cast( converter.fromConfiguration( lookup, configuration, spec.transformer(), spec.transformer(), Thread.currentThread().getContextClassLoader(), new DefaultExpressionEvaluator() ) );