Stephane Bury has released Arcana, a pure-Java archive library and command-line tool, with Maven coordinates io.github.realburst:arcana. The pitch is: ZIP, 7z, RAR 4 and 5, TAR and every compressor people wrap around it, CAB, MSI, CHM, CPIO, ISO 9660, UDF, WIM, SquashFS, DEB, RPM, XAR, self-extracting executables, with no native libraries, no JNI, no external dependencies, on Java 8 or later.
The per-format documentation adds DMG, HFS+, lzip, and lzop, and official plugins cover Quake PAK, UPX-packed executables, NSIS, Inno Setup, InstallShield, and JexePack. The README is behind the code, which is an issue, but it's a good issue as far as such things go.
Anyone who has had to open "whatever this file turns out to be" in a JVM process knows the shape of the alternative: Commons Compress for the common cases, a separate RAR library, something else for ISO (and related disk image formats!), a shell-out to 7z when all else fails, and a detection layer stitched in front of it all1.
Arcana collapses that into one JAR. It identifies by content, so a .docx or a .jar or an .epub is a ZIP as far as extraction is concerned, and it sanitizes entry names, stops on decompression bombs, and stops when the disk is nearly full.
The 7z support is rather impressive. The doc/formats/7z.md page lists the coders it decodes: Copy, LZMA, LZMA2, PPMd, BZip2, Deflate, Deflate64, Delta, the BCJ branch filters for x86, PPC, IA64, ARM, ARM-Thumb, SPARC, ARM64 and RISC-V, the Swap filters, BCJ2 with its four input streams, and AES-256. It walks the coder graph of a folder back through the bind pairs, so chains of arbitrary length work. Solid and non-solid folders, split volumes, and encrypted headers are handled, and the AES key-derivation round count is capped so a crafted archive cannot pin a CPU for hours. That is a more complete account of the format than most libraries offer2, and every format in the repository has a page like it: detection, layout, methods, limits, and the public documents the implementation was built from.
There are a few concerns with it, though: all are addressable but need addressing.
The LZMA, XZ, and BCJ code is XZ for Java, ported into the tree under be.stef.arcana.formats.xz and attributed under 0BSD. That is how "no dependencies" is achieved, and it is entirely legitimate, but it makes Arcana the maintainer of a fork, and how upstream fixes get tracked is a question the project should make apparent.
The plugin loader is another one: by default it scans ~/.arcana/plugins and a plugins directory next to the JAR and in the working directory, and loads what it finds. A system property redirects the search and a register() call loads plugins by code, so this is controllable, but an embedding application should pin the search path on purpose rather than discover it later, or use a ServiceLoader.
The library API is where the project shows its age as a CLI first. The facade takes File and InputStream, not Path or a channel. The extraction limits are public static fields, one setting shared by every extraction in flight, which is fine for a command line and awkward in a pipeline.
And the facade offers whole-archive extraction to disk or a metadata listing, with nothing between: no open-nth-entry, no filter, no visitor pattern. An ingestion pipeline would likely want to look at each entry and decide what to do with it, and today that means writing everything out and reading it back. The case for the other side is that the author's problem was a command-line tool that reads anything, and for that problem every one of these choices is correct.
All told, this is a pretty impressive early release. There are things that serve as low-hanging fruit for generalization, but making something better is usually far easier than creating something that wasn't there before. Well done.
-
Typically Tika, which has its own problems, despite being quite good for most cases. The problem is that you really need something like this for when the "normal cases" fail. Tika's extensible, thankfully, but the problem remains.
↩ -
It's definitely a more complete handling of the format than my attempt at it. Yeesh, I'm stunned.
↩
No comments yet.
Sign in to comment