You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2020/02/08 11:18:19 UTC
[maven-shade-plugin] branch master updated: [MSHADE-350] Enable
ManifestResourceTransformer to rewrite the manifest with relocations
This is an automated email from the ASF dual-hosted git repository.
rfscholte pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-shade-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new 0aa56da [MSHADE-350] Enable ManifestResourceTransformer to rewrite the manifest with relocations
0aa56da is described below
commit 0aa56da230bd0c86b8ffe7a8e6405b11dce4309a
Author: rfscholte <rf...@apache.org>
AuthorDate: Sat Feb 8 12:18:11 2020 +0100
[MSHADE-350] Enable ManifestResourceTransformer to rewrite the manifest with relocations
---
.../resource/ManifestResourceTransformer.java | 77 +++++++++-
src/site/apt/examples/resource-transformers.apt.vm | 12 ++
.../resource/ManifestResourceTransformerTest.java | 170 +++++++++++++++++++++
3 files changed, 256 insertions(+), 3 deletions(-)
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 fd0bf48..688078c 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
@@ -19,10 +19,9 @@ package org.apache.maven.plugins.shade.resource;
* under the License.
*/
-import org.apache.maven.plugins.shade.relocation.Relocator;
-
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
@@ -31,6 +30,8 @@ import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
+import org.apache.maven.plugins.shade.relocation.Relocator;
+
/**
* A resource processor that allows the arbitrary addition of attributes to
* the first MANIFEST.MF that is found in the set of JARs being processed, or
@@ -42,17 +43,39 @@ import java.util.jar.Manifest;
public class ManifestResourceTransformer
implements ResourceTransformer
{
-
+ private final List<String> defaultAttributes = Arrays.asList( "Export-Package",
+ "Import-Package",
+ "Provide-Capability",
+ "Require-Capability" );
+
// Configuration
private String mainClass;
private Map<String, Object> manifestEntries;
+ private List<String> additionalAttributes;
+
// Fields
private boolean manifestDiscovered;
private Manifest manifest;
+
+ public void setMainClass( String mainClass )
+ {
+ this.mainClass = mainClass;
+ }
+
+ public void setManifestEntries( Map<String, Object> manifestEntries )
+ {
+ this.manifestEntries = manifestEntries;
+ }
+
+ public void setAdditionalAttributes( List<String> additionalAttributes )
+ {
+ this.additionalAttributes = additionalAttributes;
+ }
+ @Override
public boolean canTransformResource( String resource )
{
if ( JarFile.MANIFEST_NAME.equalsIgnoreCase( resource ) )
@@ -63,6 +86,7 @@ public class ManifestResourceTransformer
return false;
}
+ @Override
public void processResource( String resource, InputStream is, List<Relocator> relocators )
throws IOException
{
@@ -72,15 +96,46 @@ public class ManifestResourceTransformer
if ( !manifestDiscovered )
{
manifest = new Manifest( is );
+
+ if ( relocators != null && !relocators.isEmpty() )
+ {
+ final Attributes attributes = manifest.getMainAttributes();
+
+ for ( final String attribute : defaultAttributes )
+ {
+ final String attributeValue = attributes.getValue( attribute );
+ if ( attributeValue != null )
+ {
+ String newValue = relocate( attributeValue, relocators );
+ attributes.putValue( attribute, newValue );
+ }
+ }
+
+ if ( additionalAttributes != null )
+ {
+ for ( final String attribute : additionalAttributes )
+ {
+ final String attributeValue = attributes.getValue( attribute );
+ if ( attributeValue != null )
+ {
+ String newValue = relocate( attributeValue, relocators );
+ attributes.putValue( attribute, newValue );
+ }
+ }
+ }
+ }
+
manifestDiscovered = true;
}
}
+ @Override
public boolean hasTransformedResource()
{
return true;
}
+ @Override
public void modifyOutputStream( JarOutputStream jos )
throws IOException
{
@@ -108,4 +163,20 @@ public class ManifestResourceTransformer
jos.putNextEntry( new JarEntry( JarFile.MANIFEST_NAME ) );
manifest.write( jos );
}
+
+ private String relocate( String originalValue, List<Relocator> 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/site/apt/examples/resource-transformers.apt.vm b/src/site/apt/examples/resource-transformers.apt.vm
index 7248027..1482baa 100644
--- a/src/site/apt/examples/resource-transformers.apt.vm
+++ b/src/site/apt/examples/resource-transformers.apt.vm
@@ -387,6 +387,18 @@ Transformers in <<<org.apache.maven.plugins.shade.resource>>>
* the <<<X-Compile-Target-JDK>>> entry to the value of the <<<maven.compile.target>>> property.
+ By default the <<<ManifestResourceTransformer>>> will relocate the following attributes:
+
+ * Export-Package
+
+ * Import-Package
+
+ * Provide-Capability
+
+ * Require-Capability
+
+ With <<<additionalAttributes>>> you can specify the attributes that need to be relocated too.
+
+-----
<project>
diff --git a/src/test/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformerTest.java b/src/test/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformerTest.java
new file mode 100644
index 0000000..c1c7ff2
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformerTest.java
@@ -0,0 +1,170 @@
+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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.maven.plugins.shade.relocation.Relocator;
+import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ManifestResourceTransformerTest
+{
+ private ManifestResourceTransformer transformer;
+
+ @Before
+ public void setUp()
+ {
+ transformer = new ManifestResourceTransformer();
+ }
+
+ @Test
+ public void rewriteDefaultAttributes() throws Exception
+ {
+ final Manifest manifest = new Manifest();
+ final Attributes attributes = manifest.getMainAttributes();
+ attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ attributes.putValue("Export-Package",
+ "javax.decorator;version=\"2.0\";uses:=\"javax.enterprise.inject\"," +
+ "javax.enterprise.context;version=\"2.0\";uses:=\"javax.enterprise.util,javax.inject\"");
+ attributes.putValue("Import-Package",
+ "javax.el,javax.enterprise.context;version=\"[2.0,3)\"");
+ attributes.putValue("Provide-Capability",
+ "osgi.contract;osgi.contract=JavaCDI;uses:=\"" +
+ "javax.enterprise.context,javax.enterprise.context.spi,javax.enterprise.context.control," +
+ "javax.enterprise.util,javax.enterprise.inject,javax.enterprise.inject.spi," +
+ "javax.enterprise.inject.spi.configurator,javax.enterprise.inject.literal," +
+ "javax.enterprise.inject.se,javax.enterprise.event,javax.decorator\";" +
+ "version:List<Version>=\"2.0,1.2,1.1,1.0\"");
+ attributes.putValue("Require-Capability",
+ "osgi.serviceloader;" +
+ "filter:=\"(osgi.serviceloader=javax.enterprise.inject.se.SeContainerInitializer)\";" +
+ "cardinality:=multiple," +
+ "osgi.serviceloader;" +
+ "filter:=\"(osgi.serviceloader=javax.enterprise.inject.spi.CDIProvider)\";" +
+ "cardinality:=multiple,osgi.extender;" +
+ "filter:=\"(osgi.extender=osgi.serviceloader.processor)\"," +
+ "osgi.contract;osgi.contract=JavaEL;filter:=\"(&(osgi.contract=JavaEL)(version=2.2.0))\"," +
+ "osgi.contract;osgi.contract=JavaInterceptor;" +
+ "filter:=\"(&(osgi.contract=JavaInterceptor)(version=1.2.0))\"," +
+ "osgi.contract;osgi.contract=JavaInject;" +
+ "filter:=\"(&(osgi.contract=JavaInject)(version=1.0.0))\"," +
+ "osgi.ee;filter:=\"(&(osgi.ee=JavaSE)(version=1.8))\"");
+
+ List<Relocator> relocators =
+ Collections.<Relocator>singletonList( new SimpleRelocator( "javax", "jakarta",
+ Collections.<String>emptyList(),
+ Collections.<String>emptyList() ) );
+
+ final ByteArrayOutputStream out = transform( manifest, relocators );
+
+ try ( final JarInputStream jis = new JarInputStream( new ByteArrayInputStream( out.toByteArray() ) ) )
+ {
+ final Attributes attrs = jis.getManifest().getMainAttributes();
+ assertEquals(
+ "jakarta.decorator;version=\"2.0\";uses:=\"jakarta.enterprise.inject\"," +
+ "jakarta.enterprise.context;version=\"2.0\";uses:=\"jakarta.enterprise.util," +
+ "jakarta.inject\"",
+ attrs.getValue("Export-Package"));
+ assertEquals("jakarta.el,jakarta.enterprise.context;version=\"[2.0,3)\"",
+ attrs.getValue("Import-Package"));
+ assertEquals(
+ "osgi.contract;osgi.contract=JavaCDI;" +
+ "uses:=\"jakarta.enterprise.context," +
+ "jakarta.enterprise.context.spi,jakarta.enterprise.context.control," +
+ "jakarta.enterprise.util,jakarta.enterprise.inject,jakarta.enterprise.inject.spi," +
+ "jakarta.enterprise.inject.spi.configurator,jakarta.enterprise.inject.literal," +
+ "jakarta.enterprise.inject.se,jakarta.enterprise.event," +
+ "jakarta.decorator\";version:List<Version>=\"2.0,1.2,1.1,1.0\"",
+ attrs.getValue("Provide-Capability"));
+ assertEquals(
+ "osgi.serviceloader;" +
+ "filter:=\"(osgi.serviceloader=jakarta.enterprise.inject.se.SeContainerInitializer)\";" +
+ "cardinality:=multiple,osgi.serviceloader;" +
+ "filter:=\"(osgi.serviceloader=jakarta.enterprise.inject.spi.CDIProvider)\";" +
+ "cardinality:=multiple,osgi.extender;" +
+ "filter:=\"(osgi.extender=osgi.serviceloader.processor)\"," +
+ "osgi.contract;osgi.contract=JavaEL;filter:=\"(&(osgi.contract=JavaEL)(version=2.2.0))\"," +
+ "osgi.contract;osgi.contract=JavaInterceptor;" +
+ "filter:=\"(&(osgi.contract=JavaInterceptor)(version=1.2.0))\"," +
+ "osgi.contract;osgi.contract=JavaInject;" +
+ "filter:=\"(&(osgi.contract=JavaInject)(version=1.0.0))\"," +
+ "osgi.ee;filter:=\"(&(osgi.ee=JavaSE)(version=1.8))\"",
+ attrs.getValue("Require-Capability"));
+ }
+ }
+
+ @Test
+ public void rewriteAdditionalAttributes() throws Exception
+ {
+ final Manifest manifest = new Manifest();
+ final Attributes attributes = manifest.getMainAttributes();
+ attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ attributes.putValue("description-custom",
+ "This jar uses javax packages");
+
+ List<Relocator> relocators =
+ Collections.<Relocator>singletonList( new SimpleRelocator( "javax", "jakarta",
+ Collections.<String>emptyList(),
+ Collections.<String>emptyList() ) );
+
+ transformer.setAdditionalAttributes( Arrays.asList("description-custom", "attribute-unknown") );
+ final ByteArrayOutputStream out = transform( manifest, relocators );
+
+ try ( final JarInputStream jis = new JarInputStream( new ByteArrayInputStream( out.toByteArray() ) ) )
+ {
+ final Attributes attrs = jis.getManifest().getMainAttributes();
+ assertEquals( "This jar uses jakarta packages", attrs.getValue( "description-custom" ) );
+ }
+ }
+
+ private ByteArrayOutputStream transform( final Manifest manifest, List<Relocator> relocators )
+ throws IOException
+ {
+ final ByteArrayOutputStream mboas = new ByteArrayOutputStream();
+ try ( final OutputStream mos = mboas )
+ {
+ manifest.write( mos );
+ }
+ transformer.processResource( JarFile.MANIFEST_NAME, new ByteArrayInputStream( mboas.toByteArray() ),
+ relocators );
+
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try ( final JarOutputStream jarOutputStream = new JarOutputStream( out ) )
+ {
+ transformer.modifyOutputStream( jarOutputStream );
+ }
+ return out;
+ }
+}
\ No newline at end of file