package aQute.bnd.osgi;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import aQute.lib.zip.ZipUtil;

public class ZipResource implements Resource {
	ZipFile		zip;
	ZipEntry	entry;
	long		lastModified;
	String		extra;

	ZipResource(ZipFile zip, ZipEntry entry) throws UnsupportedEncodingException {
		this.zip = zip;
		this.entry = entry;
		this.lastModified = -11L;
		byte[] data = entry.getExtra();
		if (data != null)
			this.extra = new String(data, "UTF-8");
	}

	public InputStream openInputStream() throws IOException {
		return zip.getInputStream(entry);
	}

	@Override
	public String toString() {
		return ":" + zip.getName() + "(" + entry.getName() + "):";
	}

	public static ZipFile build(Jar jar, File file) throws ZipException, IOException {
		return build(jar, file, null);
	}

	public static ZipFile build(Jar jar, File file, Pattern pattern) throws ZipException, IOException {

		try {
			ZipFile zip = new ZipFile(file);
			nextEntry: for (Enumeration< ? extends ZipEntry> e = zip.entries(); e.hasMoreElements();) {
				ZipEntry entry = e.nextElement();
				if (pattern != null) {
					Matcher m = pattern.matcher(entry.getName());
					if (!m.matches())
						continue nextEntry;
				}
				if (!entry.isDirectory()) {

					jar.putResource(entry.getName(), new ZipResource(zip, entry), true);
				}
			}
			return zip;
		} catch (ZipException ze) {
			throw new ZipException(
					"The JAR/ZIP file (" + file.getAbsolutePath() + ") seems corrupted, error: " + ze.getMessage());
		} catch (FileNotFoundException e) {
			throw new IllegalArgumentException("Problem opening JAR: " + file.getAbsolutePath());
		}
	}

	public void write(OutputStream out) throws Exception {
		FileResource.copy(this, out);
	}

	public long lastModified() {
		try {
			if (lastModified == -11L) {
				lastModified = ZipUtil.getModifiedTime(entry);
			}
			return lastModified;
		} catch (IOException e) {
			return lastModified = -1;
		}
	}

	public String getExtra() {
		return extra;
	}

	public void setExtra(String extra) {
		this.extra = extra;
	}

	public long size() {
		return entry.getSize();
	}
}

@@ -1692,17 +1692,16 @@
 ion 
-z
 e) %7B%0A%09%09%09
 thro
@@ -1692,29 +1692,41 @@
 ion e) %7B%0A%09%09%09
-throw
+ZipException ze =
  new ZipExce
@@ -1816,17 +1816,16 @@
 or: %22 + 
-z
 e.getMes
@@ -1833,16 +1833,49 @@
 age());%0A
+%09%09%09ze.initCause(e);%0A%09%09%09throw ze;%0A
 %09%09%7D catc

Use original ZipException as cause of thrown ZipException