From 1840449b2cb73de77843fa5277ffec6f4d686b2f Mon Sep 17 00:00:00 2001 From: Romain Manni-Bucau Date: Thu, 5 Mar 2020 14:21:19 +0100 Subject: [PATCH] MSHADE-353 adding a generic relocation friendly transformer delegating to other transformers the actual processing --- .../resource/BaseRelocatingTransformer.java | 46 ++++++++ .../resource/ManifestResourceTransformer.java | 18 +-- .../shade/resource/RelocationTransformer.java | 106 ++++++++++++++++++ .../apt/examples/resource-transformers.apt.vm | 43 ++++++- .../resource/RelocationTransformerTest.java | 75 +++++++++++++ 5 files changed, 270 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/apache/maven/plugins/shade/resource/BaseRelocatingTransformer.java create mode 100644 src/main/java/org/apache/maven/plugins/shade/resource/RelocationTransformer.java create mode 100644 src/test/java/org/apache/maven/plugins/shade/resource/RelocationTransformerTest.java diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/BaseRelocatingTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/BaseRelocatingTransformer.java new file mode 100644 index 00000000..4e57aeee --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/shade/resource/BaseRelocatingTransformer.java @@ -0,0 +1,46 @@ +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 java.util.List; + +import org.apache.maven.plugins.shade.relocation.Relocator; + +/** + * Abstract class providing the needed logic to relocate any content. + */ +public abstract class BaseRelocatingTransformer implements ResourceTransformer +{ + protected String relocate( String originalValue, List relocators ) + { + String newValue = originalValue; + for ( Relocator relocator : relocators ) + { + String value; + do + { + value = newValue; + newValue = relocator.relocateClass( value ); + } + while ( !value.equals( newValue ) ); + } + return newValue; + } +} 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 688078cf..82b98e7d 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 BaseRelocatingTransformer { private final List defaultAttributes = Arrays.asList( "Export-Package", "Import-Package", @@ -163,20 +163,4 @@ public void modifyOutputStream( JarOutputStream jos ) jos.putNextEntry( new JarEntry( JarFile.MANIFEST_NAME ) ); manifest.write( jos ); } - - private String relocate( String originalValue, List relocators ) - { - String newValue = originalValue; - for ( Relocator relocator : relocators ) - { - String value; - do - { - value = newValue; - newValue = relocator.relocateClass( value ); - } - while ( !value.equals( newValue ) ); - } - return newValue; - } } diff --git a/src/main/java/org/apache/maven/plugins/shade/resource/RelocationTransformer.java b/src/main/java/org/apache/maven/plugins/shade/resource/RelocationTransformer.java new file mode 100644 index 00000000..40acb9df --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/shade/resource/RelocationTransformer.java @@ -0,0 +1,106 @@ +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 java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.List; +import java.util.jar.JarOutputStream; + +import org.apache.maven.plugins.shade.relocation.Relocator; +import org.codehaus.plexus.util.IOUtil; + +/** + * Trivial transformer applying relocators on resources content. + */ +public class RelocationTransformer extends BaseRelocatingTransformer +{ + private Collection delegates; + private boolean transformed; + + @Override + public boolean canTransformResource( String resource ) + { + if ( delegates == null ) + { + return false; + } + for ( ResourceTransformer transformer : delegates ) + { + if ( transformer.canTransformResource( resource ) ) + { + return true; + } + } + return false; + } + + @Override + public void processResource( String resource, InputStream is, List relocators ) throws IOException + { + byte[] relocated = null; + for ( ResourceTransformer transformer : delegates ) + { + if ( transformer.canTransformResource( resource ) ) + { + transformed = true; + if ( relocated == null ) + { + relocated = relocate( IOUtil.toString( is ), relocators ) + .getBytes( StandardCharsets.UTF_8 ); + } + transformer.processResource( + resource, + new ByteArrayInputStream( relocated ), + relocators ); + } + } + } + + @Override + public boolean hasTransformedResource() + { + return transformed; + } + + @Override + public void modifyOutputStream( JarOutputStream os ) throws IOException + { + if ( !transformed ) + { + return; + } + for ( ResourceTransformer transformer : delegates ) + { + if ( transformer.hasTransformedResource() ) + { + transformer.modifyOutputStream( os ); + } + } + } + + public void setDelegates( Collection delegates ) + { + this.delegates = delegates; + } +} diff --git a/src/site/apt/examples/resource-transformers.apt.vm b/src/site/apt/examples/resource-transformers.apt.vm index 1482baa4..1a20fdc5 100644 --- a/src/site/apt/examples/resource-transformers.apt.vm +++ b/src/site/apt/examples/resource-transformers.apt.vm @@ -55,7 +55,9 @@ Resource Transformers *-----------------------------------------+------------------------------------------+ | {{PropertiesTransformer}} | Merges properties files owning an ordinal to solve conflicts | *-----------------------------------------+------------------------------------------+ -| {{ResourceBundleAppendingTransformer}} | Merges ResourceBundles | +| {{RelocationTransformer}} | Delegates the processing to other transformers but relocating the resource contents | +*-----------------------------------------+------------------------------------------+ +| {{ResourceBundleAppendingTransformer}} | Merges ResourceBundles | *-----------------------------------------+------------------------------------------+ | {{ServicesResourceTransformer}} | Relocated class names in <<>> resources and merges them. | *-----------------------------------------+------------------------------------------+ @@ -601,6 +603,45 @@ Transformers in <<>> +----- +* Relocating file content with {RelocationTransformer} + + The <<>> allows to apply relocators before delegating the processing to other transformers. + ++----- + + ... + + + + org.apache.maven.plugins + maven-shade-plugin + ${project.version} + + + + shade + + + + + + + configuration/application.properties + ordinal + + + + + + + + + + + ... + ++----- + * Merging Apache OpenWebBeans configuration with {OpenWebBeansPropertiesTransformer} <<>> preconfigure a <<>> diff --git a/src/test/java/org/apache/maven/plugins/shade/resource/RelocationTransformerTest.java b/src/test/java/org/apache/maven/plugins/shade/resource/RelocationTransformerTest.java new file mode 100644 index 00000000..b860bd37 --- /dev/null +++ b/src/test/java/org/apache/maven/plugins/shade/resource/RelocationTransformerTest.java @@ -0,0 +1,75 @@ +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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; + +import org.apache.maven.plugins.shade.relocation.Relocator; +import org.apache.maven.plugins.shade.relocation.SimpleRelocator; +import org.codehaus.plexus.util.IOUtil; +import org.junit.Test; + +/** + * Ensure the relation transformer uses relocators. + */ +public class RelocationTransformerTest +{ + @Test + public void relocate() throws IOException + { + AppendingTransformer delegate = new AppendingTransformer(); + delegate.resource = "foo/bar.txt"; + + RelocationTransformer resourceTransformer = new RelocationTransformer(); + resourceTransformer.setDelegates( Collections.singletonList( delegate ) ); + + assertTrue( resourceTransformer.canTransformResource( "foo/bar.txt" ) ); + resourceTransformer.processResource( + "foo/bar.txt", + new ByteArrayInputStream("a=javax.foo.bar".getBytes( StandardCharsets.UTF_8 )), + Collections.singletonList( new SimpleRelocator( + "javax", "jakarta", null, null ) )); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + try ( JarOutputStream jarOutputStream = new JarOutputStream(out) ) + { + resourceTransformer.modifyOutputStream(jarOutputStream); + } + try ( JarInputStream jarInputStream = new JarInputStream( new ByteArrayInputStream( out.toByteArray() ) )) + { + final JarEntry entry = jarInputStream.getNextJarEntry(); + assertNotNull( entry ); + assertEquals( "foo/bar.txt", entry.getName() ); + assertEquals( "a=jakarta.foo.bar", IOUtil.toString( jarInputStream ).trim() ); + assertNull( jarInputStream.getNextJarEntry() ); + } + } +}