Ah, I see your point now. The duplication a/A was not on the filenames, but on the folders / package names.
After a lot of confusion, because I was having the same problem you mentioned, I think I figured out the reason. It was 7-zip's problem, not the generated JAR
Here's some standalone java code to create a JAR with duplicate directories (and files as well):
Code:
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.spi.FileSystemProvider;
import java.util.HashMap;
import java.util.Map;
/**
* Test code for Zip creation from within java
*
* Extracted from Dex2Jar code, more specifically:
* https://github.com/pxb1988/dex2jar/blob/eca2c98278ec30e31c3953e0a030505987a6f8ca/dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2jar.java#L270
*
*/
public class ZipFSTest {
public static void to(Path file) throws IOException {
if (Files.exists(file) && Files.isDirectory(file)) {
doTranslate(file);
} else {
try (FileSystem fs = createZip(file)) {
doTranslate(fs.getPath("/"));
}
}
}
private static void doTranslate(Path file) throws IOException {
byte[] contents = new byte[] { 0x40, 0x41, 0x42 };
System.out.println("Translating path: " + file);
System.out.println("Creating: " + file.resolve("/a/b/c/").toAbsolutePath());
Files.createDirectories(file.resolve("/a/b/c/"));
Files.write(file.resolve("/a/b/c/a.txt"), contents);
Files.write(file.resolve("/a/b/c/A.txt"), contents);
System.out.println("Creating: " + file.resolve("/A/b/c/").toAbsolutePath());
Files.createDirectories(file.resolve("/A/b/c/"));
Files.write(file.resolve("/A/b/c/a.txt"), contents);
Files.write(file.resolve("/A/b/c/A.txt"), contents);
System.out.println("Creating: " + file.resolve("/a/b/C/").toAbsolutePath());
Files.createDirectories(file.resolve("/a/b/C/"));
Files.write(file.resolve("/a/b/C/a.txt"), contents);
Files.write(file.resolve("/a/b/C/A.txt"), contents);
}
private static FileSystem createZip(Path output) throws IOException {
Map<String, Object> env = new HashMap<>();
env.put("create", "true");
Files.deleteIfExists(output);
Path parent = output.getParent();
if (parent != null && !Files.exists(parent)) {
Files.createDirectories(parent);
}
for (FileSystemProvider p : FileSystemProvider.installedProviders()) {
System.out.println("Checking provider: " + p.getClass().getName());
String s = p.getScheme();
if ("jar".equals(s) || "zip".equalsIgnoreCase(s)) {
return p.newFileSystem(output, env);
}
}
throw new IOException("cant find zipfs support");
}
public static void main(String[] args) throws IOException {
to(new File("abc.zip").toPath());
System.out.println("Done");
}
}
If you run it on windows, you'll end up with "abc.zip" like the one I attached here.
Open it on 7-zip and you'll see a single root dir "a", followed by "b" and finally by "c". Inside there are 3 "a.txt"'s and 3 "A.txt"'s - the problem you mention.
However, list the file contents from the command line and all is well:
"jar tf abc.zip" or "unzip -l abc.zip":
Code:
a/
a/b/
a/b/c/
a/b/c/a.txt
a/b/c/A.txt
A/
A/b/
A/b/c/
A/b/c/a.txt
A/b/c/A.txt
a/b/C/
a/b/C/a.txt
a/b/C/A.txt
Open it in jd-gui and each package is separated, with A.txt and a.txt inside
Just wish I had not wasted so much time blindly trusting 7-zip's output and digging through the JRE's com.sun.nio.zipfs.ZipFileSystemProvider until remembering to use a command line listing of the archive contents.