public FunkyJar(final File file, boolean compress, final String version,
			final String author) throws IOException {
		super(new FileOutputStream(file));

		this.compress = compress;

		if (compress) {
			this.setMethod(ZipOutputStream.DEFLATED);
		} else {
			this.setMethod(ZipOutputStream.STORED);
		}

		final Manifest manifest = new Manifest();
		final Attributes global = manifest.getMainAttributes();
		if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) {
			global.put(Attributes.Name.MANIFEST_VERSION, version);
		}

		if (global.getValue(new Attributes.Name("Created-By")) == null) {
			global.put(new Attributes.Name("Created-By"), author);
		}

		// Add directory for manifest
		JarEntry entry = new JarEntry(FunkyJar.MANIFEST_DIR);
		entry.setTime(System.currentTimeMillis());
		entry.setSize(0); // Directories have size 0
		entry.setCrc(0); // Checksum is 0
		this.putNextEntry(entry);

		// Add manifest
		entry = new JarEntry(FunkyJar.MANIFEST);
		entry.setTime(System.currentTimeMillis());
		if (!compress) {
			// Have to compute checksum ourselves. Use an ugly anonymous
			// inner class. Influenced by CRC32OutputStream in
			// sun.tools.jar.Main. Please don't sue me. I have no money.
			// Maybe you could give me a job instead. Of course, then I'd
			// have money and you would sue me. Hmm.
			final Size size = new Size();
			FunkyJar.crc32.reset();
			manifest.write(new OutputStream() {
				public void write(final int r) throws IOException {
					FunkyJar.crc32.update(r);
					size.value++;
				}

				public void write(final byte[] b) throws IOException {
					FunkyJar.crc32.update(b, 0, b.length);
					size.value += b.length;
				}

				public void write(final byte[] b, final int off, final int len)
						throws IOException {
					FunkyJar.crc32.update(b, off, len);
					size.value += len - off;
				}
			});
			entry.setSize(size.value);
			entry.setCrc(FunkyJar.crc32.getValue());
		}
		this.putNextEntry(entry);
		manifest.write(this); // Write the manifest to JAR file
		this.closeEntry();
	}