The Java java.util.jar package has an ancient pedigree. Unfortunately, it shows that the early Java engineers did not all understand object-oriented design. Consider writing a file into a JAR:
// Write foo.jar!bar/qux.txt
JarOutputStream jos
= new JarOutputStream(new File("foo.jar"));
jos.putNextEntry(new JarEntry("bar/qux.txt"));
writeContentsToOutputStream(jos);
jos.closeEntry();
jos.close(); Contrast with a more modern design:
NewerJarOutputStream newerJos
= new NewerJarOutputStream(jarFile);
JarEntryOutputStream entryJos= newerJos.openEntry("bar/qux.txt");
writeContentsToOutputStream(entryJos);
entryJos.close();
newerJos.close(); The whole business with putNextEntry/closeEntry is lame, and managing a separate JarEntry object is annoying. What would NewerJarOutputStream and JarEntryOutputStream look like?
class NewerJarOutputStream extends JarOutputStream {
public JarEntryOutputStream openEntry(final String name) {
return new JarEntryOutputStream(this, name);
}
}
class JarEntryOutputStream extends OutputStream {
private final NewerJarOutputStream jos;
public JarEntryOutputStream(final NewerJarOutputStream jos,
final String name) {
this.jos = jos;
jos.putNextEntry(new JarEntry(name));
}
public void write(final int b) {
jos.write(b);
}
@Override
public void close() {
jos.closeEntry();
}
} What I have actually written is a SignedJarOutputStream to provide programmatic JAR signing and the attendent classes such as SignedJarFile, et al. Unfortunately, the literature is a bit dowdy, and Sun provides very little help. But the task was interesting, and the JAR signing specification is elegant and well-considered even if over-sparse. Factum est.