eclipse / transformer

Eclipse Transformer provides tools and runtime components that transform Java binaries, such as individual class files and complete JARs and WARs, mapping changes to Java packages, type names, and related resource names.

Home Page:https://projects.eclipse.org/projects/technology.transformer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Zip file conversion fails if it includes jar files whose archive type are STORED.

tsyamamoto opened this issue · comments

Environment Details

  • Transformer Version: org.eclipse.transformer.cli-0.5.0-20220610.152928-25-distribution.jar
  • JDK version: 11
  • OS: Windows Server 2019, Red Hat Enterprise Linux 7.9

Problem Description

Zip file conversion fails if it includes jar files whose archive type are STORED.

Example)

>java -jar org.eclipse.transformer.cli\target\org.eclipse.transformer.cli-0.5.0-SNAPSHOT.jar C:\dev\apps\EJBTest3.zip
- snip
[main] INFO Transformer - Action selected for input [ C:/dev/apps/EJBTest3.zip ]: Zip Action
[main] ERROR Transformer - Resource [ EJBTest3.jar ] Action [ Jar Action ]: Failed transform
java.util.zip.ZipException: STORED entry missing size, compressed size, or crc-32
        at java.util.zip.ZipOutputStream.putNextEntry(ZipOutputStream.java:224)
        at org.eclipse.transformer.action.impl.ZipActionImpl.putEntry(ZipActionImpl.java:583)
        at org.eclipse.transformer.action.impl.ZipActionImpl.applyZipStream(ZipActionImpl.java:365)
        at org.eclipse.transformer.action.impl.ZipActionImpl.applyStream(ZipActionImpl.java:210)
        at org.eclipse.transformer.action.impl.ZipActionImpl.applyFile(ZipActionImpl.java:187)
        at org.eclipse.transformer.action.impl.ZipActionImpl.apply(ZipActionImpl.java:123)
        at org.eclipse.transformer.Transformer.transform(Transformer.java:1232)
        at org.eclipse.transformer.Transformer.basicRun(Transformer.java:199)
        at org.eclipse.transformer.Transformer.run(Transformer.java:155)
        at org.eclipse.transformer.cli.TransformerCLI.run(TransformerCLI.java:387)
        at org.eclipse.transformer.cli.TransformerCLI.runWith(TransformerCLI.java:58)
        at org.eclipse.transformer.cli.JakartaTransformerCLI.main(JakartaTransformerCLI.java:24)
[main] INFO Transformer - Input  [ C:/dev/apps/EJBTest3.zip ] as [ C:\dev\apps\EJBTest3.zip ]
[main] INFO Transformer - Output [ C:/dev/apps/output_EJBTest3.zip ] as [ C:\dev\apps\output_EJBTest3.zip ]
[main] INFO Transformer - [  All Resources ] [      1 ] Unaccepted [      0 ]   Accepted [      1 ]
[main] INFO Transformer - [  All Unchanged ] [      1 ]     Failed [      1 ] Duplicated [      0 ]
[main] INFO Transformer - [    All Changed ] [      0 ]    Renamed [      0 ]    Content [      0 ]
[main] WARN Transformer - Failures were processed [ 1 ]
[main] INFO Transformer - Transformer Return Code [ 3 ] [ Transform Error ]

Steps to reproduce

It is easily reproducible with a zip which contains jar file.

Cause

ZipEntry outputEntry = createEntry(inputEntry, outputName);
String putInputName = inputName; // Need these to be effectively final.
String putOutputName = outputName;
putEntry(zipOutputStream, outputEntry, () -> {
// Note the use of 'apply' and not the internal 'applyStream'.
// Recording must be performed. And, the streams must be put through
// conversion to zip streams as a part of handling nested archives.
zipAction.apply(putInputName, zipInputStream, putOutputName, zipOutputStream);
});

private void putEntry(ZipOutputStream zipOutputStream, ZipEntry outputEntry, TransformerRunnable populator) throws IOException, TransformException {
zipOutputStream.putNextEntry(outputEntry); // throws IOException
try {
populator.run(); // throws TransformException
} finally {
zipOutputStream.closeEntry(); // throws IOException
}
}

ZipActionImpl invokes zipOutputStream.putNextEntry(outputEntry); ,
and then zipAction.apply(putInputName, zipInputStream, putOutputName, zipOutputStream); is called recursively.
However, if the compression method is STORED,
outputEntry must be set with size, csize, and crc values before executing zipOutputStream.putNextEntry(outputEntry);.
So the current implementation throws an exception because the size is not set to outputEntry when putNextEntry is called.

I made a patch to fix this problem:
We cannot simply set the value of the inputEntry to outputEntry, because the size and CRC may change as a result of the Transformer conversion.
Therefore, if the compression method is STORED, we should execute zipOutputStream.putNextEntry(outputEntry); after calling zipAction.apply(putInputName, zipInputStream, putOutputName, zipOutputStream); on the archive file in zip to determine its size.

Impact of Issue

The zip conversion is not successful.