You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/12/01 07:04:00 UTC

svn commit: r350181 [52/198] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/ depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/ depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/ depends/oss/win.I...

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarFile.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarFile.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarFile.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarFile.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,358 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.jar;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+
+/**
+ * JarFile is used to read jar entries and their associated data from jar files.
+ * 
+ * @see JarInputStream
+ * @see JarEntry
+ */
+public class JarFile extends java.util.zip.ZipFile {
+	public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
+
+	static final String META_DIR = "META-INF/";
+
+	private Manifest manifest;
+
+	private ZipEntry manifestEntry;
+
+	JarVerifier verifier;
+
+	static final class JarFileInputStream extends FilterInputStream {
+		private long count;
+
+		private ZipEntry zipEntry;
+
+		private JarVerifier verifier;
+
+		private JarVerifier.VerifierEntry entry;
+
+		private MessageDigest digest;
+
+		JarFileInputStream(InputStream is, ZipEntry ze, JarVerifier ver) {
+			super(is);
+			if (ver != null) {
+				zipEntry = ze;
+				verifier = ver;
+				count = zipEntry.getSize();
+				entry = verifier.initEntry(ze.getName());
+				if (entry != null)
+					digest = entry.digest;
+			}
+		}
+
+		public int read() throws IOException {
+			int r = super.read();
+			if (entry != null) {
+				if (r != -1) {
+					digest.update((byte) r);
+					count--;
+				}
+				if (r == -1 || count <= 0) {
+					JarVerifier.VerifierEntry temp = entry;
+					entry = null;
+					verifier.verifySignatures(temp, zipEntry);
+				}
+			}
+			return r;
+		}
+
+		public int read(byte[] buf, int off, int nbytes) throws IOException {
+			int r = super.read(buf, off, nbytes);
+			if (entry != null) {
+				if (r != -1) {
+					int size = r;
+					if (count < size)
+						size = (int) count;
+					digest.update(buf, off, size);
+					count -= r;
+				}
+				if (r == -1 || count <= 0) {
+					JarVerifier.VerifierEntry temp = entry;
+					entry = null;
+					verifier.verifySignatures(temp, zipEntry);
+				}
+			}
+			return r;
+		}
+
+		public long skip(long nbytes) throws IOException {
+			long cnt = 0, rem = 0;
+			byte[] buf = new byte[4096];
+			while (cnt < nbytes) {
+				int x = read(buf, 0,
+						(rem = nbytes - cnt) > buf.length ? buf.length
+								: (int) rem);
+				if (x == -1)
+					return cnt;
+				cnt += x;
+			}
+			return cnt;
+		}
+	}
+
+	/**
+	 * Create a new JarFile using the contents of file.
+	 * 
+	 * @param file
+	 *            java.io.File
+	 * @exception java.io.IOException
+	 *                If the file cannot be read.
+	 */
+	public JarFile(File file) throws IOException {
+		this(file, true);
+	}
+
+	/**
+	 * Create a new JarFile using the contents of file.
+	 * 
+	 * @param file
+	 *            java.io.File
+	 * @param verify
+	 *            verify a signed jar file
+	 * @exception java.io.IOException
+	 *                If the file cannot be read.
+	 */
+	public JarFile(File file, boolean verify) throws IOException {
+		super(file);
+		if (verify)
+			verifier = new JarVerifier(file.getPath());
+		readMetaEntries();
+	}
+
+	/**
+	 * Create a new JarFile using the contents of file.
+	 * 
+	 * @param file
+	 *            java.io.File
+	 * @param verify
+	 *            verify a signed jar file
+	 * @param mode
+	 *            the mode to use, either OPEN_READ or OPEN_READ | OPEN_DELETE
+	 * @exception java.io.IOException
+	 *                If the file cannot be read.
+	 */
+	public JarFile(File file, boolean verify, int mode) throws IOException {
+		super(file, mode);
+		if (verify)
+			verifier = new JarVerifier(file.getPath());
+		readMetaEntries();
+	}
+
+	/**
+	 * Create a new JarFile from the contents of the file specified by filename.
+	 * 
+	 * @param filename
+	 *            java.lang.String
+	 * @exception java.io.IOException
+	 *                If fileName cannot be opened for reading.
+	 */
+	public JarFile(String filename) throws IOException {
+		this(filename, true);
+
+	}
+
+	/**
+	 * Create a new JarFile from the contents of the file specified by filename.
+	 * 
+	 * @param filename
+	 *            java.lang.String
+	 * @param verify
+	 *            verify a signed jar file
+	 * @exception java.io.IOException
+	 *                If fileName cannot be opened for reading.
+	 */
+	public JarFile(String filename, boolean verify) throws IOException {
+		super(filename);
+		if (verify)
+			verifier = new JarVerifier(filename);
+		readMetaEntries();
+	}
+
+	/**
+	 * Return an enumeration containing the JarEntrys contained in this JarFile.
+	 * 
+	 * @return java.util.Enumeration
+	 * @exception java.lang.IllegalStateException
+	 *                If this JarFile has been closed.
+	 */
+	public Enumeration entries() {
+		class JarFileEnumerator implements Enumeration {
+			Enumeration ze;
+
+			JarFile jf;
+
+			JarFileEnumerator(Enumeration zenum, JarFile jf) {
+				ze = zenum;
+				this.jf = jf;
+			}
+
+			public boolean hasMoreElements() {
+				return ze.hasMoreElements();
+			}
+
+			public Object nextElement() {
+				JarEntry je = new JarEntry((ZipEntry) ze.nextElement());
+				je.parentJar = jf;
+				if (verifier != null)
+					je.certificates = verifier.getCertificates(je.getName());
+				return je;
+			}
+		}
+		return new JarFileEnumerator(super.entries(), this);
+	}
+
+	/**
+	 * Return the JarEntry specified by name or null if no such entry exists.
+	 * 
+	 * @param name
+	 *            the name of the entry in the jar file
+	 * @return java.util.jar.JarEntry
+	 */
+	public JarEntry getJarEntry(String name) {
+		return (JarEntry) getEntry(name);
+	}
+
+	/**
+	 * Returns the Manifest object associated with this JarFile or null if no
+	 * manifest entry exists.
+	 * 
+	 * @return java.util.jar.Manifest
+	 */
+	public Manifest getManifest() throws IOException {
+		if (manifest != null)
+			return manifest;
+		if (manifestEntry != null) {
+			ByteArrayInputStream is = (ByteArrayInputStream) super
+					.getInputStream(manifestEntry);
+			if (verifier != null) {
+				byte[] buf = new byte[is.available()];
+				is.mark(buf.length);
+				is.read(buf, 0, buf.length);
+				is.reset();
+				verifier.addMetaEntry(manifestEntry.getName(), buf);
+			}
+			try {
+				manifest = new Manifest(is, verifier != null);
+			} finally {
+				is.close();
+			}
+			manifestEntry = null;
+		}
+		return manifest;
+	}
+
+	private void readMetaEntries() throws IOException {
+		ZipEntry[] metaEntries = this.getMetaEntriesImpl(null);
+		int dirLength = META_DIR.length();
+
+		boolean signed = false;
+		if (null != metaEntries) {
+			for (int i = 0; i < metaEntries.length; i++) {
+				ZipEntry entry = metaEntries[i];
+				String entryName = entry.getName();
+				if (manifestEntry == null
+						&& manifest == null
+						&& entryName.regionMatches(true, dirLength,
+								MANIFEST_NAME, dirLength, MANIFEST_NAME
+										.length()
+										- dirLength)) {
+					manifestEntry = entry;
+					if (verifier == null)
+						break;
+				} else if (verifier != null
+						&& entryName.length() > dirLength
+						&& (entryName.regionMatches(true,
+								entryName.length() - 3, ".SF", 0, 3)
+								|| entryName.regionMatches(true, entryName
+										.length() - 4, ".DSA", 0, 4) || entryName
+								.regionMatches(true, entryName.length() - 4,
+										".RSA", 0, 4))) {
+					signed = true;
+					if (manifest == null)
+						verifier.setManifest(getManifest());
+					InputStream is = super.getInputStream(entry);
+					byte[] buf = new byte[is.available()];
+					is.read(buf, 0, buf.length);
+					is.close();
+					verifier.addMetaEntry(entryName, buf);
+				}
+			}
+		}
+		if (!signed)
+			verifier = null;
+	}
+
+	/**
+	 * Return an InputStream for reading the decompressed contents of ze.
+	 * 
+	 * @param ze
+	 *            the ZipEntry to read from
+	 * @return java.io.InputStream
+	 * @exception java.io.IOException
+	 *                If an error occured while creating the InputStream.
+	 */
+	public InputStream getInputStream(ZipEntry ze) throws IOException {
+		if (manifestEntry != null)
+			getManifest();
+		if (verifier != null) {
+			if (verifier.readCertificates()) {
+				verifier.removeMetaEntries();
+				if (manifest != null)
+					manifest.removeChunks();
+				if (!verifier.isSignedJar())
+					verifier = null;
+			}
+		}
+		InputStream in = super.getInputStream(ze);
+		if (in == null)
+			return null;
+		return new JarFileInputStream(in, ze, ze.getSize() >= 0 ? verifier
+				: null);
+	}
+
+	/**
+	 * Return the JarEntry specified by name or null if no such entry exists
+	 * 
+	 * @param name
+	 *            the name of the entry in the jar file
+	 * @return java.util.jar.JarEntry
+	 */
+	public ZipEntry getEntry(String name) {
+		ZipEntry ze = super.getEntry(name);
+		if (ze == null)
+			return ze;
+		JarEntry je = new JarEntry(ze);
+		je.parentJar = this;
+		if (verifier != null)
+			je.certificates = verifier.getCertificates(je.getName());
+		return je;
+	}
+
+	private native ZipEntry[] getMetaEntriesImpl(byte[] buf);
+
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,155 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.jar;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class JarInputStream extends ZipInputStream {
+
+	private Manifest manifest;
+
+	private boolean eos = false;
+
+	private JarEntry mEntry;
+
+	private JarEntry jarEntry;
+
+	private boolean isMeta;
+
+	private JarVerifier verifier;
+
+	private OutputStream verStream;
+
+	/**
+	 * Constructs a new JarInputStream from stream
+	 */
+	public JarInputStream(InputStream stream, boolean verify)
+			throws IOException {
+		super(stream);
+		if (verify)
+			verifier = new JarVerifier("JarInputStream");
+		if ((mEntry = getNextJarEntry()) == null)
+			return;
+		String name = mEntry.getName().toUpperCase();
+		if (name.equals(JarFile.META_DIR)) {
+			mEntry = null; // modifies behavior of getNextJarEntry()
+			closeEntry();
+			mEntry = getNextJarEntry();
+			name = mEntry.getName().toUpperCase();
+		}
+		if (name.equals(JarFile.MANIFEST_NAME)) {
+			mEntry = null;
+			manifest = new Manifest(this, verify);
+			closeEntry();
+			if (verify)
+				verifier.setManifest(manifest);
+		} else {
+			Attributes temp = new Attributes(3);
+			temp.map.put("hidden", null);
+			mEntry.setAttributes(temp);
+		}
+	}
+
+	public JarInputStream(InputStream stream) throws IOException {
+		this(stream, true);
+	}
+
+	/**
+	 * Returns the Manifest object associated with this JarInputStream or null
+	 * if no manifest entry exists.
+	 * 
+	 * @return java.util.jar.Manifest
+	 */
+	public Manifest getManifest() {
+		return manifest;
+	}
+
+	/**
+	 * Returns the next JarEntry contained in this stream or null if no more
+	 * entries are present.
+	 * 
+	 * @return java.util.jar.JarEntry
+	 * @exception java.io.IOException
+	 *                If an error occurs while reading the entry
+	 */
+	public JarEntry getNextJarEntry() throws IOException {
+		return (JarEntry) getNextEntry();
+	}
+
+	public int read(byte[] buffer, int offset, int length) throws IOException {
+		if (mEntry != null)
+			return -1;
+		int r = super.read(buffer, offset, length);
+		if (verStream != null && !eos) {
+			if (r == -1) {
+				eos = true;
+				if (isMeta) {
+					verifier.addMetaEntry(jarEntry.getName(),
+							((ByteArrayOutputStream) verStream).toByteArray());
+					verifier.readCertificates();
+				} else
+					verifier.verifySignatures(
+							(JarVerifier.VerifierEntry) verStream, jarEntry);
+			} else
+				verStream.write(buffer, offset, r);
+		}
+		return r;
+	}
+
+	/**
+	 * Returns the next ZipEntry contained in this stream or null if no more
+	 * entries are present.
+	 * 
+	 * @return java.util.zip.ZipEntry
+	 * @exception java.io.IOException
+	 *                If an error occurs while reading the entry
+	 */
+	public ZipEntry getNextEntry() throws IOException {
+		eos = false;
+		if (mEntry != null) {
+			jarEntry = mEntry;
+			mEntry = null;
+			jarEntry.setAttributes(null);
+			return jarEntry;
+		}
+		jarEntry = (JarEntry) super.getNextEntry();
+		if (jarEntry == null)
+			return null;
+		if (verifier != null) {
+			isMeta = jarEntry.getName().toUpperCase().startsWith(
+					JarFile.META_DIR);
+			if (isMeta) {
+				verStream = new ByteArrayOutputStream();
+			} else {
+				verStream = verifier.initEntry(jarEntry.getName());
+			}
+		}
+		return jarEntry;
+	}
+
+	protected ZipEntry createZipEntry(String name) {
+		JarEntry entry = new JarEntry(name);
+		if (manifest != null)
+			entry.setAttributes(manifest.getAttributes(name));
+		return entry;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarOutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarOutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarOutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,79 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.jar;
+
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * The JarOutputStream is used to output data in JarFile format.
+ */
+public class JarOutputStream extends ZipOutputStream {
+
+	private Manifest manifest;
+
+	/**
+	 * Contructs a new JarOuputStream using os as the underlying stream.
+	 * Manifest information for the JarFile to be written is obtained from the
+	 * parameter Manifest, mf.
+	 * 
+	 * @param os
+	 *            The OutputStream to write to
+	 * @param mf
+	 *            The Manifest to output for this Jar.
+	 * @exception IOException
+	 *                If an error occurs creating the JarOutputStream
+	 */
+	public JarOutputStream(OutputStream os, Manifest mf) throws IOException {
+		super(os);
+		if (mf == null)
+			throw new NullPointerException();
+		manifest = mf;
+		ZipEntry ze = new ZipEntry(JarFile.MANIFEST_NAME);
+		putNextEntry(ze);
+		manifest.write(this);
+		closeEntry();
+	}
+
+	/**
+	 * Contructs a new JarOuputStream using os as the underlying stream.
+	 * 
+	 * @param os
+	 *            The OutputStream to write to
+	 * @exception IOException
+	 *                If an error occurs creating the JarOutputStream
+	 */
+	public JarOutputStream(OutputStream os) throws IOException {
+		super(os);
+	}
+
+	/**
+	 * Writes the specified entry to the underlying stream. The previous entry
+	 * is closed if it is still open.
+	 * 
+	 * 
+	 * @param ze
+	 *            The ZipEntry to write
+	 * @exception IOException
+	 *                If an error occurs writing the entry
+	 */
+	public void putNextEntry(ZipEntry ze) throws IOException {
+		super.putNextEntry(ze);
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarVerifier.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarVerifier.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarVerifier.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/JarVerifier.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,467 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.jar;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+
+import com.ibm.oti.util.BASE64Decoder;
+import com.ibm.oti.util.JarUtils;
+import com.ibm.oti.util.Msg;
+
+/**
+ * Non-public class used by {@link java.util.jar.JarFile} and
+ * {@link java.util.jar.JarInputStream} to manage the verification of signed
+ * jars. <code>JarFile</code> and <code>JarInputStream</code> objects will
+ * be expected to have a <code>JarVerifier</code> instance member which can be
+ * used to carry out the tasks associated with verifying a signed jar. These
+ * tasks would typically include:
+ * <ul>
+ * <li>verification of all signed signature files
+ * <li>confirmation that all signed data was signed only by the party or
+ * parties specified in the signature block data
+ * <li>verification that the contents of all signature files (i.e.
+ * <code>.SF</code> files) agree with the jar entries information found in the
+ * jar maifest.
+ * </ul>
+ */
+class JarVerifier {
+
+	private String jarName;
+
+	private Manifest man;
+
+	private HashMap metaEntries = new HashMap(5);
+
+	private Hashtable signatures = new Hashtable(5);
+
+	private Hashtable certificates = new Hashtable(5);
+
+	private Hashtable verifiedEntries = new Hashtable();
+
+	/**
+	 * TODO Type description
+	 */
+	static class VerifierEntry extends OutputStream {
+		/**
+		 * Comment for <code>digest</code>
+		 */
+		MessageDigest digest;
+
+		/**
+		 * Comment for <code>hash</code>
+		 */
+		byte[] hash;
+
+		/**
+		 * Comment for <code>certificates</code>
+		 */
+		java.security.cert.Certificate[] certificates;
+
+		/**
+		 * @param digest
+		 * @param hash
+		 * @param certificates
+		 */
+		VerifierEntry(MessageDigest digest, byte[] hash,
+				java.security.cert.Certificate[] certificates) {
+			this.digest = digest;
+			this.hash = hash;
+			this.certificates = certificates;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see java.io.OutputStream#write(int)
+		 */
+		public void write(int value) {
+			digest.update((byte) value);
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see java.io.OutputStream#write(byte[], int, int)
+		 */
+		public void write(byte[] buf, int off, int nbytes) {
+			digest.update(buf, off, nbytes);
+		}
+	}
+
+	/**
+	 * Constructs and answers with a new instance of JarVerifier.
+	 * 
+	 * @param name
+	 *            the name of the jar file being verified.
+	 */
+	JarVerifier(String name) {
+		jarName = name;
+	}
+
+	/**
+	 * Called for each new jar entry read in from the input stream. This method
+	 * constructs and returns a new {@link VerifierEntry} which contains the
+	 * certificates used to sign the entry and its hash value as specified in
+	 * the jar manifest.
+	 * 
+	 * @param name
+	 *            the name of an entry in a jar file which is <b>not</b> in the
+	 *            <code>META-INF</code> directory.
+	 * @return a new instance of {@link VerifierEntry} which can be used by
+	 *         callers as an {@link OutputStream}.
+	 */
+	VerifierEntry initEntry(String name) {
+		// If no manifest is present by the time an entry is found,
+		// verification cannot occur. If no signature files have
+		// been found, do not verify.
+		if (man == null || signatures.size() == 0)
+			return null;
+
+		Attributes attributes = man.getAttributes(name);
+		// entry has no digest
+		if (attributes == null)
+			return null;
+
+		Vector certs = new Vector();
+		Iterator it = signatures.entrySet().iterator();
+		while (it.hasNext()) {
+			Map.Entry entry = (Map.Entry) it.next();
+			HashMap hm = (HashMap) entry.getValue();
+			if (hm.get(name) != null) {
+				// Found an entry for entry name in .SF file
+				String signatureFile = (String) entry.getKey();
+
+				Vector newCerts = getSignerCertificates(signatureFile,
+						certificates);
+				Iterator iter = newCerts.iterator();
+				while (iter.hasNext()) {
+					certs.add(iter.next());
+				}
+			}
+		}
+
+		// entry is not signed
+		if (certs.size() == 0)
+			return null;
+		Certificate[] certificatesArray = new Certificate[certs.size()];
+		certs.toArray(certificatesArray);
+
+		String algorithms = attributes.getValue("Digest-Algorithms");
+		if (algorithms == null)
+			algorithms = "SHA SHA1";
+		StringTokenizer tokens = new StringTokenizer(algorithms);
+		while (tokens.hasMoreTokens()) {
+			String algorithm = tokens.nextToken();
+			String hash = attributes.getValue(algorithm + "-Digest");
+			if (hash == null)
+				continue;
+			byte[] hashBytes;
+			try {
+				hashBytes = hash.getBytes("ISO8859_1");
+			} catch (UnsupportedEncodingException e) {
+				throw new RuntimeException(e.toString());
+			}
+
+			try {
+				return new VerifierEntry(MessageDigest.getInstance(algorithm),
+						hashBytes, certificatesArray);
+			} catch (NoSuchAlgorithmException e) {
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Add a new meta entry to the internal collection of data held on each jar
+	 * entry in the <code>META-INF</code> directory including the manifest
+	 * file itself. Files associated with the signing of a jar would also be
+	 * added to this collection.
+	 * 
+	 * @param name
+	 *            the name of the file located in the <code>META-INF</code>
+	 *            directory.
+	 * @param buf
+	 *            the file bytes for the file called <code>name</code>.
+	 * @see #removeMetaEntries()
+	 */
+	void addMetaEntry(String name, byte[] buf) {
+		metaEntries.put(name.toUpperCase(), buf);
+	}
+
+	/**
+	 * If the associated jar file is signed, check on the validity of all of the
+	 * known signatures.
+	 * 
+	 * @return <code>true</code> if the associated jar is signed and an
+	 *         internal check verifies the validity of the signature(s).
+	 *         <code>false</code> if the associated jar file has no entries at
+	 *         all in its <code>META-INF</code> directory. This situation is
+	 *         indicative of an invalid jar file.
+	 *         <p>
+	 *         Will also return true if the jar file is <i>not</i> signed.
+	 *         </p>
+	 * @throws SecurityException
+	 *             if the jar file is signed and it is determined that a
+	 *             signature block file contains an invalid signature for the
+	 *             corresponding signature file.
+	 */
+	synchronized boolean readCertificates() {
+		if (metaEntries == null)
+			return false;
+		Iterator it = metaEntries.keySet().iterator();
+		while (it.hasNext()) {
+			String key = (String) it.next();
+			if (key.endsWith(".DSA") || key.endsWith(".RSA")) {
+				verifyCertificate(key);
+				// Check for recursive class load
+				if (metaEntries == null)
+					return false;
+				it.remove();
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * @param certFile
+	 */
+	private void verifyCertificate(String certFile) {
+		// Found Digital Sig, .SF should already have been read
+		String signatureFile = certFile.substring(0, certFile.lastIndexOf('.'))
+				+ ".SF";
+		byte[] sfBytes = (byte[]) metaEntries.get(signatureFile);
+		if (sfBytes == null)
+			return;
+
+		byte[] sBlockBytes = (byte[]) metaEntries.get(certFile);
+		try {
+			Certificate[] signerCertChain = JarUtils.verifySignature(
+					new ByteArrayInputStream(sfBytes),
+					new ByteArrayInputStream(sBlockBytes));
+			if (signerCertChain != null) {
+				this.certificates.put(signatureFile, signerCertChain);
+			}
+		} catch (IOException e) {
+			return;
+		} catch (GeneralSecurityException e) {
+			/* [MSG "K00eb", "{0} failed verification of {1}"] */
+			throw new SecurityException(Msg.getString("K00eb", jarName,
+					signatureFile));
+		}
+
+		// Verify manifest hash in .sf file
+		Attributes attributes = new Attributes();
+		HashMap hm = new HashMap();
+		try {
+			new InitManifest(new ByteArrayInputStream(sfBytes), attributes, hm,
+					null, "Signature-Version");
+		} catch (IOException e) {
+			return;
+		}
+
+		boolean createdBySigntool = false;
+		String createdByValue = attributes.getValue("Created-By");
+		if (createdByValue != null) {
+			createdBySigntool = createdByValue.indexOf("signtool") != -1;
+		}
+		byte[] manifest = (byte[]) metaEntries.get(JarFile.MANIFEST_NAME);
+		if (manifest == null)
+			return;
+		String digestAttribute = createdBySigntool ? "-Digest"
+				: "-Digest-Manifest";
+		if (!verify(attributes, digestAttribute, manifest, false)) {
+			Iterator it = hm.entrySet().iterator();
+			while (it.hasNext()) {
+				Map.Entry entry = (Map.Entry) it.next();
+				byte[] chunk = man.getChunk((String) entry.getKey());
+				if (chunk == null)
+					return;
+				if (!verify((Attributes) entry.getValue(), "-Digest", chunk,
+						createdBySigntool))
+					/* [MSG "K00ec", "{0} has invalid digest for {1} in {2}"] */
+					throw new SecurityException(Msg.getString("K00ec",
+							new Object[] { signatureFile, entry.getKey(),
+									jarName }));
+			}
+		}
+		metaEntries.put(signatureFile, null);
+		signatures.put(signatureFile, hm);
+	}
+
+	/**
+	 * Associate this verifier with the specified {@link Manifest} object.
+	 * 
+	 * @param mf
+	 *            a <code>java.util.jar.Manifest</code> object.
+	 */
+	void setManifest(Manifest mf) {
+		man = mf;
+	}
+
+	/**
+	 * Verifies that the digests stored in the manifest match the decrypted
+	 * digests from the .SF file. This indicates the validity of the signing,
+	 * not the integrity of the file, as it's digest must be calculated and
+	 * verified when its contents are read.
+	 * 
+	 * @param entry
+	 *            the {@link VerifierEntry} associated with the specified
+	 *            <code>zipEntry</code>.
+	 * @param zipEntry
+	 *            an entry in the jar file
+	 * @throws SecurityException
+	 *             if the digest value stored in the manifest does <i>not</i>
+	 *             agree with the decrypted digest as recovered from the
+	 *             <code>.SF</code> file.
+	 * @see #initEntry(String)
+	 */
+	void verifySignatures(VerifierEntry entry, ZipEntry zipEntry) {
+		byte[] digest = entry.digest.digest();
+		if (!MessageDigest.isEqual(digest, BASE64Decoder.decode(entry.hash)))
+			/* [MSG "K00ec", "{0} has invalid digest for {1} in {2}"] */
+			throw new SecurityException(Msg.getString("K00ec", new Object[] {
+					JarFile.MANIFEST_NAME, zipEntry.getName(), jarName }));
+		verifiedEntries.put(zipEntry.getName(), entry.certificates);
+		if (zipEntry instanceof JarEntry)
+			((JarEntry) zipEntry).certificates = (Certificate[]) entry.certificates
+					.clone();
+	}
+
+	/**
+	 * Returns a <code>boolean</code> indication of whether or not the
+	 * associated jar file is signed.
+	 * 
+	 * @return <code>true</code> if the jar is signed, <code>false</code>
+	 *         otherwise.
+	 */
+	boolean isSignedJar() {
+		return certificates.size() > 0;
+	}
+
+	/*
+	 * @param attributes @param entry @param data @param ignoreSecondEndline
+	 * @return
+	 */
+	private boolean verify(Attributes attributes, String entry, byte[] data,
+			boolean ignoreSecondEndline) {
+		String algorithms = attributes.getValue("Digest-Algorithms");
+		if (algorithms == null)
+			algorithms = "SHA SHA1";
+		StringTokenizer tokens = new StringTokenizer(algorithms);
+		while (tokens.hasMoreTokens()) {
+			String algorithm = tokens.nextToken();
+			String hash = attributes.getValue(algorithm + entry);
+			if (hash == null)
+				continue;
+
+			MessageDigest md;
+			try {
+				md = MessageDigest.getInstance(algorithm);
+			} catch (NoSuchAlgorithmException e) {
+				continue;
+			}
+			if (ignoreSecondEndline && data[data.length - 1] == '\n'
+					&& data[data.length - 2] == '\n') {
+				md.update(data, 0, data.length - 1);
+			} else {
+				md.update(data, 0, data.length);
+			}
+			byte[] b = md.digest();
+			byte[] hashBytes;
+			try {
+				hashBytes = hash.getBytes("ISO8859_1");
+			} catch (UnsupportedEncodingException e) {
+				throw new RuntimeException(e.toString());
+			}
+			return MessageDigest.isEqual(b, BASE64Decoder.decode(hashBytes));
+		}
+		return false;
+	}
+
+	/**
+	 * Returns all of the {@link java.security.cert.Certificate} instances that
+	 * were used to verify the signature on the jar entry called
+	 * <code>name</code>.
+	 * 
+	 * @param name
+	 *            the name of a jar entry.
+	 * @return an array of {@link java.security.cert.Certificate}.
+	 */
+	Certificate[] getCertificates(String name) {
+		Certificate[] verifiedCerts = (Certificate[]) verifiedEntries.get(name);
+		if (verifiedCerts == null) {
+			return null;
+		}
+		return (Certificate[]) verifiedCerts.clone();
+	}
+
+	/**
+	 * Remove all entries from the internal collection of data held about each
+	 * jar entry in the <code>META-INF</code> directory.
+	 * 
+	 * @see #addMetaEntry(String, byte[])
+	 */
+	void removeMetaEntries() {
+		metaEntries = null;
+	}
+
+	/**
+	 * Returns a <code>Vector</code> of all of the
+	 * {@link java.security.cert.Certificate}s that are associated with the
+	 * signing of the named signature file.
+	 * 
+	 * @param signatureFileName
+	 *            the name of a signature file
+	 * @param certificates
+	 *            a <code>Map</code> of all of the certificate chains
+	 *            discovered so far while attempting to verify the jar that
+	 *            contains the signature file <code>signatureFileName</code>.
+	 *            This object will have been previously set in the course of one
+	 *            or more calls to
+	 *            {@link #verifyJarSignatureFile(String, String, String, Map, Map)}
+	 *            where it was passed in as the last argument.
+	 * @return all of the <code>Certificate</code> entries for the signer of
+	 *         the jar whose actions led to the creation of the named signature
+	 *         file.
+	 */
+	public static Vector getSignerCertificates(String signatureFileName,
+			Map certificates) {
+		Vector result = new Vector();
+		Certificate[] certChain = (Certificate[]) certificates
+				.get(signatureFileName);
+		if (certChain != null) {
+			for (int i = 0; i < certChain.length; i++) {
+				result.add(certChain[i]);
+			}// end for all certificates
+		}// end if at least one cert found
+		return result;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/Manifest.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/Manifest.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/Manifest.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/jar/Manifest.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,312 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.jar;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.security.AccessController;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import com.ibm.oti.util.PriviAction;
+
+/**
+ * The Manifest class is used to obtain attribute information for a JarFile and
+ * it's entries.
+ * 
+ */
+public class Manifest implements Cloneable {
+	private Attributes mainAttributes = new Attributes();
+
+	private HashMap entryAttributes = new HashMap();
+
+	private HashMap chunks;
+
+	/**
+	 * Contructs a new Manifest instance.
+	 */
+	public Manifest() {
+	}
+
+	/**
+	 * Contructs a new Manifest instance using the attributes obtained from is.
+	 * 
+	 * @param is
+	 *            InputStream to parse for attributes
+	 * 
+	 * @throws IOException
+	 *             if an IO error occurs while creating this Manifest
+	 * 
+	 */
+	public Manifest(InputStream is) throws IOException {
+		read(is);
+	}
+
+	Manifest(InputStream is, boolean readChunks) throws IOException {
+		if (readChunks)
+			chunks = new HashMap();
+		read(is);
+	}
+
+	/**
+	 * Resets the both the mainAttributes as well as the entry Attributes
+	 * associated with this Manifest.
+	 */
+	public void clear() {
+		entryAttributes.clear();
+		mainAttributes.clear();
+	}
+
+	/**
+	 * Returns the Attributes associated with the parameter entry name
+	 * 
+	 * @param name
+	 *            The name of the entry to obtain Attributes for.
+	 * @return The Attributes for the entry or null if the entry does not exist.
+	 */
+	public Attributes getAttributes(String name) {
+		return (Attributes) getEntries().get(name);
+	}
+
+	/**
+	 * Returns a Map containing the Attributes for each entry in the Manifest.
+	 * 
+	 * @return A Map of entry attributes
+	 */
+	public Map getEntries() {
+		return entryAttributes;
+	}
+
+	/**
+	 * Returns the main Attributes of the JarFile.
+	 * 
+	 * @return Main Attributes associated with the source JarFile
+	 */
+	public Attributes getMainAttributes() {
+		return mainAttributes;
+	}
+
+	/**
+	 * Contructs a new Manifest instance. The new instance will have the same
+	 * attributes as those found in the parameter Manifest.
+	 * 
+	 * @param man
+	 *            Manifest instance to obtain attributes from
+	 */
+	public Manifest(Manifest man) {
+		mainAttributes = (Attributes) man.mainAttributes.clone();
+		entryAttributes = (HashMap) man.entryAttributes.clone();
+	}
+
+	/**
+	 * Creates a copy of this Manifest. The returned Manifest will equal the
+	 * Manifest from which it was cloned.
+	 * 
+	 * @return A copy of the receiver.
+	 */
+	public Object clone() {
+		return new Manifest(this);
+	}
+
+	static class WriteManifest {
+		private static final int LIMIT = 70;
+
+		private static byte[] sepBuf = new byte[] { '\r', '\n' };
+
+		private static Attributes.Name nameAttribute = new Attributes.Name(
+				"Name", false);
+
+		byte[] oneByte = new byte[1];
+
+		char[] oneChar = new char[1];
+
+		private Charset charset;
+
+		private byte[] outBuf = new byte[LIMIT];
+
+		OutputStream os;
+
+		/**
+		 * Writes out a manifest entry.
+		 */
+		private void writeEntry(Attributes.Name name, String value)
+				throws IOException {
+			int offset = 0, limit = LIMIT;
+			byte[] out = (name.toString() + ": ").getBytes("ISO8859_1");
+			if (out.length > limit) {
+				while (out.length - offset >= limit) {
+					int len = out.length - offset;
+					if (len > limit)
+						len = limit;
+					if (offset > 0)
+						os.write(' ');
+					os.write(out, offset, len);
+					os.write(sepBuf);
+					offset += len;
+					limit = LIMIT - 1;
+				}
+			}
+			int size = out.length - offset;
+			System.arraycopy(out, offset, outBuf, 0, size);
+			for (int i = 0; i < value.length(); i++) {
+				oneChar[0] = value.charAt(i);
+				byte[] buf;
+				if (oneChar[0] < 128 || charset == null) {
+					oneByte[0] = (byte) oneChar[0];
+					buf = oneByte;
+				} else
+					buf = charset.encode(CharBuffer.wrap(oneChar, 0, 1)).array();
+				if (size + buf.length > limit) {
+					if (limit != LIMIT)
+						os.write(' ');
+					os.write(outBuf, 0, size);
+					os.write(sepBuf);
+					limit = LIMIT - 1;
+					size = 0;
+				}
+				if (buf.length == 1)
+					outBuf[size] = buf[0];
+				else
+					System.arraycopy(buf, 0, outBuf, size, buf.length);
+				size += buf.length;
+			}
+			if (size > 0) {
+				if (limit != LIMIT)
+					os.write(' ');
+				os.write(outBuf, 0, size);
+				os.write(sepBuf);
+			}
+		}
+
+		/**
+		 * Writes out the attribute information of the receiver to the specified
+		 * OutputStream
+		 * 
+		 * 
+		 * @param manifest
+		 *            the attribute information of the receiver
+		 * @param out
+		 *            The OutputStream to write to.
+		 * 
+		 * @throws IOException
+		 *             If an error occurs writing the Manifest
+		 */
+		void write(Manifest manifest, OutputStream out) throws IOException {
+			os = out;
+			String encoding = (String) AccessController
+					.doPrivileged(new PriviAction("manifest.write.encoding"));
+			if (encoding != null) {
+				if ("".equals(encoding))
+					encoding = "UTF8";
+				charset = Charset.forName(encoding);				
+			}
+			String version = manifest.mainAttributes
+					.getValue(Attributes.Name.MANIFEST_VERSION);
+			if (version != null) {
+				writeEntry(Attributes.Name.MANIFEST_VERSION, version);
+				Iterator entries = manifest.mainAttributes.keySet().iterator();
+				while (entries.hasNext()) {
+					Attributes.Name name = (Attributes.Name) entries.next();
+					if (!name.equals(Attributes.Name.MANIFEST_VERSION))
+						writeEntry(name, manifest.mainAttributes.getValue(name));
+				}
+			}
+			os.write(sepBuf);
+			Iterator i = manifest.entryAttributes.keySet().iterator();
+			while (i.hasNext()) {
+				String key = (String) i.next();
+				writeEntry(nameAttribute, key);
+				Attributes attrib = (Attributes) manifest.entryAttributes
+						.get(key);
+				Iterator entries = attrib.keySet().iterator();
+				while (entries.hasNext()) {
+					Attributes.Name name = (Attributes.Name) entries.next();
+					writeEntry(name, attrib.getValue(name));
+				}
+				os.write(sepBuf);
+			}
+		}
+	}
+
+	/**
+	 * Writes out the attribute information of the receiver to the specified
+	 * OutputStream
+	 * 
+	 * @param os
+	 *            The OutputStream to write to.
+	 * 
+	 * @throws IOException
+	 *             If an error occurs writing the Manifest
+	 */
+	public void write(OutputStream os) throws IOException {
+		new WriteManifest().write(this, os);
+	}
+
+	/**
+	 * Contructs a new Manifest instance obtaining Attribute information from
+	 * the paramter InputStream.
+	 * 
+	 * @param is
+	 *            The InputStream to read from
+	 * @throws IOException
+	 *             If an error occurs reading the Manifest.
+	 */
+	public void read(InputStream is) throws IOException {
+		new InitManifest(is, mainAttributes, entryAttributes, chunks, null);
+	}
+
+	/**
+	 * Returns the hashCode for this instance.
+	 * 
+	 * @return This Manifest's hashCode
+	 */
+	public int hashCode() {
+		return mainAttributes.hashCode() ^ entryAttributes.hashCode();
+	}
+
+	/**
+	 * Determines if the receiver is equal to the parameter Object. Two
+	 * Manifests are equal if they have identical main Attributes as well as
+	 * identical entry Attributes.
+	 * 
+	 * @param o
+	 *            The Object to compare against.
+	 * @return <code>true</code> if the manifests are equal,
+	 *         <code>false</code> otherwise
+	 */
+	public boolean equals(Object o) {
+		if (o == null)
+			return false;
+		if (o.getClass() != this.getClass())
+			return false;
+		if (!mainAttributes.equals(((Manifest) o).mainAttributes))
+			return false;
+		return entryAttributes.equals(((Manifest) o).entryAttributes);
+	}
+
+	byte[] getChunk(String name) {
+		return (byte[]) chunks.get(name);
+	}
+
+	void removeChunks() {
+		chunks = null;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Adler32.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Adler32.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Adler32.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Adler32.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,85 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+/**
+ * The Adler32 class is used to compute the Adler32 Checksum from a set of data.
+ */
+public class Adler32 implements java.util.zip.Checksum {
+
+	private long adler = 1;
+
+	/**
+	 * Returns the Adler32 checksum for all input received
+	 * 
+	 * @return The checksum for this instance
+	 */
+	public long getValue() {
+		return adler;
+	}
+
+	/**
+	 * Reset this instance to its initial checksum
+	 */
+	public void reset() {
+		adler = 1;
+	}
+
+	/**
+	 * Update this Adler32 checksum using val.
+	 * 
+	 * @param i
+	 *            byte to update checksum with
+	 */
+	public void update(int i) {
+		adler = updateByteImpl(i, adler);
+	}
+
+	/**
+	 * Update this Adler32 checksum using the contents of buf.
+	 * 
+	 * @param buf
+	 *            bytes to update checksum with
+	 */
+	public void update(byte[] buf) {
+		update(buf, 0, buf.length);
+	}
+
+	/**
+	 * Update this Adler32 checksum with the contents of buf, starting from
+	 * offset and using nbytes of data.
+	 * 
+	 * @param buf
+	 *            bufffer to obtain dat from
+	 * @param off
+	 *            offset i buf to conpy from
+	 * @param nbytes
+	 *            number of bytes from buf to use
+	 */
+	public void update(byte[] buf, int off, int nbytes) {
+		// avoid int overflow, check null buf
+		if (off <= buf.length && nbytes >= 0 && off >= 0
+				&& buf.length - off >= nbytes)
+			adler = updateImpl(buf, off, nbytes, adler);
+		else
+			throw new ArrayIndexOutOfBoundsException();
+	}
+
+	private native long updateImpl(byte[] buf, int off, int nbytes, long adler1);
+
+	private native long updateByteImpl(int val, long adler1);
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CRC32.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CRC32.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CRC32.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CRC32.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,86 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+/**
+ * The CRC32 class is used to compute a CRC32 Checksum from a set of data.
+ */
+public class CRC32 implements java.util.zip.Checksum {
+
+	private long crc = 0L;
+
+	long tbytes = 0L;
+
+	/**
+	 * Returns the CRC32 Checksum for all input received.
+	 * 
+	 * @return The checksum for this instance
+	 */
+	public long getValue() {
+		return crc;
+	}
+
+	/**
+	 * Returns the CRC32 checksum to it initial state.
+	 */
+	public void reset() {
+		tbytes = crc = 0;
+
+	}
+
+	/**
+	 * Updates this Checksum with value val
+	 */
+	public void update(int val) {
+		crc = updateByteImpl((byte) val, crc);
+	}
+
+	/**
+	 * Updates this Checksum with the bytes contained in buffer buf.
+	 * 
+	 * @param buf
+	 *            Buffer to update Checksum
+	 */
+	public void update(byte[] buf) {
+		update(buf, 0, buf.length);
+	}
+
+	/**
+	 * Updates this Checksum with nbytes of data from buffer buf, starting at
+	 * offset off.
+	 * 
+	 * @param buf
+	 *            Buffer to update Checksum
+	 * @param off
+	 *            Offest in buf to obtain data from
+	 * @param nbytes
+	 *            Number of bytes to read from buf
+	 */
+	public void update(byte[] buf, int off, int nbytes) {
+		// avoid int overflow, check null buf
+		if (off <= buf.length && nbytes >= 0 && off >= 0
+				&& buf.length - off >= nbytes) {
+			tbytes += nbytes;
+			crc = updateImpl(buf, off, nbytes, crc);
+		} else
+			throw new ArrayIndexOutOfBoundsException();
+	}
+
+	private native long updateImpl(byte[] buf, int off, int nbytes, long crc1);
+
+	private native long updateByteImpl(byte val, long crc1);
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,106 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * The CheckedInputStream class is used to maintain a running Checksum of all
+ * data read from a stream.
+ */
+public class CheckedInputStream extends java.io.FilterInputStream {
+
+	private Checksum check;
+
+	/**
+	 * Constructs a new CheckedInputStream on InputStream is. The Checksum will
+	 * be calculated using the algorithm implemented by csum.
+	 * 
+	 * @param is
+	 *            InputStream to calculate checksum from
+	 * @param csum
+	 *            Type of Checksum to calculate
+	 */
+	public CheckedInputStream(InputStream is, Checksum csum) {
+		super(is);
+		check = csum;
+	}
+
+	/**
+	 * Reads a byte of data from the underlying stream and recomputes the
+	 * Checksum with the byte data.
+	 * 
+	 * @return -1 if end of stream, a single byte value otherwise
+	 */
+	public int read() throws IOException {
+		int x = in.read();
+		if (x != -1) {
+			check.update(x);
+		}
+		return x;
+	}
+
+	/**
+	 * Reads up to nbytes of data from the underlying stream, storing it in buf,
+	 * starting at offset off. The Checksum is updated with the bytes read.
+	 * 
+	 * @return Number of bytes read, -1 if end of stream
+	 */
+	public int read(byte[] buf, int off, int nbytes) throws IOException {
+		int x = in.read(buf, off, nbytes);
+		if (x != -1)
+			check.update(buf, off, x);
+		return x;
+	}
+
+	/**
+	 * Returns the Checksum calculated on the stream thus far.
+	 * 
+	 * @return A java.util.zip.Checksum
+	 */
+	public Checksum getChecksum() {
+		return check;
+	}
+
+	/**
+	 * Skip upto nbytes of data on the underlying stream. Any skipped bytes are
+	 * added to the running Checksum value.
+	 * 
+	 * @param nbytes
+	 *            long Number of bytes to skip
+	 * @return Number of bytes skipped
+	 */
+	public long skip(long nbytes) throws IOException {
+		if (nbytes < 1) {
+			return 0;
+		}
+		long skipped = 0;
+		byte[] b = new byte[2048];
+		int x, v;
+		while (skipped != nbytes) {
+			x = in.read(b, 0,
+					(v = (int) (nbytes - skipped)) > b.length ? b.length : v);
+			if (x == -1) {
+				return skipped;
+			}
+			check.update(b, 0, x);
+			skipped += x;
+		}
+		return skipped;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedOutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedOutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/CheckedOutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,86 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The CheckedOutputStream class is used to maintain a running Checksum of all
+ * data written to a stream.
+ */
+public class CheckedOutputStream extends java.io.FilterOutputStream {
+
+	private Checksum check;
+
+	/**
+	 * Constructs a new CheckedOutputStream on OutputStream os. The Checksum
+	 * will be calculated using the algorithm implemented by csum.
+	 * 
+	 * @param os
+	 *            OutputStream to calculate checksum from
+	 * @param cs
+	 *            Type of Checksum to calculate
+	 */
+	public CheckedOutputStream(OutputStream os, Checksum cs) {
+		super(os);
+		check = cs;
+	}
+
+	/**
+	 * Returns the Checksum calculated on the stream thus far.
+	 * 
+	 * @return A java.util.zip.Checksum
+	 */
+	public Checksum getChecksum() {
+		return check;
+	}
+
+	/**
+	 * Writes byte value val to the underlying stream. The Checksum is updated
+	 * with val.
+	 * 
+	 * @param val
+	 *            Value of the byte to write out
+	 * 
+	 * @throws IOException
+	 *             if an IO error has occured
+	 */
+	public void write(int val) throws IOException {
+		out.write(val);
+		check.update(val);
+	}
+
+	/**
+	 * Writes nbytes of data from buf starting at offset off to the underlying
+	 * stream. The Checksum is updated with the bytes written.
+	 * 
+	 * @param buf
+	 *            data to write out
+	 * @param off
+	 *            the start offset of the data
+	 * @param nbytes
+	 *            number of bytes to write out
+	 * 
+	 * @throws IOException
+	 *             if an IO error has occured
+	 */
+	public void write(byte[] buf, int off, int nbytes) throws IOException {
+		out.write(buf, off, nbytes);
+		check.update(buf, off, nbytes);
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Checksum.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Checksum.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Checksum.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Checksum.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,27 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+public interface Checksum {
+	public long getValue();
+
+	public void reset();
+
+	public void update(int val);
+
+	public void update(byte[] buf, int off, int nbytes);
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DataFormatException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DataFormatException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DataFormatException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DataFormatException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,43 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+/**
+ * DataFormatException is used to indicate an error in the format of a
+ * particular data stream.
+ */
+public class DataFormatException extends Exception {
+
+	/**
+	 * Constructs a new instance of this class with its walkback filled in.
+	 * 
+	 */
+	public DataFormatException() {
+		super();
+	}
+
+	/**
+	 * Constructs a new instance of this class with its walkback and message
+	 * filled in.
+	 * 
+	 * @param detailMessage
+	 *            String The detail message for the exception.
+	 */
+	public DataFormatException(String detailMessage) {
+		super(detailMessage);
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Deflater.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Deflater.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Deflater.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/Deflater.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,376 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+/**
+ * The Deflater class is used to compress bytes using the DEFLATE compressionn
+ * algorithm. Deflation is performed by the ZLIB compression library.
+ * 
+ * @see DeflaterOutputStream
+ * @see Inflater
+ */
+public class Deflater {
+
+	public static final int BEST_COMPRESSION = 9;
+
+	public static final int BEST_SPEED = 1;
+
+	public static final int DEFAULT_COMPRESSION = -1;
+
+	public static final int DEFAULT_STRATEGY = 0;
+
+	public static final int DEFLATED = 8;
+
+	public static final int FILTERED = 1;
+
+	public static final int HUFFMAN_ONLY = 2;
+
+	public static final int NO_COMPRESSION = 0;
+
+	private static final int Z_NO_FLUSH = 0;
+
+	private static final int Z_FINISH = 4;
+
+	private int flushParm = Z_NO_FLUSH;
+
+	private boolean noHeader = false;
+
+	private boolean finished = false;
+
+	int compressLevel = DEFAULT_COMPRESSION;
+
+	int strategy = DEFAULT_STRATEGY;
+
+	long streamHandle = -1;
+
+	byte[] inputBuffer;
+
+	int inRead = 0, inLength = 0;
+
+	// Fill in the JNI id caches
+	private static native void oneTimeInitialization();
+
+	static {
+		oneTimeInitialization();
+	}
+
+	/**
+	 * Deflates data into the supplied buffer
+	 * 
+	 * @param buf
+	 *            buffer to store compressed data
+	 * 
+	 * @return number of bytes of compressed data stored
+	 * 
+	 */
+	public int deflate(byte[] buf) {
+		return deflate(buf, 0, buf.length);
+	}
+
+	/**
+	 * Deflates data into the supplied buffer using the region from off to
+	 * nbytes - 1.
+	 * 
+	 * @param buf
+	 *            buffer to store compressed data
+	 * @param off
+	 *            offset inf buf to start storing data
+	 * @param nbytes
+	 *            number of bytes of compressed data to store in buf
+	 * 
+	 * @return number of bytes of compresed data stored
+	 * 
+	 */
+	public synchronized int deflate(byte[] buf, int off, int nbytes) {
+		if (streamHandle == -1)
+			throw new IllegalStateException();
+		// avoid int overflow, check null buf
+		if (off <= buf.length && nbytes >= 0 && off >= 0
+				&& buf.length - off >= nbytes)
+			return deflateImpl(buf, off, nbytes, streamHandle, flushParm);
+		throw new ArrayIndexOutOfBoundsException();
+	}
+
+	private native synchronized int deflateImpl(byte[] buf, int off,
+			int nbytes, long handle, int flushParm1);
+
+	private synchronized native void endImpl(long handle);
+
+	/**
+	 * Frees all resources held onto by this Deflater. Any unused input or ouput
+	 * is discarded. This is also called from the finalize method.
+	 * 
+	 * @see #finalize
+	 */
+	public synchronized void end() {
+		if (streamHandle != -1) {
+			endImpl(streamHandle);
+			inputBuffer = null;
+			streamHandle = -1;
+		}
+	}
+
+	protected void finalize() {
+		end();
+	}
+
+	/**
+	 * Indicates to the Deflater that all uncompressed input has been provided
+	 * to it.
+	 * 
+	 * @see #finished
+	 */
+	public synchronized void finish() {
+		flushParm = Z_FINISH;
+	}
+
+	/**
+	 * Returns whether or not all provided data has been successfully
+	 * compressed.
+	 * 
+	 * @return true if all data has been compressed, false otherwise
+	 */
+	public synchronized boolean finished() {
+		return finished;
+	}
+
+	/**
+	 * Returns the Adler32 checksum of uncompressed data currently read. If a
+	 * preset dictionary is used getAdler() will return the Adler32 checksum of
+	 * the dictionary used.
+	 * 
+	 * @return The Adler32 checksum of uncompressed data or preset dictionary if
+	 *         used
+	 * 
+	 * @see #setDictionary(byte[])
+	 * @see #setDictionary(byte[], int, int)
+	 */
+	public synchronized int getAdler() {
+		if (streamHandle == -1)
+			throw new IllegalStateException();
+
+		return getAdlerImpl(streamHandle);
+	}
+
+	private synchronized native int getAdlerImpl(long handle);
+
+	/**
+	 * Returns the total number of bytes of input consumed by the deflater.
+	 * 
+	 * @return number of bytes of input read.
+	 */
+	public synchronized int getTotalIn() {
+		if (streamHandle == -1)
+			throw new IllegalStateException();
+
+		return getTotalInImpl(streamHandle);
+	}
+
+	private native synchronized int getTotalInImpl(long handle);
+
+	/**
+	 * Returns the total number of compressed bytes output nby this Deflater.
+	 * 
+	 * @return number of compressed bytes output.
+	 */
+	public synchronized int getTotalOut() {
+		if (streamHandle == -1)
+			throw new IllegalStateException();
+
+		return getTotalOutImpl(streamHandle);
+	}
+
+	private synchronized native int getTotalOutImpl(long handle);
+
+	/**
+	 * Indicates whether or not all bytes of uncompressed input have been
+	 * consumed by the Deflater. If needsInput() answers true setInput() must be
+	 * called before deflation can continue. If all bytes of uncompressed data
+	 * have been provided to the Deflater finish() must be called to ensure the
+	 * compressed data is output.
+	 * 
+	 * @return True if input is reuired for deflation to continue, false
+	 *         otherwise
+	 * @see #finished()
+	 * @see #setInput(byte[])
+	 * @see #setInput(byte[], int, int)
+	 */
+	public boolean needsInput() {
+		if (inputBuffer == null)
+			return true;
+		return inRead == inLength;
+	}
+
+	/**
+	 * Resets the <code>Deflater</code> to accept new input without affecting
+	 * any previously made settings for the compression strategy or level. This
+	 * operation <i>must</i> be called after <code>finished()</code> returns
+	 * <code>true</code> if the <code>Deflater</code> is to be reused.
+	 * 
+	 * @see #finished
+	 */
+	public synchronized void reset() {
+		if (streamHandle == -1)
+			throw new NullPointerException();
+
+		flushParm = Z_NO_FLUSH;
+		finished = false;
+		resetImpl(streamHandle);
+		inputBuffer = null;
+	}
+
+	private native synchronized void resetImpl(long handle);
+
+	public void setDictionary(byte[] buf) {
+		setDictionary(buf, 0, buf.length);
+	}
+
+	/**
+	 * Sets the dictionary to be used for compression by this Deflater.
+	 * setDictionary() can only be called if this Deflater supports the writing
+	 * of ZLIB headers. This is the default behaviour but can be overridden
+	 * using Deflater(int, boolean).
+	 * 
+	 * @see Deflater#Deflater(int, boolean)
+	 */
+	public synchronized void setDictionary(byte[] buf, int off, int nbytes) {
+		if (streamHandle == -1)
+			throw new IllegalStateException();
+		// avoid int overflow, check null buf
+		if (off <= buf.length && nbytes >= 0 && off >= 0
+				&& buf.length - off >= nbytes)
+			setDictionaryImpl(buf, off, nbytes, streamHandle);
+		else
+			throw new ArrayIndexOutOfBoundsException();
+	}
+
+	private native synchronized void setDictionaryImpl(byte[] buf, int off,
+			int nbytes, long handle);
+
+	/**
+	 * Sets the input buffer the Deflater will use to extract uncompressed bytes
+	 * for later compression.
+	 */
+	public void setInput(byte[] buf) {
+		setInput(buf, 0, buf.length);
+	}
+
+	/**
+	 * Sets the input buffer the Deflater will use to extract uncompressed bytes
+	 * for later compression. Input will be taken from the buffer region
+	 * starting at off and ending at nbytes - 1.
+	 */
+	public synchronized void setInput(byte[] buf, int off, int nbytes) {
+		if (streamHandle == -1)
+			throw new IllegalStateException();
+		// avoid int overflow, check null buf
+		if (off <= buf.length && nbytes >= 0 && off >= 0
+				&& buf.length - off >= nbytes) {
+			inLength = nbytes;
+			inRead = 0;
+			if (inputBuffer == null)
+				setLevelsImpl(compressLevel, strategy, streamHandle);
+			inputBuffer = buf;
+			setInputImpl(buf, off, nbytes, streamHandle);
+		} else
+			throw new ArrayIndexOutOfBoundsException();
+	}
+
+	private native synchronized void setLevelsImpl(int level, int strategy,
+			long handle);
+
+	private native synchronized void setInputImpl(byte[] buf, int off,
+			int nbytes, long handle);
+
+	/**
+	 * Sets the compression level to be used when compressing data. The
+	 * compression level must be a value between 0 and 9. This value must be set
+	 * prior to calling setInput().
+	 * 
+	 * @param level
+	 *            compression level to use
+	 * @exception IllegalArgumentException
+	 *                If the compression level is invalid.
+	 */
+	public synchronized void setLevel(int level) {
+		if (level < DEFAULT_COMPRESSION || level > BEST_COMPRESSION)
+			throw new IllegalArgumentException();
+		if (inputBuffer != null)
+			throw new IllegalStateException();
+		compressLevel = level;
+	}
+
+	/**
+	 * Sets the compression strategy to be used. The strategy must be one of
+	 * FILTERED, HUFFMAN_ONLY or DEFAULT_STRATEGY.This value must be set prior
+	 * to calling setInput().
+	 * 
+	 * @param strategy
+	 *            compression strategy to use
+	 * @exception IllegalArgumentException
+	 *                If the strategy specified is not one of FILTERED,
+	 *                HUFFMAN_ONLY or DEFAULT_STRATEGY.
+	 */
+	public synchronized void setStrategy(int strategy) {
+		if (strategy < DEFAULT_STRATEGY || strategy > HUFFMAN_ONLY)
+			throw new IllegalArgumentException();
+		if (inputBuffer != null)
+			throw new IllegalStateException();
+		this.strategy = strategy;
+	}
+
+	/**
+	 * Constructs a new Deflater instance with default compression level and
+	 * strategy.
+	 */
+	public Deflater() {
+		this(DEFAULT_COMPRESSION, false);
+	}
+
+	/**
+	 * Constructs a new Deflater instance with compression level level and
+	 * default compression strategy. If the noHeader parameter is specified then
+	 * no ZLIB header will be written as part of the compressed output. The
+	 * compression level specified must be between 0 and 9.
+	 * 
+	 * @param level
+	 *            the compression level to use
+	 * @param noHeader
+	 *            if true do not write the ZLIB header
+	 */
+	public Deflater(int level, boolean noHeader) {
+		if (level < DEFAULT_COMPRESSION || level > BEST_COMPRESSION)
+			throw new IllegalArgumentException();
+		compressLevel = level;
+		this.noHeader = noHeader;
+		streamHandle = createStream(compressLevel, strategy, noHeader);
+	}
+
+	/**
+	 * Constructs a new Deflater instance with compression level level and
+	 * default compression strategy. THe compression level provided must be
+	 * between 0 and 9.
+	 * 
+	 * @param level
+	 *            the compression level to use
+	 */
+	public Deflater(int level) {
+		this(level, false);
+	}
+
+	private native long createStream(int level, int strategy1, boolean noHeader1);
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DeflaterOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DeflaterOutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DeflaterOutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/DeflaterOutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,170 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import com.ibm.oti.util.Msg;
+
+/**
+ * The DeflaterOutputStream class implements a stream filter for the writing of
+ * compressed data to a stream. Compression is performed by an instance of
+ * Deflater.
+ */
+public class DeflaterOutputStream extends FilterOutputStream {
+	static final int BUF_SIZE = 512;
+
+	protected byte[] buf;
+
+	protected Deflater def;
+
+	boolean done = false;
+
+	/**
+	 * Constructs a new DeflaterOutputStream instance using os as the underlying
+	 * stream. The provided Deflater instance will be used to compress data.
+	 * 
+	 * @param os
+	 *            OutputStream to receive compressed data
+	 * @param def
+	 *            Deflater to perform compression
+	 */
+	public DeflaterOutputStream(OutputStream os, Deflater def) {
+		this(os, def, BUF_SIZE);
+	}
+
+	/**
+	 * Constructs a new DeflaterOutputStream instance using os as the underlying
+	 * stream.
+	 * 
+	 * @param os
+	 *            OutputStream to receive compressed data
+	 */
+	public DeflaterOutputStream(OutputStream os) {
+		this(os, new Deflater());
+	}
+
+	/**
+	 * Constructs a new DeflaterOutputStream instance using os as the underlying
+	 * stream. The provided Deflater instance will be used to compress data. The
+	 * internal buffer for storing compressed data will be of size bsize.
+	 * 
+	 * @param os
+	 *            OutputStream to receive compressed data
+	 * @param def
+	 *            Deflater to perform compression
+	 * @param bsize
+	 *            size of internal compression buffer
+	 */
+	public DeflaterOutputStream(OutputStream os, Deflater def, int bsize) {
+		super(os);
+		if (os == null || def == null)
+			throw new NullPointerException();
+		if (bsize <= 0)
+			throw new IllegalArgumentException();
+		this.def = def;
+		buf = new byte[bsize];
+	}
+
+	/**
+	 * Compress the data in the input buffer and write it to the underlying
+	 * stream.
+	 * 
+	 * @exception java.io.IOException
+	 *                If an error occurs during deflation.
+	 */
+	protected void deflate() throws IOException {
+		int x = 0;
+		do {
+			x = def.deflate(buf);
+			out.write(buf, 0, x);
+		} while (!def.needsInput());
+	}
+
+	/**
+	 * Writes any unwritten compressed data to the underlying stream, the closes
+	 * all underlying streams. This stream can no longer be used after close()
+	 * has been called.
+	 * 
+	 * @exception java.io.IOException
+	 *                If an error occurs during close.
+	 */
+	public void close() throws IOException {
+		if (!def.finished())
+			finish();
+		def.end();
+		out.close();
+	}
+
+	/**
+	 * Write any unwritten data to the underlying stream. Do not close the
+	 * stream. This allows subsequent Deflater's to write to the same stream.
+	 * This Deflater cannot be used again.
+	 * 
+	 * @exception java.io.IOException
+	 *                If an error occurs.
+	 */
+	public void finish() throws IOException {
+		if (done)
+			return;
+		def.finish();
+		int x = 0;
+		while (!def.finished()) {
+			if (def.needsInput())
+				def.setInput(buf, 0, 0);
+			x = def.deflate(buf);
+			out.write(buf, 0, x);
+		}
+		done = true;
+	}
+
+	public void write(int i) throws IOException {
+		byte[] b = new byte[1];
+		b[0] = (byte) i;
+		write(b, 0, 1);
+	}
+
+	/**
+	 * Compress nbytes of data from buf starting at off and write it to the
+	 * underlying stream.
+	 * 
+	 * @param buf
+	 *            Buffer of data to compress
+	 * @param off
+	 *            offset in buffer to extract data from
+	 * @param nbytes
+	 *            Number of bytes of data to compress and write
+	 * 
+	 * @exception java.io.IOException
+	 *                If an error occurs during writing.
+	 */
+	public void write(byte[] buffer, int off, int nbytes) throws IOException {
+		if (done)
+			throw new IOException(Msg.getString("K0007"));
+		// avoid int overflow, check null buf
+		if (off <= buffer.length && nbytes >= 0 && off >= 0
+				&& buffer.length - off >= nbytes) {
+			if (!def.needsInput())
+				throw new IOException();
+			def.setInput(buffer, off, nbytes);
+			deflate();
+		} else
+			throw new ArrayIndexOutOfBoundsException();
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,189 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.ibm.oti.util.Msg;
+
+/**
+ * The GZIPInputStream class is used to read data stored in the GZIP format.
+ */
+public class GZIPInputStream extends java.util.zip.InflaterInputStream {
+	protected CRC32 crc = new CRC32();
+
+	protected boolean eos = false;
+
+	public final static int GZIP_MAGIC = 0x8b1f;
+
+	private static final int FHCRC = 2;
+
+	private static final int FEXTRA = 4;
+
+	private static final int FNAME = 8;
+
+	private static final int FCOMMENT = 16;
+
+	/**
+	 * Construct a GZIPInputStream to read from GZIP data from the underlying
+	 * stream
+	 * 
+	 * @param is
+	 *            InputStream to read data from
+	 */
+	public GZIPInputStream(InputStream is) throws IOException {
+		this(is, BUF_SIZE);
+	}
+
+	/**
+	 * Construct a GZIPInputStream to read from GZIP data from the underlying
+	 * stream. Set the internal buffer size to size
+	 * 
+	 * @param is
+	 *            InputStream to read data from
+	 * @param size
+	 *            Internal read buffer size
+	 */
+	public GZIPInputStream(InputStream is, int size) throws IOException {
+		super(is, new Inflater(true), size);
+		byte[] header = new byte[10];
+		readFully(header, 0, header.length);
+		if (getShort(header, 0) != GZIP_MAGIC)
+			throw new IOException(Msg.getString("K0020"));
+		int flags = header[3];
+		boolean hcrc = (flags & FHCRC) != 0;
+		if (hcrc)
+			crc.update(header, 0, header.length);
+		if ((flags & FEXTRA) != 0) {
+			readFully(header, 0, 2);
+			if (hcrc)
+				crc.update(header, 0, 2);
+			int length = getShort(header, 0);
+			while (length > 0) {
+				int max = length > buf.length ? buf.length : length;
+				int result = in.read(buf, 0, max);
+				if (result == -1)
+					throw new EOFException();
+				if (hcrc)
+					crc.update(buf, 0, result);
+				length -= result;
+			}
+		}
+		if ((flags & FNAME) != 0)
+			readZeroTerminated(hcrc);
+		if ((flags & FCOMMENT) != 0)
+			readZeroTerminated(hcrc);
+		if (hcrc) {
+			readFully(header, 0, 2);
+			int crc16 = getShort(header, 0);
+			if ((crc.getValue() & 0xffff) != crc16)
+				throw new IOException(Msg.getString("K0077"));
+			crc.reset();
+		}
+	}
+
+	private long getLong(byte[] buffer, int off) {
+		long l = 0;
+		l |= (buffer[off] & 0xFF);
+		l |= (buffer[off + 1] & 0xFF) << 8;
+		l |= (buffer[off + 2] & 0xFF) << 16;
+		l |= ((long) (buffer[off + 3] & 0xFF)) << 24;
+		return l;
+	}
+
+	private int getShort(byte[] buffer, int off) {
+		return (buffer[off] & 0xFF) | ((buffer[off + 1] & 0xFF) << 8);
+	}
+
+	/**
+	 * Reads and decompresses GZIP data from the underlying stream into buf.
+	 * 
+	 * @param buffer
+	 *            Buffer to receive data
+	 * @param off
+	 *            Offset in buffer to store data
+	 * @param nbytes
+	 *            Number of bytes to read
+	 */
+	public int read(byte[] buffer, int off, int nbytes) throws IOException {
+		// avoid int overflow, check null buffer
+		if (off <= buffer.length && nbytes >= 0 && off >= 0
+				&& buffer.length - off >= nbytes) {
+			int val = super.read(buffer, off, nbytes);
+			if (val != -1)
+				crc.update(buffer, off, val);
+			else if (!eos) {
+				eos = true;
+				// Get non-compressed bytes read by fill
+				int size = 0;
+				byte[] b = new byte[8];
+				int inB = inf.getTotalIn();
+				if (inB > 0) {
+					int diff = inB % buf.length;
+					if (diff != 0 || len != buf.length) {
+						size = len - diff;
+						if (size > b.length)
+							size = b.length;
+						System.arraycopy(buf, diff, b, 0, size);
+					}
+				}
+				readFully(b, size, b.length - size);
+				if (getLong(b, 0) != crc.getValue())
+					throw new IOException(Msg.getString("K0077"));
+				if ((int) getLong(b, 4) != inf.getTotalOut())
+					throw new IOException(Msg.getString("K00ae"));
+			}
+			return val;
+		}
+		throw new ArrayIndexOutOfBoundsException();
+	}
+
+	/**
+	 * Closes this stream and any underlying streams.
+	 */
+	public void close() throws IOException {
+		eos = true;
+		super.close();
+	}
+
+	private void readFully(byte[] buffer, int offset, int length)
+			throws IOException {
+		int result;
+		while (length > 0) {
+			result = in.read(buffer, offset, length);
+			if (result == -1)
+				throw new EOFException();
+			offset += result;
+			length -= result;
+		}
+	}
+
+	private void readZeroTerminated(boolean hcrc) throws IOException {
+		int result;
+		while ((result = in.read()) > 0) {
+			if (hcrc)
+				crc.update(result);
+		}
+		if (result == -1)
+			throw new EOFException();
+		// Add the zero
+		if (hcrc)
+			crc.update(result);
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPOutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPOutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/archive/src/java/util/zip/GZIPOutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,102 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The GZIPOutputStream class is used to write data to a stream in the GZIP
+ * storage format.
+ */
+public class GZIPOutputStream extends DeflaterOutputStream {
+
+	protected CRC32 crc = new CRC32();
+
+	/**
+	 * Construct a new GZIPOutputStream to write data in GZIP format to the
+	 * underlying stream.
+	 * 
+	 * @param os
+	 *            OutputStream to write to
+	 */
+	public GZIPOutputStream(OutputStream os) throws IOException {
+		this(os, BUF_SIZE);
+	}
+
+	/**
+	 * Construct a new GZIPOutputStream to write data in GZIP format to the
+	 * underlying stream. Set the internal compression buffer to sise size.
+	 * 
+	 * @param os
+	 *            OutputStream to write to
+	 * @param size
+	 *            Internal buffer size
+	 */
+	public GZIPOutputStream(OutputStream os, int size) throws IOException {
+		super(os, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
+		writeShort(GZIPInputStream.GZIP_MAGIC);
+		out.write(Deflater.DEFLATED);
+		out.write(0); // flags
+		writeLong(0); // mod time
+		out.write(0); // extra flags
+		out.write(0); // operating system
+	}
+
+	/**
+	 * Indicates to the stream that all data has been written out, and any GZIP
+	 * terminal data can now be output.
+	 */
+	public void finish() throws IOException {
+		super.finish();
+		writeLong(crc.getValue());
+		writeLong(crc.tbytes);
+	}
+
+	/**
+	 * Close this stream and any underlying streams.
+	 */
+	public void close() throws IOException {
+		if (!done)
+			finish();
+		super.close();
+	}
+
+	/**
+	 * Write up to nbytes of data from buf, starting at offset off, to the
+	 * underlying stream in GZIP format.
+	 */
+	public void write(byte[] buffer, int off, int nbytes) throws IOException {
+		super.write(buffer, off, nbytes);
+		crc.update(buffer, off, nbytes);
+	}
+
+	private int writeShort(int i) throws IOException {
+		out.write(i & 0xFF);
+		out.write((i >> 8) & 0xFF);
+		return i;
+	}
+
+	private long writeLong(long i) throws IOException {
+		// Write out the long value as an unsigned int
+		out.write((int) (i & 0xFF));
+		out.write((int) (i >> 8) & 0xFF);
+		out.write((int) (i >> 16) & 0xFF);
+		out.write((int) (i >> 24) & 0xFF);
+		return i;
+	}
+}