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