diff --git a/bnd-plugins/org.eclipse.transformer.bnd.analyzer/src/test/java/org/eclipse/transformer/bnd/analyzer/BndAnalyzerPluginTest.java b/bnd-plugins/org.eclipse.transformer.bnd.analyzer/src/test/java/org/eclipse/transformer/bnd/analyzer/BndAnalyzerPluginTest.java index 059af680..b4e37c4e 100644 --- a/bnd-plugins/org.eclipse.transformer.bnd.analyzer/src/test/java/org/eclipse/transformer/bnd/analyzer/BndAnalyzerPluginTest.java +++ b/bnd-plugins/org.eclipse.transformer.bnd.analyzer/src/test/java/org/eclipse/transformer/bnd/analyzer/BndAnalyzerPluginTest.java @@ -230,6 +230,7 @@ void options_test() throws Exception { try (Processor processor = new Processor()) { processor.setProperty("-transformer", "tb;arg=value1"); processor.setProperty("-transformer.overwrite", "overwrite"); + processor.setProperty("-transformer.stripSignatures", "stripSignatures"); processor.setProperty("-transformer.morebundles", "bundles;arg=value2"); processor.setProperty("-transformer.immediate", "immediate;option=tv;package=org.eclipse.transformer.test.api;version=\"[2.0\\,3.0);Export-Package=2.0.0\""); @@ -253,6 +254,11 @@ void options_test() throws Exception { assertThat(options.getOptionValues(AppOption.WIDEN_ARCHIVE_NESTING)).isNull(); assertThat(options.getOptionValue(AppOption.WIDEN_ARCHIVE_NESTING)).isNull(); + assertThat(options.getDefaultValue(AppOption.STRIP_SIGNATURES)).isNull(); + assertThat(options.hasOption(AppOption.STRIP_SIGNATURES)).isTrue(); + assertThat(options.getOptionValues(AppOption.STRIP_SIGNATURES)).isEmpty(); + assertThat(options.getOptionValue(AppOption.STRIP_SIGNATURES)).isNull(); + assertThat(options.getOptionValues(AppOption.RULES_IMMEDIATE_DATA)).containsExactly("tv", "org.eclipse.transformer.test.api", "[2.0\\,3.0);Export-Package=2.0.0"); } diff --git a/maven-plugins/transformer-maven-plugin/README.md b/maven-plugins/transformer-maven-plugin/README.md index 2138fd57..35765ad6 100644 --- a/maven-plugins/transformer-maven-plugin/README.md +++ b/maven-plugins/transformer-maven-plugin/README.md @@ -51,8 +51,9 @@ A list value of `-` (Hyphen-minus) is ignored. This can be used to configure an |`immediates` | A list of immediate options. | |`invert` | If `true`, invert the rename rules. _Defaults to `false`_. | |`overwrite` | If `true`, the items which transform to the same path as an existing item overwrite the existing item. _Defaults to `false`_. | -|`widen` | If `true`, By default, archive nesting is restricted to JavaEE active locations. This may be relaxed to enable JAR and ZIP within JAR, ZIP within ZIP, and ZIP within EAR, WAR, and RAR. _Defaults to `false`_. | +|`widen` | If `true`, by default, archive nesting is restricted to JavaEE active locations. This may be relaxed to enable JAR and ZIP within JAR, ZIP within ZIP, and ZIP within EAR, WAR, and RAR. _Defaults to `false`_. | |`jakartaDefaults` | If `true`, the Jakarta rule defaults are included. _Defaults to `false`_. | +|`stripSignatures` | If `true`, signature files will be removed from signed JAR files. _Defaults to `false`_. | ```xml diff --git a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/AbstractTransformerMojo.java b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/AbstractTransformerMojo.java index cf5c2029..63bb3fee 100644 --- a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/AbstractTransformerMojo.java +++ b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/AbstractTransformerMojo.java @@ -58,7 +58,7 @@ public abstract class AbstractTransformerMojo extends AbstractMojo { *

* The rules configuration includes: selections, renames, versions, bundles, * directs, texts, perClassConstants, immediates, invert, overwrite, widen, - * and jakartaDefaults. + * jakartaDefaults, and stripSignatures. */ @Parameter private TransformerRules rules = new TransformerRules(); diff --git a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerMojoOptions.java b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerMojoOptions.java index 2dc5fb5b..ee09d92b 100644 --- a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerMojoOptions.java +++ b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerMojoOptions.java @@ -109,6 +109,9 @@ public boolean hasOption(AppOption option) { case WIDEN_ARCHIVE_NESTING : has = rules.isWiden(); break; + case STRIP_SIGNATURES : + has = rules.isStripSignatures(); + break; default : has = TransformOptions.super.hasOption(option); break; diff --git a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerRunMojo.java b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerRunMojo.java index b5b0d8f8..6ae14943 100644 --- a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerRunMojo.java +++ b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/TransformerRunMojo.java @@ -59,6 +59,9 @@ public class TransformerRunMojo extends AbstractMojo { @Parameter(defaultValue = "true", property = "transformer-plugin.overwrite", required = true) private boolean overwrite; + @Parameter(defaultValue = "false", property = "transformer-plugin.stripSignatures", required = false) + private boolean stripSignatures; + @Parameter(defaultValue = "true", property = "transformer-plugin.attach", required = true) private boolean attach; @@ -131,6 +134,8 @@ public boolean hasOption(AppOption option) { return overwrite; case INVERT : return invert; + case STRIP_SIGNATURES: + return stripSignatures; default : return TransformOptions.super.hasOption(option); } @@ -257,4 +262,7 @@ void setAttach(boolean attach) { this.attach = attach; } + void setStripSignatures(boolean stripSignatures) { + this.stripSignatures = stripSignatures; + } } diff --git a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/configuration/TransformerRules.java b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/configuration/TransformerRules.java index f4cc6bab..6a60df69 100644 --- a/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/configuration/TransformerRules.java +++ b/maven-plugins/transformer-maven-plugin/src/main/java/org/eclipse/transformer/maven/configuration/TransformerRules.java @@ -29,6 +29,7 @@ public class TransformerRules { private boolean overwrite; private boolean widen; private boolean jakartaDefaults; + private boolean stripSignatures; public TransformerRules() {} @@ -134,12 +135,26 @@ public void setWiden(boolean widen) { this.widen = widen; } + /** + * @return the stripSignatures + */ + public boolean isStripSignatures() { + return stripSignatures; + } + + /** + * @param stripSignatures the stripSignatures to set + */ + public void setStripSignatures(boolean stripSignatures) { + this.stripSignatures = stripSignatures; + } + @Override public String toString() { return String.format( - "selections=%s, renames=%s, versions=%s, bundles=%s, directs=%s, texts=%s, perClassConstants=%s, immediates=%s, invert=%s, overwrite=%s, widen=%s, jakartaDefaults=%s", + "selections=%s, renames=%s, versions=%s, bundles=%s, directs=%s, texts=%s, perClassConstants=%s, immediates=%s, invert=%s, overwrite=%s, widen=%s, jakartaDefaults=%s, stripSignatures=%s", getSelections(), getRenames(), getVersions(), getBundles(), getDirects(), getTexts(), - getPerClassConstants(), getImmediates(), isInvert(), isOverwrite(), isWiden(), isJakartaDefaults()); + getPerClassConstants(), getImmediates(), isInvert(), isOverwrite(), isWiden(), isJakartaDefaults(), isStripSignatures()); } } diff --git a/maven-plugins/transformer-maven-plugin/src/test/java/org/eclipse/transformer/maven/TransformerRunMojoTest.java b/maven-plugins/transformer-maven-plugin/src/test/java/org/eclipse/transformer/maven/TransformerRunMojoTest.java index 1d7e0910..443c9eb3 100644 --- a/maven-plugins/transformer-maven-plugin/src/test/java/org/eclipse/transformer/maven/TransformerRunMojoTest.java +++ b/maven-plugins/transformer-maven-plugin/src/test/java/org/eclipse/transformer/maven/TransformerRunMojoTest.java @@ -11,15 +11,19 @@ package org.eclipse.transformer.maven; +import static org.assertj.core.api.Assertions.assertThat; 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.File; import java.io.IOException; +import java.util.Enumeration; +import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; @@ -28,8 +32,12 @@ import org.apache.maven.plugin.testing.stubs.DefaultArtifactHandlerStub; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; +import org.eclipse.transformer.action.ElementAction; +import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.FileAsset; import org.jboss.shrinkwrap.api.exporter.ZipExporter; +import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Rule; import org.junit.Test; @@ -58,15 +66,13 @@ public void testProjectArtifactTransformerPlugin() throws Exception { mojo.setOutputDirectory(tmp.newFolder(name.getMethodName())); mojo.setAttach(true); - assertNotNull(mojo); - final File targetDirectory = this.resources.getBasedir("transform-build-artifact"); final File modelDirectory = new File(targetDirectory, "target/model"); final File pom = new File(targetDirectory, "pom.xml"); final MavenProject mavenProject = createMavenProject(modelDirectory, pom, "war", "rest-sample"); mavenProject.getArtifact() - .setFile(createService()); + .setFile(createService("war", targetDirectory)); mojo.setProject(mavenProject); mojo.setClassifier("transformed"); @@ -100,8 +106,6 @@ public void testMultipleArtifactTransformerPlugin() throws Exception { mojo.setProjectHelper(this.rule.lookup(MavenProjectHelper.class)); mojo.setAttach(true); - assertNotNull(mojo); - final File targetDirectory = this.resources.getBasedir("transform-build-artifact"); final File modelDirectory = new File(targetDirectory, "target/model"); final File pom = new File(targetDirectory, "pom.xml"); @@ -113,11 +117,11 @@ public void testMultipleArtifactTransformerPlugin() throws Exception { mojo.setOutputDirectory(tmp.newFolder(name.getMethodName())); mojo.getProjectHelper() - .attachArtifact(mavenProject, "zip", "test1", createService()); + .attachArtifact(mavenProject, "zip", "test1", createService("war", targetDirectory)); mojo.getProjectHelper() - .attachArtifact(mavenProject, "zip", "test2", createService()); + .attachArtifact(mavenProject, "zip", "test2", createService("war", targetDirectory)); mojo.getProjectHelper() - .attachArtifact(mavenProject, "zip", "test3", createService()); + .attachArtifact(mavenProject, "zip", "test3", createService("war", targetDirectory)); final Artifact[] sourceArtifacts = mojo.getSourceArtifacts(); assertEquals(3, sourceArtifacts.length); @@ -163,15 +167,13 @@ public void testProjectArtifactTransformerPluginNoAttach() throws Exception { mojo.setOutputDirectory(tmp.newFolder(name.getMethodName())); mojo.setAttach(false); - assertNotNull(mojo); - final File targetDirectory = this.resources.getBasedir("transform-build-artifact"); final File modelDirectory = new File(targetDirectory, "target/model"); final File pom = new File(targetDirectory, "pom.xml"); final MavenProject mavenProject = createMavenProject(modelDirectory, pom, "war", "rest-sample"); mavenProject.getArtifact() - .setFile(createService()); + .setFile(createService("war", targetDirectory)); mojo.setProject(mavenProject); mojo.setClassifier("transformed"); @@ -190,6 +192,51 @@ public void testProjectArtifactTransformerPluginNoAttach() throws Exception { .size()); } + @Test + public void testProjectArtifactTransformerPluginStripSignatureFiles() throws Exception { + final TransformerRunMojo mojo = new TransformerRunMojo(); + mojo.setProjectHelper(this.rule.lookup(MavenProjectHelper.class)); + mojo.setOverwrite(true); + mojo.setOutputDirectory(tmp.newFolder(name.getMethodName())); + mojo.setAttach(true); + mojo.setStripSignatures(true); + + final File targetDirectory = this.resources.getBasedir("transform-build-jar-artifact"); + final File modelDirectory = new File(targetDirectory, "target/model"); + final File pom = new File(targetDirectory, "pom.xml"); + + final MavenProject mavenProject = createMavenProject(modelDirectory, pom, "jar", "rest-sample"); + mavenProject.getArtifact() + .setFile(createService("jar", targetDirectory)); + + mojo.setProject(mavenProject); + mojo.setClassifier("transformed"); + + final Artifact[] sourceArtifacts = mojo.getSourceArtifacts(); + assertEquals(1, sourceArtifacts.length); + final Artifact sourceArtifact = sourceArtifacts[0]; + assertEquals("org.superbiz.rest", sourceArtifact.getGroupId()); + assertEquals("rest-sample", sourceArtifact.getArtifactId()); + assertEquals("1.0-SNAPSHOT", sourceArtifact.getVersion()); + assertEquals("jar", sourceArtifact.getType()); + assertNull(sourceArtifact.getClassifier()); + assertThat(getSignatureFileEntries(sourceArtifact.getFile())).containsExactly("META-INF/MYKEY.SF", "META-INF/MYKEY.DSA"); + + mojo.transform(sourceArtifacts[0]); + + assertEquals(1, mavenProject.getAttachedArtifacts() + .size()); + final Artifact transformedArtifact = mavenProject.getAttachedArtifacts() + .get(0); + + assertEquals("org.superbiz.rest", transformedArtifact.getGroupId()); + assertEquals("rest-sample", transformedArtifact.getArtifactId()); + assertEquals("1.0-SNAPSHOT", transformedArtifact.getVersion()); + assertEquals("jar", transformedArtifact.getType()); + assertEquals("transformed", transformedArtifact.getClassifier()); + assertThat(getSignatureFileEntries(transformedArtifact.getFile())).isEmpty(); + } + public MavenProject createMavenProject(final File modelDirectory, final File pom, final String packaging, final String artfifactId) { final MavenProject mavenProject = new MavenProject(); @@ -205,19 +252,44 @@ public MavenProject createMavenProject(final File modelDirectory, final File pom .setOutputDirectory(modelDirectory.getAbsolutePath()); mavenProject.setArtifact( new DefaultArtifact(mavenProject.getGroupId(), mavenProject.getArtifactId(), mavenProject.getVersion(), - (String) null, "war", (String) null, new DefaultArtifactHandlerStub(packaging, null))); + null, packaging, null, new DefaultArtifactHandlerStub(packaging, null))); return mavenProject; } - public File createService() throws IOException { - final File tempFile = File.createTempFile("service", ".war"); + private static File createService(String packaging, File targetDirectory) throws IOException { + final File tempFile = File.createTempFile("service", "." + packaging); tempFile.delete(); - final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "service.war") - .addClass(EchoService.class); + final Archive archive; + if (packaging.equals("jar")) { + archive = ShrinkWrap.create(JavaArchive.class, "service." + packaging) + .addClass(EchoService.class); + } else { + archive = ShrinkWrap.create(WebArchive.class, "service." + packaging) + .addClass(EchoService.class); + } + + if (packaging.equals("jar")) { + archive.add(new FileAsset(new File(targetDirectory, "META-INF/MYKEY.SF")), "META-INF/MYKEY.SF"); + archive.add(new FileAsset(new File(targetDirectory, "META-INF/MYKEY.DSA")), "META-INF/MYKEY.DSA"); + } - webArchive.as(ZipExporter.class) + archive.as(ZipExporter.class) .exportTo(tempFile, true); return tempFile; } + + private static Set getSignatureFileEntries(File file) throws IOException { + try (ZipFile zipFile = new ZipFile(file)) { + final Enumeration entries = zipFile.entries(); + final Set signatureFiles = new HashSet<>(); + while (entries.hasMoreElements()) { + final ZipEntry zipEntry = entries.nextElement(); + if (ElementAction.SIGNATURE_FILE_PATTERN.matcher(zipEntry.getName()).matches()) { + signatureFiles.add(zipEntry.getName()); + } + } + return signatureFiles; + } + } } diff --git a/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/META-INF/MYKEY.DSA b/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/META-INF/MYKEY.DSA new file mode 100644 index 00000000..f66e7f4b Binary files /dev/null and b/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/META-INF/MYKEY.DSA differ diff --git a/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/META-INF/MYKEY.SF b/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/META-INF/MYKEY.SF new file mode 100644 index 00000000..534d5d6c --- /dev/null +++ b/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/META-INF/MYKEY.SF @@ -0,0 +1,297 @@ +Signature-Version: 1.0 +Created-By: 11.0.14 (Azul Systems, Inc.) +SHA-256-Digest-Manifest: rpUqmWWrqQlA1TEvbLXR7NuESr1lNFXm2oReB7V7DTA= +SHA-256-Digest-Manifest-Main-Attributes: SlnRbD8M/TqLiKOgyjX0QrtvBleQgdR + N5WQCUXbqpUQ= + +Name: javax/servlet/http/Cookie.class +SHA-256-Digest: 82Y2PIZIZpUi6Z/1qoQBfsfa/5Y3pApX3XaxBdSfoAc= + +Name: META-INF/maven/org.example/signed-jar-with-javax/pom.xml +SHA-256-Digest: ng7kCODAS7H2YJ3eHeN+hSjgu+QMQCzTt5a/LJNwTvc= + +Name: javax/servlet/http/HttpSessionContext.class +SHA-256-Digest: Li0vj2pDAdwIowMKd/vVOZBCaLlL37I2SVZbJHeg5qg= + +Name: javax/servlet/http/HttpSessionListener.class +SHA-256-Digest: zMTgy+vjih50fRtjRw1zhJqaxffBNONvQVb/02yptmA= + +Name: javax/servlet/http/WebConnection.class +SHA-256-Digest: 0B74ZovspVotuv7IKXBm6xKG1jXQ3TszaV+7eNCr9pU= + +Name: javax/servlet/http/HttpSessionAttributeListener.class +SHA-256-Digest: ySXsEuI3L1MqyWLdtgrfRCnFUBVoCkvrXxIafprlu9o= + +Name: javax/servlet/http/LocalStrings_fr.properties +SHA-256-Digest: 6xpR/jN16EhPwAvxcgIu6LT2MUdycfpWAGbNWgxAyAw= + +Name: javax/servlet/LocalStrings_ja.properties +SHA-256-Digest: JLjZwyjfN8KQT9nHAvJTZxc8RWTserWYgUq5Dv90VKA= + +Name: javax/servlet/ServletRequestAttributeListener.class +SHA-256-Digest: xg93xi/RQIrRgYAgiAq8jCmHVWMW6klHupi09xZRiaI= + +Name: javax/servlet/ServletContainerInitializer.class +SHA-256-Digest: DxIzr8cpB7qFek6wbAPYRO8qmlop+pkvcwAT+YHti2I= + +Name: javax/servlet/ReadListener.class +SHA-256-Digest: zZnn2Cnwsl06h6A8yeCvIH9BFOZJ06KyJxrJP8xM8cY= + +Name: javax/servlet/ServletRequest.class +SHA-256-Digest: eQ4A2AMb90b/7hEblRG+M5H9dYsYEoD2FO9UhKsdEQQ= + +Name: javax/servlet/MultipartConfigElement.class +SHA-256-Digest: TTAYSZe6g7G/oxjuQlVyLevg0dtqwip/49vxNy08q4k= + +Name: javax/servlet/http/HttpUtils.class +SHA-256-Digest: 3WfV09iVtviyUnt00bn1wd2we1owF0bV1a96jJcHrgc= + +Name: javax/servlet/AsyncContext.class +SHA-256-Digest: jSs0vFJ251Nor5UB5DnR3APHXRWNYXSbDFPWtAZvmKA= + +Name: javax/servlet/FilterConfig.class +SHA-256-Digest: x5U3KtPAq8HnsAQJ9JXeeqjh4337EDjVaIaETYIoewA= + +Name: javax/servlet/ServletResponseWrapper.class +SHA-256-Digest: 97fKrsxzgjQauSPl/ldbJUcCiWPPyr/uVJbMphEMs6k= + +Name: javax/servlet/Registration$Dynamic.class +SHA-256-Digest: sJBFs0S3T1F0hWuyAV8KuHfiVgk7PbLikSJBDZa5xbM= + +Name: javax/servlet/descriptor/JspConfigDescriptor.class +SHA-256-Digest: woTO02dn+N7donL32vmlyGxp2SymMXVcKhHlTwOhGfg= + +Name: javax/servlet/ServletResponse.class +SHA-256-Digest: 8qHcYmuRvUsA/Ks6mqm53L6s+6E94u+G417St1e4Fkg= + +Name: javax/servlet/annotation/WebFilter.class +SHA-256-Digest: shpjmXFa/priZyD+zuQ1j2K2jk1AkS68fdc87OZaq08= + +Name: javax/servlet/annotation/HttpMethodConstraint.class +SHA-256-Digest: hxj37VtjmXOXwfjVJE5fKKkc03o4zFwPf59JdGLPSDs= + +Name: javax/servlet/SingleThreadModel.class +SHA-256-Digest: KnlDoFsIEv3aDkRf9S3kksjszr/kMSna2x9TAnQUVnM= + +Name: javax/servlet/ServletConfig.class +SHA-256-Digest: tx6KBryAT7Yrf2gXrE1nf5ioEemPbMoEngeg0Bwi7lw= + +Name: org/example/Main.java +SHA-256-Digest: ZeG4NCcEVdey6WhE2Kcmt8yYMCASU+1LULevLGGDoOc= + +Name: javax/servlet/annotation/HttpConstraint.class +SHA-256-Digest: 7a6ZlhZWhFEeY7+ISXOfCVqSP8NaWUf0aR8yEmvAxQQ= + +Name: javax/servlet/http/HttpSessionBindingEvent.class +SHA-256-Digest: rERLe8uNkbbXSTvyPS6ZVrn9wp6I1m5kUL/AcLEyaHw= + +Name: javax/servlet/DispatcherType.class +SHA-256-Digest: vBqD4yz8rebyAJGQZ4jabdsFAuI7/dG0vwo4Z4BbDJg= + +Name: javax/servlet/ServletOutputStream.class +SHA-256-Digest: XgeVe6BeMBJlcxqwVkbfDfzc9lBJDpc1WKtcGz/6jdw= + +Name: javax/servlet/descriptor/JspPropertyGroupDescriptor.class +SHA-256-Digest: CkpfWH4ABCemtS5sfU/yzabjYjzZthZHjE4M7WWfMFs= + +Name: javax/servlet/SessionTrackingMode.class +SHA-256-Digest: vPdjsyvIYiu88XqVbpA+6zaDHA4xJ5qL/NNSYaABavM= + +Name: javax/servlet/annotation/ServletSecurity$EmptyRoleSemantic.class +SHA-256-Digest: 8cAjpVvLSwQkhz72k+9E6sJF2MYuPhZi7jcGf6Tt3/w= + +Name: javax/servlet/ServletContextListener.class +SHA-256-Digest: eVo64hIxahqWyZdU05KCuZvmyL0DeYSlfr9mls5smds= + +Name: javax/servlet/Filter.class +SHA-256-Digest: JAf3kDjh5C8okRUHRy9dgDwDWbQeZeL/cYBte+9Bg6k= + +Name: javax/servlet/http/HttpUpgradeHandler.class +SHA-256-Digest: FSQ02EJarsAfuOc9BsvuLKpHTpq5JvXIdPnj/N7EhCI= + +Name: javax/servlet/FilterRegistration.class +SHA-256-Digest: j5X7LWDYfyCHXaw1a1QU0ZWdiQXGhLCa3eLfcmGxllE= + +Name: javax/servlet/Servlet.class +SHA-256-Digest: EGk0jFklwDAKG/yVYigKJLitbf2WWqwGa8ae6Za5TuQ= + +Name: javax/servlet/http/LocalStrings_es.properties +SHA-256-Digest: INs55tD8i2YSokcZvu+On4erTJvNEmeP+mBlSISpY94= + +Name: javax/servlet/annotation/WebInitParam.class +SHA-256-Digest: 6Js7lQ+lofEQ/XFO7B5FKKFGjm6ns2SkUZMBNJauJas= + +Name: javax/servlet/descriptor/TaglibDescriptor.class +SHA-256-Digest: ifsKXM/fDdZQSfTDY0hgjs+fhKiBPhPMa9hXwzznYJQ= + +Name: javax/servlet/ServletContextEvent.class +SHA-256-Digest: mgIk2gDh6Ib5ykOs7JMg6OMGNJ06u5l9YtmPbJD/5Js= + +Name: javax/servlet/http/NoBodyOutputStream.class +SHA-256-Digest: WO4YA1kqjSL/sxRszHCu8gW0NjpvuJGtfLwz2c+pcHE= + +Name: javax/servlet/ServletRegistration$Dynamic.class +SHA-256-Digest: aiiZyMvYqK99kWr5d845NqyLgOWLNxZbBWIXLBFsWmU= + +Name: javax/servlet/UnavailableException.class +SHA-256-Digest: xcZUP2YFWzYKqVy74Rd0FDBE4T31H15WkK5m/uNBVlA= + +Name: javax/servlet/ServletRequestListener.class +SHA-256-Digest: x3xl26ZpZeYHVhSWoUcHbORfI3vbznn02dYlnXH3dfg= + +Name: javax/servlet/package.html +SHA-256-Digest: NPQhFHnAGi1yarOwlm864usFMmlNnkocTbF15I0Gs1I= + +Name: javax/servlet/http/HttpServletRequest.class +SHA-256-Digest: 4uHhhhqVAW06loe4w5pf8UYDSaT86Cn07SimS4ufoJ4= + +Name: javax/servlet/ServletContext.class +SHA-256-Digest: jRBO4ZQMDmubphGp0P1TGtn520ma5yiwnGIFlXjrpfU= + +Name: javax/servlet/Registration.class +SHA-256-Digest: Aw3HPUeP4Xh8jEORQQIGl6NdyWcrOuPZCIeGACXyooE= + +Name: javax/servlet/FilterChain.class +SHA-256-Digest: mwKCSXXxRffLPz++bXJD5B7rgZ01ONvuu45r+fTUAoA= + +Name: javax/servlet/http/HttpServletRequestWrapper.class +SHA-256-Digest: jd7TR6/i/WGas8MnsGlGr1Ei8mufXrSlBkO1dxk7veI= + +Name: javax/servlet/annotation/HandlesTypes.class +SHA-256-Digest: 5W4WlpmJZG1JAgLn60QhOImk41gY1ykjAZYDllbFtwA= + +Name: javax/servlet/http/HttpSessionBindingListener.class +SHA-256-Digest: QGhM8czlA18u9Y9cSaMIha4luI9HF7i2MdP6g3JiQSw= + +Name: javax/servlet/annotation/ServletSecurity.class +SHA-256-Digest: 2JSCRnTNlxedodflTEzpzv7Vsd0o8dGZu3VUSJjRPVo= + +Name: javax/servlet/ServletRequestAttributeEvent.class +SHA-256-Digest: 9Vv6M/sFd0m4FHqciN4LRUTugYe7NgeC/yYpD46dZAw= + +Name: javax/servlet/ServletRequestWrapper.class +SHA-256-Digest: AjZm9ZHL1Qwud/L0XDrXxeDOs3nnDB5Wz3EuOOrZDSk= + +Name: javax/servlet/annotation/MultipartConfig.class +SHA-256-Digest: QutcTcaFochjJimstYEGxjBuq+m5Y5MTt2dESpr3YVM= + +Name: javax/servlet/ServletRequestEvent.class +SHA-256-Digest: av0TTDJtcOeGaHPVX/qNgi3ATwjDKgnN3WNrr7SuVHc= + +Name: javax/servlet/http/HttpServlet.class +SHA-256-Digest: KtJ+P1TGullJrO6PbX3U/uDlp4a0X5BRyoQw1Ui1m/w= + +Name: javax/servlet/LocalStrings_fr.properties +SHA-256-Digest: d2jbgmW48aj3CErfe7FmdfipYLyH5M4CvYNa0TRxiAU= + +Name: javax/servlet/LocalStrings.properties +SHA-256-Digest: AYhzGsJHWLT6ymgA2ybsWyT2ogbPbjndrqu28IoCF0U= + +Name: javax/servlet/annotation/package.html +SHA-256-Digest: O4NXfLNZHJa+v6PuCweBedX3ALdrXqgwdyMX/CVoYHU= + +Name: javax/servlet/http/LocalStrings_ja.properties +SHA-256-Digest: /x7zSiBDCQTh3gryrqH9LpFDgkPlsG/oxJmZ+FEauqA= + +Name: javax/servlet/SessionCookieConfig.class +SHA-256-Digest: 1uWMECVljGxWzMrtm2RjSx4qIroh1ubcHp9KqDf3aTU= + +Name: META-INF/maven/org.example/signed-jar-with-javax/pom.properties +SHA-256-Digest: HTInLkbuwl9EwiK0IfSlUsT1NBae7CMp6YYsjI8ZnmE= + +Name: javax/servlet/http/Part.class +SHA-256-Digest: qS8JPwEQBpHEcQJ07GCg+TzSpt5+Q+EhZXg2/RfsIJ8= + +Name: javax/servlet/http/HttpServletResponseWrapper.class +SHA-256-Digest: AANn3d328uvstVjj8F6/1DmTQGnH1EA+gMtZKAq75fo= + +Name: javax/servlet/AsyncListener.class +SHA-256-Digest: BDdxeUXdructVe20bYMNHAxDaLjzzvCgsEFpDkpA4mE= + +Name: javax/servlet/descriptor/package.html +SHA-256-Digest: hXpMG7jKEBmAN3pDFJ50ovBJRQ1af8fZlZaiTRbSYo8= + +Name: META-INF/maven/javax.servlet/javax.servlet-api/pom.properties +SHA-256-Digest: 0Yhfe4l5cV/yX/0pRB1ArkXv1BPNOTeus2TmX5G+jTs= + +Name: javax/servlet/HttpConstraintElement.class +SHA-256-Digest: pTp3RBntJeSVr+NvWvngLd9BbwhU2TBk7xcO+7w/YW8= + +Name: META-INF/maven/javax.servlet/javax.servlet-api/pom.xml +SHA-256-Digest: DKKCitUwl3nN/uVIG6M6caadog5ZqWs3rb9Ci1BDDhI= + +Name: javax/servlet/annotation/WebServlet.class +SHA-256-Digest: YAtD65tbtJDFVSv1udeRBTtDrSyTpOD4nZspDT5R7EE= + +Name: javax/servlet/http/HttpSessionActivationListener.class +SHA-256-Digest: bVBk5lW/6YlCC36Jc7RWqdvxFkCUnUfe7bLv2WysQXQ= + +Name: javax/servlet/HttpMethodConstraintElement.class +SHA-256-Digest: rpyHGd6kuGctASZKU3wJ5rRjiMl+cM+frAPeH3dVcGE= + +Name: javax/servlet/WriteListener.class +SHA-256-Digest: uczY24xrI+Um4pQek1ls7QGU1DHBul9TDP/YBVdkmv0= + +Name: javax/servlet/http/NoBodyResponse.class +SHA-256-Digest: 2xo1OU/b/K7JrOIraisYYYfJGjlizlQhE9+dqkfHlDs= + +Name: org/example/Main.class +SHA-256-Digest: mgxR2BQuWiqlV0LtYIOzaKVZB7HcFa/Ovq1OkF76GGM= + +Name: javax/servlet/GenericServlet.class +SHA-256-Digest: jemlA5/Uu+/AzaXdCQU1BSEEn8QvaczHvjaDArU9MRw= + +Name: javax/servlet/http/HttpSessionIdListener.class +SHA-256-Digest: kphVrWbBPN7oYz5GfLO+D9zy48S15TDfcL5ExNdZK0o= + +Name: javax/servlet/ServletException.class +SHA-256-Digest: 2A96F0if2wZ4735Y/11MIFEW2rVgWQnXDlmG6Hx1Uxc= + +Name: javax/servlet/ServletRegistration.class +SHA-256-Digest: CXM/0mAAT9qJ9ell2/3QgxJLEojuTeSzBIowJASY09E= + +Name: javax/servlet/ServletContextAttributeEvent.class +SHA-256-Digest: pRYtbRz9z+n82A5MsDlzzOhUvYnxhbyJr2J3VKkducg= + +Name: javax/servlet/http/LocalStrings.properties +SHA-256-Digest: 8YW/cRY5ZNp4piwxqyPgYvbM2Q/Y4sGV/6+IK2Ap7Uk= + +Name: javax/servlet/AsyncEvent.class +SHA-256-Digest: vf0KvIhvwQxjqZBQ/6g1x8re8dL3GwYwG7gZyMvU7Ss= + +Name: javax/servlet/http/HttpServletResponse.class +SHA-256-Digest: lmqNHTRSSZuYEcFiAnsavKJHcWymA+wd9plAWRb15q4= + +Name: javax/servlet/http/package.html +SHA-256-Digest: 0/yGDdAITN1l2lDm3IDRAfUufbh8DKlVl3V3S+zBflA= + +Name: javax/servlet/annotation/ServletSecurity$TransportGuarantee.class +SHA-256-Digest: o+kYKk2fCzYi+tSmNTecA5sdgFBceIkJ0fXsG94m4Kk= + +Name: javax/servlet/ServletSecurityElement.class +SHA-256-Digest: Fpb2Mcnv/H3lYx9teQSidT98uiDbzWR0IMFJ4+8lF6A= + +Name: javax/servlet/ServletContextAttributeListener.class +SHA-256-Digest: R7IWmc5ouL0PMpfItKX4cWszy6wE9MOXJzmf5TVurpI= + +Name: META-INF/LICENSE.txt +SHA-256-Digest: +SnfA26jz/POzd3XyCfraXybcdU55pa9j8QFS8yHg/M= + +Name: javax/servlet/http/HttpSession.class +SHA-256-Digest: apPkO8o3kT8EDNnKmQPBTqxsRuuuexYUnn8j7kCwgHE= + +Name: javax/servlet/http/HttpSessionEvent.class +SHA-256-Digest: aM9Zg0cD5+QtSV+4FM2T2XHoSXeBNgm/Bk8FrxHzrkA= + +Name: javax/servlet/RequestDispatcher.class +SHA-256-Digest: aoOyBeOetaLV7Mfx2dJJGLTHQsUMQQfJyszR/YQ9gLo= + +Name: javax/servlet/annotation/WebListener.class +SHA-256-Digest: ROxLGTdJNNBVYUB2/vxdoqyPvzhk/MdlXJFtL1CBH7I= + +Name: javax/servlet/ServletInputStream.class +SHA-256-Digest: u3alWBPjFkpnKH/4Fw5dJb48DNUEKKgTCakr0iGX9hs= + +Name: javax/servlet/FilterRegistration$Dynamic.class +SHA-256-Digest: NJB/fL60z9uf+rQPrYIWe255zDXO5MfV4S8sGs3oKng= + diff --git a/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/pom.xml b/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/pom.xml new file mode 100644 index 00000000..5b86a207 --- /dev/null +++ b/maven-plugins/transformer-maven-plugin/src/test/projects/transform-build-jar-artifact/pom.xml @@ -0,0 +1,66 @@ + + + + 4.0.0 + + org.superbiz.rest + rest-sample + 1.0-SNAPSHOT + jar + + rest-sample Maven Webapp + http://www.example.com + + + UTF-8 + 1.8 + 1.8 + + + + + javax + javaee-api + 8.0.1 + provided + + + + + rest-sample + + + org.eclipse.transformer + org.eclipse.transformer.maven + ${revision} + + + + + + + run + + package + + + + + maven-jar-plugin + + false + + + + + diff --git a/org.eclipse.transformer.cli/src/test/data/command-line/signed-jar-with-javax.jar b/org.eclipse.transformer.cli/src/test/data/command-line/signed-jar-with-javax.jar new file mode 100644 index 00000000..5f7bea0f Binary files /dev/null and b/org.eclipse.transformer.cli/src/test/data/command-line/signed-jar-with-javax.jar differ diff --git a/org.eclipse.transformer.cli/src/test/java/transformer/test/TestCommandLine.java b/org.eclipse.transformer.cli/src/test/java/transformer/test/TestCommandLine.java index 5d2c0a75..0df4629f 100644 --- a/org.eclipse.transformer.cli/src/test/java/transformer/test/TestCommandLine.java +++ b/org.eclipse.transformer.cli/src/test/java/transformer/test/TestCommandLine.java @@ -15,14 +15,21 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; import java.io.PrintStream; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import aQute.lib.io.IO; import org.assertj.core.api.SoftAssertions; import org.eclipse.transformer.Transformer; import org.eclipse.transformer.action.Changes; import org.eclipse.transformer.action.ContainerChanges; +import org.eclipse.transformer.action.ElementAction; import org.eclipse.transformer.action.impl.DirectoryActionImpl; import org.eclipse.transformer.action.impl.JavaActionImpl; import org.eclipse.transformer.action.impl.ManifestActionImpl; @@ -76,14 +83,14 @@ public void tearDown() { void testManifestActionAccepted() throws Exception { String inputFileName = STATIC_CONTENT_DIR + "/command-line/MANIFEST.MF"; String outputFileName = DYNAMIC_CONTENT_DIR + "/MANIFEST.MF"; - verifyAction(ManifestActionImpl.class.getName(), inputFileName, outputFileName, outputFileName); + verifyAction(ManifestActionImpl.class.getName(), inputFileName, outputFileName, outputFileName, false); } @Test void testJavaActionAccepted() throws Exception { String inputFileName = STATIC_CONTENT_DIR + "/command-line/A.java"; String outputFileName = DYNAMIC_CONTENT_DIR + "/A.java"; - verifyAction(JavaActionImpl.class.getName(), inputFileName, outputFileName, outputFileName); + verifyAction(JavaActionImpl.class.getName(), inputFileName, outputFileName, outputFileName, false); } @Test @@ -110,7 +117,7 @@ void testInputFileNameOnlyAccepted() throws Exception { String inputFileName = inputFile.getCanonicalPath().replace(File.separatorChar, '/'); String expectedOutputFileName = new File(inputFile.getParentFile(), Transformer.OUTPUT_PREFIX + inputFile.getName()).getCanonicalPath() .replace(File.separatorChar, '/'); - verifyAction(JavaActionImpl.class.getName(), inputFileName, null, expectedOutputFileName); + verifyAction(JavaActionImpl.class.getName(), inputFileName, null, expectedOutputFileName, false); } @Test @@ -126,7 +133,47 @@ void testInvalidOutputDirectoryRejected() throws Exception { void zip_entry_creation() throws Exception { String inputFileName = STATIC_CONTENT_DIR + "/command-line/sac-1.3.jar"; String outputFileName = DYNAMIC_CONTENT_DIR + "/sac-1.3.jar"; - verifyAction(ZipActionImpl.class.getName(), inputFileName, outputFileName, outputFileName); + verifyAction(ZipActionImpl.class.getName(), inputFileName, outputFileName, outputFileName, false); + } + + /* + * Tests that signature files have been discarded from signed jar file (regardless of whether it was mutated) + * when -s command-line option has been specified. + * + * signed-jar-with-javax.jar contains a single class file which references javax.servlet.Servlet. + * The Java source code is included with the jar file. + */ + @Test + void testStripSignatureFiles() throws Exception { + String inputFileName = STATIC_CONTENT_DIR + "/command-line/signed-jar-with-javax.jar"; + String outputFileName = DYNAMIC_CONTENT_DIR + "/signed-jar-with-javax.jar"; + // Assert that signed input jar file contains 2 signature files: META-INF/MYKEY.SF and META-INF/MYKEY.DSA + Map inputJarSigFilesMap = extractSignatureFileEntries(inputFileName); + assertThat(inputJarSigFilesMap).containsOnlyKeys("META-INF/MYKEY.SF", "META-INF/MYKEY.DSA"); + verifyAction(ZipActionImpl.class.getName(), inputFileName, outputFileName, outputFileName, true); + // Assert that signature files have been removed from output jar file + assertThat(extractSignatureFileEntries(outputFileName)).isEmpty(); + } + + /* + * Tests that signature files are preserved in signed jar file by default. + * + * signed-jar-with-javax.jar contains a single class file which references javax.servlet.Servlet. + * The Java source code is included with the jar file. + */ + @Test + void testSignatureFilesPreservedByDefault() throws Exception { + String inputFileName = STATIC_CONTENT_DIR + "/command-line/signed-jar-with-javax.jar"; + String outputFileName = DYNAMIC_CONTENT_DIR + "/unsigned-jar-with-javax.jar"; + // Assert that signed input jar file contains 2 signature files: META-INF/MYKEY.SF and META-INF/MYKEY.DSA + Map inputJarSigFilesMap = extractSignatureFileEntries(inputFileName); + assertThat(inputJarSigFilesMap).containsOnlyKeys("META-INF/MYKEY.SF", "META-INF/MYKEY.DSA"); + verifyAction(ZipActionImpl.class.getName(), inputFileName, outputFileName, outputFileName, false); + // Assert that signature files have been preserved in output jar file + Map outputJarSigFilesMap = extractSignatureFileEntries(outputFileName); + assertThat(outputJarSigFilesMap).containsOnlyKeys("META-INF/MYKEY.SF", "META-INF/MYKEY.DSA"); + assertThat(outputJarSigFilesMap.get("META-INF/MYKEY.SF")).isEqualTo(inputJarSigFilesMap.get("META-INF/MYKEY.SF")); + assertThat(outputJarSigFilesMap.get("META-INF/MYKEY.DSA")).isEqualTo(inputJarSigFilesMap.get("META-INF/MYKEY.DSA")); } // Test zip with STORED archive to make sure ZipEntries are properly created. @@ -134,7 +181,7 @@ void zip_entry_creation() throws Exception { void zip_nested_stored_archive() throws Exception { String inputFileName = STATIC_CONTENT_DIR + "/command-line/nested_stored_archive.war"; String outputFileName = DYNAMIC_CONTENT_DIR + "/nested_stored_archive.war"; - verifyAction(ZipActionImpl.class.getName(), inputFileName, outputFileName, outputFileName); + verifyAction(ZipActionImpl.class.getName(), inputFileName, outputFileName, outputFileName, false); } // Test zip with entry names encoded with a charset other than UTF-8. @@ -294,11 +341,17 @@ void testSetLogFile() throws Exception { } - private void verifyAction(String actionClassName, String inputFileName, String outputFileName, String expectedOutputFileName) throws Exception { - verifyAction(actionClassName, inputFileName, outputFileName, expectedOutputFileName, 0); + private void verifyAction(String actionClassName, String inputFileName, String outputFileName, String expectedOutputFileName, + boolean stripSignatures) throws Exception { + verifyAction(actionClassName, inputFileName, outputFileName, expectedOutputFileName, 0, stripSignatures); } private void verifyAction(String actionClassName, String inputFileName, String outputFileName, String expectedOutputFileName, int duplicates) throws Exception { + verifyAction(actionClassName, inputFileName, outputFileName, expectedOutputFileName, duplicates, false); + } + + private void verifyAction(String actionClassName, String inputFileName, String outputFileName, String expectedOutputFileName, + int duplicates, boolean stripSignatures) throws Exception { System.out.printf("verifyAction: Input is: [%s] Output is: [%s]\n", inputFileName, outputFileName); String[] args = outputFileName != null ? new String[] { inputFileName, outputFileName, "-o" @@ -306,6 +359,13 @@ private void verifyAction(String actionClassName, String inputFileName, String o inputFileName, "-o" }; + if (stripSignatures) { + String[] moreArgs = new String[args.length + 1]; + System.arraycopy(args, 0, moreArgs, 0, args.length); + moreArgs[args.length] = "-s"; + args = moreArgs; + } + TransformerCLI cli = new JakartaTransformerCLI(System.out, System.err, args); Transformer transformer = new Transformer(cli.getLogger(), cli); @@ -368,4 +428,18 @@ private void verifyActionInvalidDirectoryRejected(String actionClassName, String assertThat(transformer.setOutput()).as("transformer.setOutput() unexpectedly succeeded") .isFalse(); } + + private static Map extractSignatureFileEntries(String zipFilePath) throws IOException { + try (ZipFile zipFile = new ZipFile(zipFilePath)) { + final Enumeration entries = zipFile.entries(); + final Map signatureFilesMap = new HashMap(); + while (entries.hasMoreElements()) { + final ZipEntry zipEntry = entries.nextElement(); + if (ElementAction.SIGNATURE_FILE_PATTERN.matcher(zipEntry.getName()).matches()) { + signatureFilesMap.put(zipEntry.getName(), IO.read(zipFile.getInputStream(zipEntry))); + } + } + return signatureFilesMap; + } + } } diff --git a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/AppOption.java b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/AppOption.java index a44c27f3..73997f4b 100644 --- a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/AppOption.java +++ b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/AppOption.java @@ -77,6 +77,9 @@ public enum AppOption { INVERT(new Settings("i", "invert", "Invert transformation rules", !Settings.HAS_ARG, !Settings.HAS_ARGS, !Settings.IS_REQUIRED, Settings.NO_GROUP)), + STRIP_SIGNATURES(new Settings("s", "stripSignatures", "Strips signatures from signed jar files", !Settings.HAS_ARG, !Settings.HAS_ARGS, + !Settings.IS_REQUIRED, Settings.NO_GROUP)), + FILE_TYPE(new Settings("t", "type", "Input file type", Settings.HAS_ARG, !Settings.HAS_ARGS, !Settings.IS_REQUIRED, Settings.NO_GROUP)), OVERWRITE(new Settings("o", "overwrite", "Overwrite", !Settings.HAS_ARG, !Settings.HAS_ARGS, !Settings.IS_REQUIRED, diff --git a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/Transformer.java b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/Transformer.java index 67459c8e..f953079b 100644 --- a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/Transformer.java +++ b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/Transformer.java @@ -1135,11 +1135,16 @@ public ActionSelector getActionSelector() { standardActions.add(propertiesAction); // after text so text can supersede standardActions.add(xmlAction); // after text so text can supersede - ContainerAction jarAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.JAR), context); - ContainerAction warAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.WAR), context); - ContainerAction rarAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.RAR), context); - ContainerAction earAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.EAR), context); - ContainerAction zipAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.ZIP), context); + ContainerAction jarAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.JAR, + options.hasOption(AppOption.STRIP_SIGNATURES)), context); + ContainerAction warAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.WAR, + options.hasOption(AppOption.STRIP_SIGNATURES)), context); + ContainerAction rarAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.RAR, + options.hasOption(AppOption.STRIP_SIGNATURES)), context); + ContainerAction earAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.EAR, + options.hasOption(AppOption.STRIP_SIGNATURES)), context); + ContainerAction zipAction = useSelector.addUsing(c -> new ZipActionImpl(c, ActionType.ZIP, + options.hasOption(AppOption.STRIP_SIGNATURES)), context); Action renameAction = useSelector.addUsing(RenameActionImpl::new, context); diff --git a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/ElementAction.java b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/ElementAction.java index 5e890cf0..2f64c64e 100644 --- a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/ElementAction.java +++ b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/ElementAction.java @@ -13,7 +13,12 @@ import org.eclipse.transformer.TransformException; +import java.util.regex.Pattern; + public interface ElementAction extends Action { + + Pattern SIGNATURE_FILE_PATTERN = Pattern.compile("META-INF/([^/]+\\.(?:DSA|RSA|EC|SF)|SIG-[^/]+)"); + @Override default boolean isElementAction() { return true; diff --git a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/impl/ZipActionImpl.java b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/impl/ZipActionImpl.java index 103e7dcf..e90031e7 100644 --- a/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/impl/ZipActionImpl.java +++ b/org.eclipse.transformer/src/main/java/org/eclipse/transformer/action/impl/ZipActionImpl.java @@ -52,12 +52,14 @@ */ public class ZipActionImpl extends ContainerActionImpl implements ElementAction { - public ZipActionImpl(ActionContext context, ActionType actionType) { + public ZipActionImpl(ActionContext context, ActionType actionType, boolean stripSignatures) { super(context); this.actionType = actionType; + this.stripSignatures = stripSignatures; } private final ActionType actionType; + private final boolean stripSignatures; @Override public ActionType getActionType() { @@ -264,6 +266,9 @@ private void applyZipStream( try { inputName = FileUtils.sanitize(inputEntry.getName()); // Avoid ZipSlip + if (stripSignatures && ElementAction.SIGNATURE_FILE_PATTERN.matcher(inputName).matches()) { + continue; + } int inputLength = Math.toIntExact(inputEntry.getSize()); useLogger.debug("[ {}.{} ] Entry [ {} ] Size [ {} ]", className, methodName, inputName, inputLength); diff --git a/org.eclipse.transformer/src/test/java/transformer/test/TestTransformClass.java b/org.eclipse.transformer/src/test/java/transformer/test/TestTransformClass.java index 4a4800b4..e7aaae33 100644 --- a/org.eclipse.transformer/src/test/java/transformer/test/TestTransformClass.java +++ b/org.eclipse.transformer/src/test/java/transformer/test/TestTransformClass.java @@ -345,7 +345,7 @@ public ZipActionImpl getJavaxToJakartaJarAction() { createSelectionRule(useLogger, getIncludes(), getExcludes()), createSignatureRule(useLogger, getToJakartaRenames(), null, null, null, Collections.emptyMap())); - toJakartaJarAction = new ZipActionImpl(context, ActionType.JAR); + toJakartaJarAction = new ZipActionImpl(context, ActionType.JAR, false); } return toJakartaJarAction; @@ -363,7 +363,7 @@ public ZipActionImpl getJakartaToJavaxJarAction() { createSelectionRule(useLogger, getIncludes(), getExcludes()), createSignatureRule(useLogger, toJavaxRenames, null, null, null, Collections.emptyMap())); - toJavaxJarAction = new ZipActionImpl(context, ActionType.JAR); + toJavaxJarAction = new ZipActionImpl(context, ActionType.JAR, false); } return toJavaxJarAction; @@ -379,7 +379,7 @@ public ZipActionImpl getJavaxToJakartaJarAction_DirectOverride() { createSelectionRule(useLogger, getOverrideIncludes(), getExcludes()), createSignatureRule(useLogger, getToJakartaRenames(), null, null, toJakartaDirectStrings(), null)); - toJakartaJarAction_DirectOverride = new ZipActionImpl(context, ActionType.JAR); + toJakartaJarAction_DirectOverride = new ZipActionImpl(context, ActionType.JAR, false); } return toJakartaJarAction_DirectOverride; @@ -396,7 +396,7 @@ public ZipActionImpl getJavaxToJakartaJarAction_PerClassDirectOverride() { createSignatureRule(useLogger, getToJakartaRenames(), null, null, toJakartaDirectStrings(), toJakartaPerClassDirectStrings())); - toJakartaJarAction_PerClassDirectOverride = new ZipActionImpl(context, ActionType.JAR); + toJakartaJarAction_PerClassDirectOverride = new ZipActionImpl(context, ActionType.JAR, false); } return toJakartaJarAction_PerClassDirectOverride; @@ -412,7 +412,7 @@ public ZipActionImpl getJavaxToJakartaJarAction_PackageRenamesOnly() { createSelectionRule(useLogger, getOverrideIncludes(), getExcludes()), createSignatureRule(useLogger, getToJakartaRenames(), null, null, null, null)); - toJakartaJarAction_PackageRenamesOnly = new ZipActionImpl(context, ActionType.JAR); + toJakartaJarAction_PackageRenamesOnly = new ZipActionImpl(context, ActionType.JAR, false); } return toJakartaJarAction_PackageRenamesOnly; diff --git a/org.eclipse.transformer/src/test/java/transformer/test/TestTransformServiceConfig.java b/org.eclipse.transformer/src/test/java/transformer/test/TestTransformServiceConfig.java index b174819b..565e6d1d 100644 --- a/org.eclipse.transformer/src/test/java/transformer/test/TestTransformServiceConfig.java +++ b/org.eclipse.transformer/src/test/java/transformer/test/TestTransformServiceConfig.java @@ -30,7 +30,6 @@ import org.eclipse.transformer.action.BundleData; import org.eclipse.transformer.action.ByteData; import org.eclipse.transformer.action.impl.ActionContextImpl; -import org.eclipse.transformer.action.impl.ActionSelectorImpl; import org.eclipse.transformer.action.impl.PropertiesActionImpl; import org.eclipse.transformer.action.impl.SelectionRuleImpl; import org.eclipse.transformer.action.impl.ServiceLoaderConfigActionImpl; @@ -190,13 +189,11 @@ public ZipActionImpl getJarJavaxServiceAction() { Map invertedRenames = TransformProperties.invert(getPackageRenames()); - ActionSelectorImpl actionSelector = new ActionSelectorImpl(); - ActionContext context = new ActionContextImpl(useLogger, createSelectionRule(useLogger, Collections.emptyMap(), getExcludes()), createSignatureRule(useLogger, invertedRenames, null, null, null)); - jarJavaxServiceAction = new ZipActionImpl(context, ActionType.JAR); + jarJavaxServiceAction = new ZipActionImpl(context, ActionType.JAR, false); jarJavaxServiceAction.addUsing(PropertiesActionImpl::new); jarJavaxServiceAction.addUsing(ServiceLoaderConfigActionImpl::new); }