harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r350181 [92/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...
Date Thu, 01 Dec 2005 06:04:00 GMT
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/OIDDatabase.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/OIDDatabase.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/OIDDatabase.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/OIDDatabase.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,181 @@
+/* Copyright 2005, 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 com.ibm.oti.util;
+
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+public class OIDDatabase {
+
+	private static OIDDatabase instance = new OIDDatabase();
+
+	private Set oids = new HashSet();
+
+	private Set algorithms = new HashSet();
+
+	/**
+	 * Private constructor to enforce singleton pattern
+	 */
+	private OIDDatabase() {
+		// First, encryption algorithms...
+
+		// MD2withRSA
+		DBEntry oid = new DBEntry("1.2.840.113549.1.1.2");
+		DBEntry alg = new DBEntry("MD2withRSA");
+		wireTogether(oid, alg);
+
+		// MD5withRSA
+		oid = new DBEntry("1.2.840.113549.1.1.4");
+		alg = new DBEntry("MD5withRSA");
+		wireTogether(oid, alg);
+
+		// SHA1withRSA
+		oid = new DBEntry("1.2.840.113549.1.1.5");
+		alg = new DBEntry("SHA1withRSA");
+		wireTogether(oid, alg);
+
+		// SHA1withDSA
+		oid = new DBEntry("1.2.840.10040.4.3");
+		alg = new DBEntry("SHA1withDSA");
+		wireTogether(oid, alg);
+
+		// message digest algorithms
+
+		// SHA and SHA-1
+		oid = new DBEntry("1.3.14.3.2.26");
+		alg = new DBEntry("SHA");
+		DBEntry alg2 = new DBEntry("SHA-1");
+		wireTogether(oid, alg);
+		wireTogether(oid, alg2);
+
+		// MD5
+		oid = new DBEntry("1.2.840.113549.2.5");
+		alg = new DBEntry("MD5");
+		wireTogether(oid, alg);
+
+		// key factories
+
+		// RSA
+		oid = new DBEntry("1.2.840.113549.1.1.1");
+		alg = new DBEntry("RSA");
+		wireTogether(oid, alg);
+
+		// DSA
+		oid = new DBEntry("1.2.840.10040.4.1");
+		DBEntry oid2 = new DBEntry("1.3.14.3.2.12");
+		alg = new DBEntry("DSA");
+		wireTogether(oid, alg);
+		wireTogether(oid2, alg);
+
+		// DiffieHellman
+		oid = new DBEntry("1.2.840.10046.2.1");
+		alg = new DBEntry("DiffieHellman");
+		wireTogether(oid, alg);
+	}
+
+	private void wireTogether(DBEntry oidValue, DBEntry algorithmValue) {
+		oids.add(oidValue);
+		algorithms.add(algorithmValue);
+		oidValue.addEquivalent(algorithmValue);
+		algorithmValue.addEquivalent(oidValue);
+	}
+
+	public static OIDDatabase getInstance() {
+		return instance;
+	}
+
+	public String getFirstAlgorithmForOID(String oid) {
+		String result = null;
+		Iterator it = this.getAllAlgorithmsForOID(oid).iterator();
+		if (it.hasNext()) {
+			result = ((String) it.next());
+		}
+		return result;
+	}
+
+	public Set getAllAlgorithmsForOID(String oid) {
+		Set result = null;
+		Iterator it = this.oids.iterator();
+		result = getAllEquivalents(oid, it);
+		if (result == null) {
+			throw new IllegalArgumentException("Unknown OID : " + oid);
+		}
+		return result;
+	}
+
+	public String getFirstOIDForAlgorithm(String algorithm) {
+		String result = null;
+		Iterator it = this.getAllOIDsForAlgorithm(algorithm).iterator();
+		if (it.hasNext()) {
+			result = ((String) it.next());
+		}
+		return result;
+	}
+
+	public Set getAllOIDsForAlgorithm(String algorithm) {
+		Set result = null;
+		Iterator it = this.algorithms.iterator();
+		result = getAllEquivalents(algorithm, it);
+		if (result == null) {
+			throw new IllegalArgumentException("Unsupported algorithm : "
+					+ algorithm);
+		}
+		return result;
+	}
+
+	private Set getAllEquivalents(String value, Iterator it) {
+		Set result = null;
+		while (it.hasNext()) {
+			DBEntry element = (DBEntry) it.next();
+			if (element.getValue().equals(value)) {
+				Set allMatchingDBEntries = element.getAllEquivalents();
+				result = new HashSet();
+				Iterator dbIt = allMatchingDBEntries.iterator();
+				while (dbIt.hasNext()) {
+					DBEntry matchingEntry = (DBEntry) dbIt.next();
+					result.add(matchingEntry.getValue());
+				}
+			}
+		}
+		return result;
+	}
+
+	static class DBEntry {
+		private List equivalents = new LinkedList();
+
+		private String value;
+
+		DBEntry(String value) {
+			this.value = value;
+		}
+
+		void addEquivalent(DBEntry entry) {
+			this.equivalents.add(entry);
+		}
+
+		String getValue() {
+			return this.value;
+		}
+
+		Set getAllEquivalents() {
+			return new HashSet(this.equivalents);
+		}
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PasswordProtectedInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PasswordProtectedInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PasswordProtectedInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PasswordProtectedInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,102 @@
+/* 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 com.ibm.oti.util;
+
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class implements a password-protected input stream. The algorithm used
+ * for protection is a Vigenere (repeated-key) cipher. The encrypted data is the
+ * result of <original data> XOR KEYKEYKEY...
+ */
+public class PasswordProtectedInputStream extends FilterInputStream {
+
+	private byte[] password; // Password to use to decrypt the input bytes
+
+	private int pwdIndex = 0; // Index into the password array.
+
+	/**
+	 * Constructs a new instance of the receiver.
+	 * 
+	 * @param in
+	 *            java.io.InputStream The actual input stream where to read the
+	 *            bytes from.
+	 * @param password
+	 *            byte[] password bytes to use to decrypt the input bytes
+	 */
+	public PasswordProtectedInputStream(InputStream in, byte[] password) {
+		super(in);
+		this.password = password;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#read()
+	 */
+	public int read() throws IOException {
+		int read = in.read();
+		if (read >= 0) {
+			read ^= password[pwdIndex];
+			pwdIndex = (pwdIndex + 1) % password.length;
+		}
+		return read;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#read(byte[], int, int)
+	 */
+	public int read(byte b[], int off, int len) throws IOException {
+		int read = in.read(b, off, len);
+		if (read > 0) {
+			int lastIndex = off + read;
+			for (int i = off; i < lastIndex; i++) {
+				b[i] ^= password[pwdIndex];
+				pwdIndex = (pwdIndex + 1) % password.length;
+			}
+		}
+		return read;
+	}
+
+	/**
+	 * Skips over and discards <code>n</code> bytes of data from the input
+	 * stream. The <code>skip</code> method may, for a variety of reasons, end
+	 * up skipping over some smaller number of bytes, possibly <code>0</code>.
+	 * The actual number of bytes skipped is returned.
+	 * <p>
+	 * The <code>skip </code>method of <code>FilterInputStream</code> calls
+	 * the <code>skip</code> method of its underlying input stream with the
+	 * same argument, and returns whatever value that method does.
+	 * 
+	 * @param n
+	 *            the number of bytes to be skipped.
+	 * @return the actual number of bytes skipped.
+	 * @exception IOException
+	 *                if an I/O error occurs.
+	 * @since JDK1.0
+	 */
+
+	public long skip(long n) throws IOException {
+		long skip = super.skip(n);
+		pwdIndex += skip;
+		return skip;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PositionedInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PositionedInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PositionedInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PositionedInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,93 @@
+/* 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 com.ibm.oti.util;
+
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class implements a Stream whose position can be querried for.
+ */
+public class PositionedInputStream extends FilterInputStream {
+
+	int currentPosition = 0; // Current position on the underlying stream
+
+	/**
+	 * Constructs a new instance of the receiver.
+	 * 
+	 * @param in
+	 *            java.io.InputStream The actual input stream where to read the
+	 *            bytes from.
+	 */
+	public PositionedInputStream(InputStream in) {
+		super(in);
+	}
+
+	/**
+	 * Return the current position in the receiver
+	 * 
+	 * @return int The current position in the receiver
+	 */
+	public int currentPosition() {
+		return currentPosition;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#read()
+	 */
+	public int read() throws IOException {
+		int read = in.read();
+		if (read >= 0)
+			currentPosition++;
+		return read;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#read(byte[], int, int)
+	 */
+	public int read(byte b[], int off, int len) throws IOException {
+		int read = in.read(b, off, len);
+		if (read >= 0)
+			currentPosition += read;
+		return read;
+	}
+
+	/**
+	 * Makes the current position on the underlying stream be assigned relative
+	 * position zero.
+	 */
+	public void resetCurrentPosition() {
+		currentPosition = 0;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#skip(long)
+	 */
+	public long skip(long n) throws IOException {
+		long skip = in.skip(n);
+		currentPosition += skip; // Maybe currentPosition should be long ?
+		return skip;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PriviAction.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PriviAction.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PriviAction.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/PriviAction.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,136 @@
+/* Copyright 2004, 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 com.ibm.oti.util;
+
+
+import java.lang.reflect.AccessibleObject;
+import java.security.Policy;
+import java.security.PrivilegedAction;
+import java.security.Security;
+
+/**
+ * Helper class to avoid multiple anonymous inner class for
+ * <code>{@link java.security.AccessController#doPrivileged(PrivilegedAction)}</code>
+ * calls.
+ */
+public class PriviAction implements PrivilegedAction {
+
+	private Object arg1;
+
+	private Object arg2;
+
+	private int action;
+
+	private static final int GET_SYSTEM_PROPERTY = 1;
+
+	private static final int GET_SECURITY_POLICY = 2;
+
+	private static final int SET_ACCESSIBLE = 3;
+
+	private static final int GET_SECURITY_PROPERTY = 4;
+
+	/**
+	 * Creates a PrivilegedAction to get the security property with the given
+	 * name.
+	 * 
+	 * @param property
+	 *            the name of the property
+	 * 
+	 * @see Security#getProperty
+	 */
+	public static PrivilegedAction getSecurityProperty(String property) {
+		return new PriviAction(GET_SECURITY_PROPERTY, property);
+	}
+
+	private PriviAction(int action, Object arg) {
+		this.action = action;
+		this.arg1 = arg;
+	}
+
+	/**
+	 * Creates a PrivilegedAction to get the current security policy object.
+	 * 
+	 * @see Policy#getPolicy
+	 */
+	public PriviAction() {
+		action = GET_SECURITY_POLICY;
+	}
+
+	/**
+	 * Creates a PrivilegedAction to disable the access checks to the given
+	 * object.
+	 * 
+	 * @param object
+	 *            the object whose accessible flag will be set to
+	 *            <code>true</code>
+	 * 
+	 * @see AccessibleObject#setAccessible(boolean)
+	 */
+	public PriviAction(AccessibleObject object) {
+		action = SET_ACCESSIBLE;
+		arg1 = object;
+	}
+
+	/**
+	 * Creates a PrivilegedAction to return the value of the system property
+	 * with the given key.
+	 * 
+	 * @param property
+	 *            the key of the system property
+	 * 
+	 * @see System#getProperty(String)
+	 */
+	public PriviAction(String property) {
+		action = GET_SYSTEM_PROPERTY;
+		arg1 = property;
+	}
+
+	/**
+	 * Creates a PrivilegedAction to return the value of the system property
+	 * with the given key.
+	 * 
+	 * @param property
+	 *            the key of the system property
+	 * @param defaultAnswer
+	 *            the return value if the system property does not exist
+	 * 
+	 * @see System#getProperty(String, String)
+	 */
+	public PriviAction(String property, String defaultAnswer) {
+		action = GET_SYSTEM_PROPERTY;
+		arg1 = property;
+		arg2 = defaultAnswer;
+	}
+
+	/**
+	 * Performs the actual privileged computation as defined by the constructor.
+	 * 
+	 * @see java.security.PrivilegedAction#run()
+	 */
+	public Object run() {
+		switch (action) {
+		case GET_SYSTEM_PROPERTY:
+			return System.getProperty((String) arg1, (String) arg2);
+		case GET_SECURITY_PROPERTY:
+			return Security.getProperty((String) arg1);
+		case GET_SECURITY_POLICY:
+			return Policy.getPolicy();
+		case SET_ACCESSIBLE:
+			((AccessibleObject) arg1).setAccessible(true);
+		}
+		return null;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/SHAOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/SHAOutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/SHAOutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/SHAOutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,468 @@
+/* Copyright 1998, 2003 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 com.ibm.oti.util;
+
+
+import java.io.OutputStream;
+
+/**
+ * This class implements the Secure Hash Algorithm, SHA-1. The specification can
+ * be found at http://csrc.ncsl.nist.gov/fips/fip180-1.txt
+ */
+public class SHAOutputStream extends OutputStream implements Cloneable {
+
+	// 5-word Array. Starts with well-known constants, ends with SHA
+	private int[] HConstants;
+
+	// 80-word Array.
+	private int[] WArray;
+
+	// 16-word Array. Input bit stream M is divided in chunks of MArray
+	private byte[] MArray;
+
+	// Number of bytes of input already processed towards SHA result
+	private long bytesProcessed;
+
+	// Number of bytes in WArray not processed yet
+	private int bytesToProcess;
+
+	// Optimization, for write
+	private byte[] oneByte = new byte[1];
+
+	/* Constants as in the specification */
+
+	// K in iterations 0..19, from spec
+	private static final int K0_19 = 0x5a827999;
+
+	// K in iterations 20..39, from spec
+	private static final int K20_39 = 0x6ed9eba1;
+
+	// K in iterations 40..59, from spec
+	private static final int K40_59 = 0x8f1bbcdc;
+
+	// K in iterations 60..79, from spec
+	private static final int K60_79 = 0xca62c1d6;
+
+	// H0, from spec
+	private static final int H0 = 0x67452301;
+
+	// H1, from spec
+	private static final int H1 = 0xefcdab89;
+
+	// H2, from spec
+	private static final int H2 = 0x98badcfe;
+
+	// H3, from spec
+	private static final int H3 = 0x10325476;
+
+	// H4, from spec
+	private static final int H4 = 0xc3d2e1f0;
+
+	private static final int HConstantsSize = 5;
+
+	private static final int HashSizeInBytes = 20;
+
+	// 16 words
+	private static final int BlockSizeInBytes = 16 * 4;
+
+	// 80 words
+	private static final int WArraySize = 80;
+
+	/**
+	 * Constructs a new SHAOutputStream.
+	 */
+	public SHAOutputStream() {
+		super();
+		initialize();
+		reset();
+	}
+
+	/**
+	 * Constructs a new MD5OutputStream with the given initial state.
+	 * 
+	 * @param state
+	 *            The initial state of the output stream. This is what will be
+	 *            returned by getHash() if write() is never called.
+	 * 
+	 * @exception IllegalArgumentException
+	 *                if state.length is less than 16.
+	 */
+	public SHAOutputStream(byte[] state) {
+		this();
+
+		if (state.length < HashSizeInBytes) {
+			throw new IllegalArgumentException();
+		}
+
+		for (int i = 0; i < 4; i++) {
+			HConstants[i] = 0;
+			for (int j = 0; j < 4; j++) {
+				HConstants[i] += (state[4 * i + j] & 0xFF) << 8 * (3 - j);
+			}
+		}
+	}
+
+	/**
+	 * Answers a new instance of the same class as the receiver, whose slots
+	 * have been filled in with the values in the slots of the receiver.
+	 * <p>
+	 * Classes which wish to support cloning must specify that they implement
+	 * the Cloneable interface, since the native implementation checks for this.
+	 * 
+	 * @return a complete copy of this object
+	 * @exception CloneNotSupportedException
+	 *                if the component does not implement the interface
+	 *                Cloneable
+	 */
+	public Object clone() throws CloneNotSupportedException {
+		// Calling super takes care of primitive type slots
+		SHAOutputStream result = (SHAOutputStream) super.clone();
+		result.HConstants = (int[]) this.HConstants.clone();
+		result.WArray = (int[]) this.WArray.clone();
+		result.MArray = (byte[]) this.MArray.clone();
+		result.oneByte = (byte[]) this.oneByte.clone();
+		return result;
+	}
+
+	/**
+	 * Copies a byte array into the receiver's internal buffer, making the
+	 * adjustments as necessary and keeping the receiver in a consistent state.
+	 * 
+	 * @param buffer
+	 *            byte array representation of the bytes
+	 * @param off
+	 *            offset into the source buffer where to start the copying
+	 * @param len
+	 *            how many bytes in the source byte array to copy
+	 * 
+	 */
+	private void copyToInternalBuffer(byte[] buffer, int off, int len) {
+		int index;
+		index = off;
+		for (int i = bytesToProcess; i < bytesToProcess + len; i++) {
+			MArray[i] = buffer[index];
+			index++;
+		}
+		bytesToProcess = bytesToProcess + len;
+	}
+
+	/**
+	 * Returns an int array (length = 5) with the SHA value of the bytes written
+	 * to the receiver.
+	 * 
+	 * @return int[] The 5 ints that form the SHA value of the bytes written to
+	 *         the receiver
+	 */
+	public int[] getHash() {
+		this.padBuffer();
+		this.processBuffer();
+		int[] result = (int[]) HConstants.clone();
+		// After the user asks for the hash value, the stream is put back to the
+		// initial state
+		reset();
+		return result;
+	}
+
+	/**
+	 * Returns a byte array (length = 20) with the SHA value of the bytes
+	 * written to the receiver.
+	 * 
+	 * @return byte[] The bytes that form the SHA value of the bytes written to
+	 *         the receiver
+	 */
+	public byte[] getHashAsBytes() {
+		byte[] hash = new byte[HashSizeInBytes];
+		this.padBuffer();
+		this.processBuffer();
+
+		// We need to return HConstants (modified by the loop) as an array of
+		// bytes. A memcopy would be the fastest.
+		for (int i = 0; i < (HashSizeInBytes / 4); ++i) {
+			hash[i * 4] = (byte) (HConstants[i] >>> 24 & 0xff);
+			hash[i * 4 + 1] = (byte) (HConstants[i] >>> 16 & 0xff);
+			hash[i * 4 + 2] = (byte) (HConstants[i] >>> 8 & 0xff);
+			hash[i * 4 + 3] = (byte) (HConstants[i] & 0xff);
+		}
+		// After the user asks for the hash value, the stream is put back to the
+		// initial state
+		reset();
+		return hash;
+	}
+
+	/**
+	 * Returns a byte array (length = 20) with the SHA value of the bytes
+	 * written to the receiver.
+	 * 
+	 * @return byte[] The bytes that form the SHA value of the bytes written to
+	 *         the receiver
+	 */
+	public byte[] getHashAsBytes(boolean pad) {
+		byte[] hash = new byte[HashSizeInBytes];
+		if (pad) {
+			this.padBuffer();
+			this.processBuffer();
+		}
+
+		// Convert HConstants to an array of bytes
+		for (int i = 0; i < (HashSizeInBytes / 4); i++) {
+			hash[i * 4] = (byte) (HConstants[i] >>> 24 & 0xff);
+			hash[i * 4 + 1] = (byte) (HConstants[i] >>> 16 & 0xff);
+			hash[i * 4 + 2] = (byte) (HConstants[i] >>> 8 & 0xff);
+			hash[i * 4 + 3] = (byte) (HConstants[i] & 0xff);
+		}
+		// After the user asks for the hash value, the stream is put back to the
+		// initial state
+		reset();
+		return hash;
+	}
+
+	/**
+	 * Initializes the receiver.
+	 */
+	private void initialize() {
+		HConstants = new int[HConstantsSize];
+		MArray = new byte[BlockSizeInBytes];
+		WArray = new int[WArraySize];
+	}
+
+	/**
+	 * Adds extra bytes to the bit stream as required (see the SHA
+	 * specification).
+	 */
+	private void padBuffer() {
+		long lengthInBits;
+		MArray[bytesToProcess] = (byte) 0x80;
+		for (int i = bytesToProcess + 1; i < BlockSizeInBytes; i++) {
+			MArray[i] = (byte) 0;
+		}
+		// Get length now because there might be extra padding (length in bits)
+		lengthInBits = (bytesToProcess + bytesProcessed) * 8;
+
+		// 9 extra bytes are needed: 1 for 1000... and 8 for length (long)
+		if ((bytesToProcess + 9) > BlockSizeInBytes) {
+			// Not enough space to append length. We need another block for
+			// padding
+			// Padding in this buffer only includes 1000000....
+			this.processBuffer();
+			// Now put 0's in all the buffer. memfill would be faster
+			for (int i = 0; i < BlockSizeInBytes; i++) {
+				MArray[i] = (byte) 0;
+			}
+		}
+
+		for (int i = 1; i < 9; i++) {
+			MArray[BlockSizeInBytes - i] = (byte) (lengthInBits & 0xff);
+			lengthInBits = lengthInBits >>> 8;
+		}
+	}
+
+	/**
+	 * Core SHA code. Processes the receiver's buffer of bits, computing the
+	 * values towards the final SHA
+	 */
+	private void processBuffer() {
+		int A; // A variable, from spec
+		int B; // B variable, from spec
+		int C; // C variable, from spec
+		int D; // D variable, from spec
+		int E; // E variable, from spec
+		int temp; // TEMP, from spec
+		int t; // t, for iteration, from spec
+
+		for (t = 0; t <= 15; t++) { // step a, page 7 of spec. Here we convert 4
+			// bytes into 1 word, 16 times
+			WArray[t] = (MArray[4 * t] & 0xff) << 24
+					| ((MArray[4 * t + 1] & 0xff) << 16)
+					| ((MArray[4 * t + 2] & 0xff) << 8)
+					| (MArray[4 * t + 3] & 0xff);
+		}
+		for (t = 16; t <= 79; t++) { // step b, page 7 of spec
+			temp = (WArray[t - 3] ^ WArray[t - 8] ^ WArray[t - 14] ^ WArray[t - 16]);
+			temp = (temp << 1) | (temp >>> (32 - 1)); // element , Circular
+			// Shift Left by 1
+			WArray[t] = temp;
+		}
+
+		// step c, page 7 of spec
+		A = HConstants[0];
+		B = HConstants[1];
+		C = HConstants[2];
+		D = HConstants[3];
+		E = HConstants[4];
+
+		// step d, page 8 of spec
+		for (t = 0; t <= 19; t++) {
+			temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
+			temp = temp + E + WArray[t] + K0_19;
+			temp = temp + ((B & C) | (~B & D));
+			E = D;
+			D = C;
+			C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
+			B = A;
+			A = temp;
+		}
+		for (t = 20; t <= 39; t++) {
+			temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
+			temp = temp + E + WArray[t] + K20_39;
+			temp = temp + (B ^ C ^ D);
+			E = D;
+			D = C;
+			C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
+			B = A;
+			A = temp;
+		}
+		for (t = 40; t <= 59; t++) {
+			temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
+			temp = temp + E + WArray[t] + K40_59;
+			temp = temp + ((B & C) | (B & D) | (C & D));
+			E = D;
+			D = C;
+			C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
+			B = A;
+			A = temp;
+		}
+		for (t = 60; t <= 79; t++) {
+			temp = (A << 5) | (A >>> (32 - 5)); // A , Circular Shift Left by 5
+			temp = temp + E + WArray[t] + K60_79;
+			temp = temp + (B ^ C ^ D);
+			E = D;
+			D = C;
+			C = (B << 30) | (B >>> (32 - 30)); // B , Circular Shift Left by 30
+			B = A;
+			A = temp;
+		}
+
+		// step e, page 8 of spec
+		HConstants[0] = HConstants[0] + A;
+		HConstants[1] = HConstants[1] + B;
+		HConstants[2] = HConstants[2] + C;
+		HConstants[3] = HConstants[3] + D;
+		HConstants[4] = HConstants[4] + E;
+		// Update number of bytes actually processed
+		bytesProcessed = bytesProcessed + BlockSizeInBytes;
+		bytesToProcess = 0; // No pending bytes in the block
+
+	}
+
+	/**
+	 * Reset this SHAOutputStream to the state it was before any byte was
+	 * written to it.
+	 */
+	public void reset() {
+		HConstants[0] = H0;
+		HConstants[1] = H1;
+		HConstants[2] = H2;
+		HConstants[3] = H3;
+		HConstants[4] = H4;
+		bytesProcessed = 0;
+		bytesToProcess = 0;
+	}
+
+	/**
+	 * Answers a string containing a concise, human-readable description of the
+	 * receiver.
+	 * 
+	 * @return a printable representation for the receiver.
+	 */
+	public String toString() {
+		return this.getClass().getName() + ':'
+				+ toStringBlock(getHashAsBytes());
+	}
+
+	/**
+	 * Converts a block to a String representation.
+	 * 
+	 * @param block
+	 *            byte array representation of the bytes
+	 */
+	private static String toStringBlock(byte[] block) {
+		return toStringBlock(block, 0, block.length);
+	}
+
+	/**
+	 * Converts a block to a String representation.
+	 * 
+	 * @param block
+	 *            byte array representation of the bytes
+	 * @param off
+	 *            offset into the block where to start the conversion
+	 * @param len
+	 *            how many bytes in the byte array to convert to a printable
+	 *            representation
+	 */
+	private static String toStringBlock(byte[] block, int off, int len) {
+		String hexdigits = "0123456789ABCDEF";
+		StringBuffer buf = new StringBuffer();
+		for (int i = off; i < off + len; ++i) {
+			buf.append(hexdigits.charAt((block[i] >>> 4) & 0xf));
+			buf.append(hexdigits.charAt(block[i] & 0xf));
+		}
+		return "[" + buf + "]";
+	}
+
+	/**
+	 * Writes <code>len</code> <code>bytes</code> from this byte array
+	 * <code>buffer</code> starting at offset <code>off</code> to the
+	 * SHAOutputStream. The internal buffer used to compute SHA is updated, and
+	 * the incremental computation of SHA is also performed.
+	 * 
+	 * @param buffer
+	 *            the buffer to be written
+	 * @param off
+	 *            offset in buffer to get bytes
+	 * @param len
+	 *            number of bytes in buffer to write
+	 */
+	public void write(byte[] buffer, int off, int len) {
+		int spaceLeft;
+		int start;
+		int bytesLeft;
+		spaceLeft = BlockSizeInBytes - bytesToProcess;
+		if (len < spaceLeft) { // Extra bytes are not enough to fill buffer
+			this.copyToInternalBuffer(buffer, off, len);
+			return;
+		}
+		// Extra bytes are bigger than space in buffer. Process buffer multiple
+		// times
+		this.copyToInternalBuffer(buffer, off, spaceLeft);
+		bytesLeft = len - spaceLeft;
+		this.processBuffer();
+		start = off + spaceLeft;
+		while (bytesLeft >= BlockSizeInBytes) {
+			this.copyToInternalBuffer(buffer, start, BlockSizeInBytes);
+			bytesLeft = bytesLeft - BlockSizeInBytes;
+			this.processBuffer();
+			start = start + BlockSizeInBytes;
+		}
+		if (bytesLeft > 0) {
+			// Extra bytes at the end, not enough to fill buffer
+			this.copyToInternalBuffer(buffer, start, bytesLeft);
+		}
+	}
+
+	/**
+	 * Writes the specified byte <code>b</code> to this OutputStream. Only the
+	 * low order byte of <code>b</code> is written.
+	 * 
+	 * @param b
+	 *            the byte to be written
+	 */
+	public void write(int b) {
+		// Not thread-safe because we use a shared one-byte buffer
+		oneByte[0] = (byte) b;
+		write(oneByte, 0, 1);
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Sorter.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Sorter.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Sorter.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Sorter.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,40 @@
+/* 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 com.ibm.oti.util;
+
+
+import java.util.Arrays;
+
+/**
+ * Helper class with methods for sorting arrays.
+ */
+public final class Sorter {
+	public interface Comparator extends java.util.Comparator {
+	}
+
+	/**
+	 * Sorts the array of objects using the default sorting algorithm.
+	 * 
+	 * @param objs
+	 *            array of objects to be sorted
+	 * @param comp
+	 *            A Comparator to be used to sort the elements
+	 */
+	public static void sort(Object[] objs, Comparator comp) {
+		Arrays.sort(objs, comp);
+	}
+
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Util.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Util.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Util.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/util/Util.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,268 @@
+/* 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 com.ibm.oti.util;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.UTFDataFormatException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+public final class Util {
+
+	private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday",
+			"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
+
+	private static String[] MONTHS = new String[] { "January", "February",
+			"March", "April", "May", "June", "July", "August", "September",
+			"October", "November", "December" };
+
+	private static final String defaultEncoding;
+
+	static {
+		String encoding = System.getProperty("os.encoding");
+		if (encoding != null) {
+			try {
+				"".getBytes(encoding);
+			} catch (java.io.UnsupportedEncodingException e) {
+				encoding = null;
+			}
+		}
+		defaultEncoding = encoding;
+	}
+
+	public static byte[] getBytes(String name) {
+		if (defaultEncoding != null) {
+			try {
+				return name.getBytes(defaultEncoding);
+			} catch (java.io.UnsupportedEncodingException e) {
+			}
+		}
+		return name.getBytes();
+	}
+
+	public static String toString(byte[] bytes) {
+		if (defaultEncoding != null) {
+			try {
+				return new String(bytes, 0, bytes.length, defaultEncoding);
+			} catch (java.io.UnsupportedEncodingException e) {
+			}
+		}
+		return new String(bytes, 0, bytes.length);
+	}
+
+	public static String toString(byte[] bytes, int offset, int length) {
+		if (defaultEncoding != null) {
+			try {
+				return new String(bytes, offset, length, defaultEncoding);
+			} catch (java.io.UnsupportedEncodingException e) {
+			}
+		}
+		return new String(bytes, offset, length);
+	}
+
+	/**
+	 * Answers the millisecond value of the date and time parsed from the
+	 * specified String. Many date/time formats are recognized
+	 * 
+	 * @param string
+	 *            the String to parse
+	 * @return the millisecond value parsed from the String
+	 */
+	public static long parseDate(String string) {
+		int offset = 0, length = string.length(), state = 0;
+		int year = -1, month = -1, date = -1;
+		int hour = -1, minute = -1, second = -1;
+		final int PAD = 0, LETTERS = 1, NUMBERS = 2;
+		StringBuffer buffer = new StringBuffer();
+
+		while (offset <= length) {
+			char next = offset < length ? string.charAt(offset) : '\r';
+			offset++;
+
+			int nextState;
+			if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))
+				nextState = LETTERS;
+			else if (next >= '0' && next <= '9')
+				nextState = NUMBERS;
+			else if (" ,-:\r\t".indexOf(next) == -1)
+				throw new IllegalArgumentException();
+			else
+				nextState = PAD;
+
+			if (state == NUMBERS && nextState != NUMBERS) {
+				int digit = Integer.parseInt(buffer.toString());
+				buffer.setLength(0);
+				if (digit >= 70) {
+					if (year != -1
+							|| (next != ' ' && next != ',' && next != '\r'))
+						throw new IllegalArgumentException();
+					year = digit;
+				} else if (next == ':') {
+					if (hour == -1)
+						hour = digit;
+					else if (minute == -1)
+						minute = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (next == ' ' || next == ',' || next == '-'
+						|| next == '\r') {
+					if (hour != -1 && minute == -1)
+						minute = digit;
+					else if (minute != -1 && second == -1)
+						second = digit;
+					else if (date == -1)
+						date = digit;
+					else if (year == -1)
+						year = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (year == -1 && month != -1 && date != -1)
+					year = digit;
+				else
+					throw new IllegalArgumentException();
+			} else if (state == LETTERS && nextState != LETTERS) {
+				String text = buffer.toString().toUpperCase();
+				buffer.setLength(0);
+				if (text.length() < 3)
+					throw new IllegalArgumentException();
+				if (parse(text, WEEKDAYS) != -1) {
+				} else if (month == -1 && (month = parse(text, MONTHS)) != -1) {
+				} else if (text.equals("GMT")) {
+				} else
+					throw new IllegalArgumentException();
+			}
+
+			if (nextState == LETTERS || nextState == NUMBERS)
+				buffer.append(next);
+			state = nextState;
+		}
+
+		if (year != -1 && month != -1 && date != -1) {
+			if (hour == -1)
+				hour = 0;
+			if (minute == -1)
+				minute = 0;
+			if (second == -1)
+				second = 0;
+			Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+			int current = cal.get(Calendar.YEAR) - 80;
+			if (year < 100) {
+				year += current / 100 * 100;
+				if (year < current)
+					year += 100;
+			}
+			cal.set(Calendar.YEAR, year);
+			cal.set(Calendar.MONTH, month);
+			cal.set(Calendar.DATE, date);
+			cal.set(Calendar.HOUR_OF_DAY, hour);
+			cal.set(Calendar.MINUTE, minute);
+			cal.set(Calendar.SECOND, second);
+			cal.set(Calendar.MILLISECOND, 0);
+			return cal.getTime().getTime();
+		}
+		throw new IllegalArgumentException();
+	}
+
+	private static int parse(String string, String[] array) {
+		int length = string.length();
+		for (int i = 0; i < array.length; i++) {
+			if (string.regionMatches(true, 0, array[i], 0, length))
+				return i;
+		}
+		return -1;
+	}
+
+	public static String convertFromUTF8(byte[] buf, int offset, int utfSize)
+			throws UTFDataFormatException {
+		return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize);
+	}
+
+	public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset,
+			int utfSize) throws UTFDataFormatException {
+		int count = 0, s = 0, a;
+		while (count < utfSize) {
+			if ((out[s] = (char) buf[offset + count++]) < '\u0080')
+				s++;
+			else if (((a = out[s]) & 0xe0) == 0xc0) {
+				if (count >= utfSize)
+					throw new UTFDataFormatException(Msg.getString("K0062",
+							count));
+				int b = buf[count++];
+				if ((b & 0xC0) != 0x80)
+					throw new UTFDataFormatException(Msg.getString("K0062",
+							(count - 1)));
+				out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+			} else if ((a & 0xf0) == 0xe0) {
+				if (count + 1 >= utfSize)
+					throw new UTFDataFormatException(Msg.getString("K0063",
+							(count + 1)));
+				int b = buf[count++];
+				int c = buf[count++];
+				if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
+					throw new UTFDataFormatException(Msg.getString("K0064",
+							(count - 2)));
+				out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+			} else {
+				throw new UTFDataFormatException(Msg.getString("K0065",
+						(count - 1)));
+			}
+		}
+		return new String(out, 0, s);
+	}
+
+	/**
+	 * '%' and two following hex digit characters are converted to the
+	 * equivalent byte value. All other characters are passed through
+	 * unmodified. e.g. "ABC %24%25" -> "ABC $%"
+	 * 
+	 * @param s
+	 *            java.lang.String The encoded string.
+	 * @return java.lang.String The decoded version.
+	 */
+	public static String decode(String s, boolean convertPlus) {
+		if (!convertPlus && s.indexOf('%') == -1)
+			return s;
+		StringBuffer result = new StringBuffer(s.length());
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		for (int i = 0; i < s.length();) {
+			char c = s.charAt(i);
+			if (convertPlus && c == '+')
+				result.append(' ');
+			else if (c == '%') {
+				out.reset();
+				do {
+					if (i + 2 >= s.length())
+						throw new IllegalArgumentException(Msg.getString(
+								"K01fe", i));
+					int d1 = Character.digit(s.charAt(i + 1), 16);
+					int d2 = Character.digit(s.charAt(i + 2), 16);
+					if (d1 == -1 || d2 == -1)
+						throw new IllegalArgumentException(Msg.getString(
+								"K01ff", s.substring(i, i + 3), String
+										.valueOf(i)));
+					out.write((byte) ((d1 << 4) + d2));
+					i += 3;
+				} while (i < s.length() && s.charAt(i) == '%');
+				result.append(out.toString());
+				continue;
+			} else
+				result.append(c);
+			i++;
+		}
+		return result.toString();
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/vm/MsgHelp.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/vm/MsgHelp.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/vm/MsgHelp.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/vm/MsgHelp.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,118 @@
+/* Copyright 2003, 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 com.ibm.oti.vm;
+
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This class contains helper methods for loading resource bundles and
+ * formatting external message strings.
+ */
+
+public final class MsgHelp {
+
+	/**
+	 * Generates a formatted text string given a source string containing
+	 * "argument markers" of the form "{argNum}" where each argNum must be in
+	 * the range 0..9. The result is generated by inserting the toString of each
+	 * argument into the position indicated in the string.
+	 * <p>
+	 * To insert the "{" character into the output, use a single backslash
+	 * character to escape it (i.e. "\{"). The "}" character does not need to be
+	 * escaped.
+	 * 
+	 * @param format
+	 *            String the format to use when printing.
+	 * @param args
+	 *            Object[] the arguments to use.
+	 * @return String the formatted message.
+	 */
+	public static String format(String format, Object[] args) {
+		StringBuffer answer = new StringBuffer(format.length()
+				+ (args.length * 20));
+		String[] argStrings = new String[args.length];
+		for (int i = 0; i < args.length; ++i) {
+			if (args[i] == null)
+				argStrings[i] = "<null>";
+			else
+				argStrings[i] = args[i].toString();
+		}
+		int lastI = 0;
+		for (int i = format.indexOf('{', 0); i >= 0; i = format.indexOf('{',
+				lastI)) {
+			if (i != 0 && format.charAt(i - 1) == '\\') {
+				// It's escaped, just print and loop.
+				if (i != 1)
+					answer.append(format.substring(lastI, i - 1));
+				answer.append('{');
+				lastI = i + 1;
+			} else {
+				// It's a format character.
+				if (i > format.length() - 3) {
+					// Bad format, just print and loop.
+					answer.append(format.substring(lastI, format.length()));
+					lastI = format.length();
+				} else {
+					int argnum = (byte) Character.digit(format.charAt(i + 1),
+							10);
+					if (argnum < 0 || format.charAt(i + 2) != '}') {
+						// Bad format, just print and loop.
+						answer.append(format.substring(lastI, i + 1));
+						lastI = i + 1;
+					} else {
+						// Got a good one!
+						answer.append(format.substring(lastI, i));
+						if (argnum >= argStrings.length)
+							answer.append("<missing argument>");
+						else
+							answer.append(argStrings[argnum]);
+						lastI = i + 3;
+					}
+				}
+			}
+		}
+		if (lastI < format.length())
+			answer.append(format.substring(lastI, format.length()));
+		return answer.toString();
+	}
+
+	/**
+	 * Changes the locale of the messages.
+	 * 
+	 * @param locale
+	 *            Locale the locale to change to.
+	 */
+	static public ResourceBundle setLocale(final Locale locale,
+			final String resource) {
+		try {
+			final ClassLoader loader = VM.getStackClassLoader(1);
+			return (ResourceBundle) AccessController
+					.doPrivileged(new PrivilegedAction() {
+						public Object run() {
+							return ResourceBundle.getBundle(resource, locale,
+									loader);
+						}
+					});
+		} catch (MissingResourceException e) {
+		}
+		return null;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,336 @@
+/* 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.io;
+
+
+/**
+ * <code>BufferedInputStream</code> is a class which takes an input stream and
+ * <em>buffers</em> the input. In this way, costly interaction with the
+ * original input stream can be minimized by reading buffered amounts of data
+ * infrequently. The drawback is that extra space is required to hold the buffer
+ * and that copying takes place when reading that buffer.
+ * 
+  * @see BufferedOutputStream
+ */
+public class BufferedInputStream extends FilterInputStream {
+	/**
+	 * The buffer containing the current bytes read from the target InputStream.
+	 */
+	protected byte[] buf;
+
+	/**
+	 * The total number of bytes inside the byte array <code>buf</code>.
+	 */
+	protected int count;
+
+	/**
+	 * The current limit, which when passed, invalidates the current mark.
+	 */
+	protected int marklimit;
+
+	/**
+	 * The currently marked position. -1 indicates no mark has been set or the
+	 * mark has been invalidated.
+	 */
+	protected int markpos = -1;
+
+	/**
+	 * The current position within the byte array <code>buf</code>.
+	 */
+	protected int pos;
+
+	/**
+	 * Constructs a new <code>BufferedInputStream</code> on the InputStream
+	 * <code>in</code>. The default buffer size (2K) is allocated and all
+	 * reads can now be filtered through this stream.
+	 * 
+	 * @param in
+	 *            the InputStream to buffer reads on.
+	 */
+	public BufferedInputStream(InputStream in) {
+		super(in);
+		buf = new byte[2048];
+	}
+
+	/**
+	 * Constructs a new BufferedInputStream on the InputStream <code>in</code>.
+	 * The buffer size is specified by the parameter <code>size</code> and all
+	 * reads can now be filtered through this BufferedInputStream.
+	 * 
+	 * @param in
+	 *            the InputStream to buffer reads on.
+	 * @param size
+	 *            the size of buffer to allocate.
+	 */
+	public BufferedInputStream(InputStream in, int size) {
+		super(in);
+		if (size > 0)
+			buf = new byte[size];
+		else
+			throw new IllegalArgumentException(com.ibm.oti.util.Msg
+					.getString("K0058")); //$NON-NLS-1$
+	}
+
+	/**
+	 * Answers a int representing then number of bytes that are available before
+	 * this BufferedInputStream will block. This method returns the number of
+	 * bytes available in the buffer plus those available in the target stream.
+	 * 
+	 * @return the number of bytes available before blocking.
+	 * 
+	 * @throws IOException
+	 *             If an error occurs in this stream.
+	 */
+	public synchronized int available() throws IOException {
+		if (buf == null) {
+			throw new IOException(com.ibm.oti.util.Msg.getString("K0059")); //$NON-NLS-1$
+		}
+		return count - pos + in.available();
+	}
+
+	/**
+	 * Close this BufferedInputStream. This implementation closes the target
+	 * stream and releases any resources associated with it.
+	 * 
+	 * @throws IOException
+	 *             If an error occurs attempting to close this stream.
+	 */
+	public synchronized void close() throws IOException {
+		super.close();
+		buf = null;
+	}
+
+	private int fillbuf() throws IOException {
+		if (markpos == -1 || (pos - markpos >= marklimit)) {
+			/* Mark position not set or exceeded readlimit */
+			int result = in.read(buf);
+			markpos = -1;
+			pos = 0;
+			count = result == -1 ? 0 : result;
+			return result;
+		}
+		if (marklimit > buf.length) {
+			/* Increase buffer size to accomodate the readlimit */
+			byte[] newbuf = new byte[marklimit];
+			System.arraycopy(buf, markpos, newbuf, 0, buf.length - markpos);
+			buf = newbuf;
+		} else if (markpos > 0) {
+			System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
+		}
+		/* Set the new position and mark position */
+		pos -= markpos;
+		count = markpos = 0;
+		int bytesread = in.read(buf, pos, buf.length - pos);
+		count = bytesread <= 0 ? pos : pos + bytesread;
+		return bytesread;
+	}
+
+	/**
+	 * Set a Mark position in this BufferedInputStream. The parameter
+	 * <code>readLimit</code> indicates how many bytes can be read before a
+	 * mark is invalidated. Sending reset() will reposition the Stream back to
+	 * the marked position provided <code>readLimit</code> has not been
+	 * surpassed. The underlying buffer may be increased in size to allow
+	 * <code>readlimit</code> number of bytes to be supported.
+	 * 
+	 * @param readlimit
+	 *            the number of bytes to be able to read before invalidating the
+	 *            mark.
+	 */
+	public synchronized void mark(int readlimit) {
+		marklimit = readlimit;
+		markpos = pos;
+	}
+
+	/**
+	 * Answers a boolean indicating whether or not this BufferedInputStream
+	 * supports mark() and reset(). This implementation answers
+	 * <code>true</code>.
+	 * 
+	 * @return <code>true</code> for BufferedInputStreams.
+	 */
+	public boolean markSupported() {
+		return true;
+	}
+
+	/**
+	 * Reads a single byte from this BufferedInputStream and returns the result
+	 * as an int. The low-order byte is returned or -1 of the end of stream was
+	 * encountered. If the underlying buffer does not contain any available
+	 * bytes then it is filled and the first byte is returned.
+	 * 
+	 * @return the byte read or -1 if end of stream.
+	 * 
+	 * @throws IOException
+	 *             If the stream is already closed or another IOException
+	 *             occurs.
+	 */
+	public synchronized int read() throws IOException {
+		if (buf != null) {
+			/* Are there buffered bytes available? */
+			if (pos >= count && fillbuf() == -1)
+				return -1; /* no, fill buffer */
+
+			/* Did filling the buffer fail with -1 (EOF)? */
+			if (count - pos > 0)
+				return buf[pos++] & 0xFF;
+			return -1;
+		}
+		throw new IOException(com.ibm.oti.util.Msg.getString("K0059")); //$NON-NLS-1$
+	}
+
+	/**
+	 * Reads at most <code>length</code> bytes from this BufferedInputStream
+	 * and stores them in byte array <code>buffer</code> starting at offset
+	 * <code>offset</code>. Answer the number of bytes actually read or -1 if
+	 * no bytes were read and end of stream was encountered. If all the buffered
+	 * bytes have been used, a mark has not been set, and the requested number
+	 * of bytes is larger than the receiver's buffer size, this implementation
+	 * bypasses the buffer and simply places the results directly into
+	 * <code>buffer</code>.
+	 * 
+	 * @param buffer
+	 *            the byte array in which to store the read bytes.
+	 * @param offset
+	 *            the offset in <code>buffer</code> to store the read bytes.
+	 * @param length
+	 *            the maximum number of bytes to store in <code>buffer</code>.
+	 * @return the number of bytes actually read or -1 if end of stream.
+	 * 
+	 * @throws IOException
+	 *             If the stream is already closed or another IOException
+	 *             occurs.
+	 */
+	public synchronized int read(byte[] buffer, int offset, int length)
+			throws IOException {
+		if (buf != null && buffer != null) {
+			// avoid int overflow
+			if (0 <= offset && offset <= buffer.length && 0 <= length
+					&& length <= buffer.length - offset) {
+				if (length == 0)
+					return 0;
+
+				int required;
+				if (pos < count) {
+					/* There are bytes available in the buffer. */
+					int copylength = count - pos >= length ? length : count
+							- pos;
+					System.arraycopy(buf, pos, buffer, offset, copylength);
+					pos += copylength;
+					if (copylength == length || in.available() == 0)
+						return copylength;
+					offset += copylength;
+					required = length - copylength;
+				} else
+					required = length;
+
+				while (true) {
+					int read;
+					/*
+					 * If we're not marked and the required size is greater than
+					 * the buffer, simply read the bytes directly bypassing the
+					 * buffer.
+					 */
+					if (markpos == -1 && required >= buf.length) {
+						read = in.read(buffer, offset, required);
+						if (read == -1)
+							return required == length ? -1 : length - required;
+					} else {
+						if (fillbuf() == -1)
+							return required == length ? -1 : length - required;
+						read = count - pos >= required ? required : count - pos;
+						System.arraycopy(buf, pos, buffer, offset, read);
+						pos += read;
+					}
+					required -= read;
+					if (required == 0)
+						return length;
+					if (in.available() == 0)
+						return length - required;
+					offset += read;
+				}
+			}
+			throw new ArrayIndexOutOfBoundsException();
+		}
+		if (buf == null) {
+			throw new IOException(com.ibm.oti.util.Msg.getString("K0059")); //$NON-NLS-1$
+		}
+		throw new NullPointerException(com.ibm.oti.util.Msg.getString("K0047")); //$NON-NLS-1$
+	}
+
+	/**
+	 * Reset this BufferedInputStream to the last marked location. If the
+	 * <code>readlimit</code> has been passed or no <code>mark</code> has
+	 * been set, throw IOException. This implementation resets the target
+	 * stream.
+	 * 
+	 * @throws IOException
+	 *             If the stream is already closed or another IOException
+	 *             occurs.
+	 */
+
+	public synchronized void reset() throws IOException {
+		if (markpos != -1) {
+			if (buf != null) {
+				pos = markpos;
+			} else
+				throw new IOException(com.ibm.oti.util.Msg.getString("K0059")); //$NON-NLS-1$
+		} else
+			throw new IOException(com.ibm.oti.util.Msg.getString("K005a")); //$NON-NLS-1$
+	}
+
+	/**
+	 * Skips <code>amount</code> number of bytes in this BufferedInputStream.
+	 * Subsequent <code>read()</code>'s will not return these bytes unless
+	 * <code>reset()</code> is used.
+	 * 
+	 * @param amount
+	 *            the number of bytes to skip.
+	 * @return the number of bytes actually skipped.
+	 * 
+	 * @throws IOException
+	 *             If the stream is already closed or another IOException
+	 *             occurs.
+	 */
+	public synchronized long skip(long amount) throws IOException {
+		if (amount < 1)
+			return 0;
+
+		if (count - pos >= amount) {
+			pos += amount;
+			return amount;
+		}
+		long read = count - pos;
+		pos = count;
+
+		if (markpos != -1) {
+			if (amount <= marklimit) {
+				if (fillbuf() == -1)
+					return read;
+				if (count - pos >= amount - read) {
+					pos += amount - read;
+					return amount;
+				}
+				// Couldn't get all the bytes, skip what we read
+				read += (count - pos);
+				pos = count;
+				return read;
+			}
+			markpos = -1;
+		}
+		return read + in.skip(amount - read);
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedOutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedOutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedOutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,174 @@
+/* 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.io;
+
+
+/**
+ * BufferedOutputStream is a class which takes an output stream and
+ * <em>buffers</em> the writes to that stream. In this way, costly interaction
+ * with the original output stream can be minimized by writing buffered amounts
+ * of data infrequently. The drawback is that extra space is required to hold
+ * the buffer and copying takes place when writing that buffer.
+ * 
+ * @see BufferedInputStream
+ */
+public class BufferedOutputStream extends FilterOutputStream {
+	/**
+	 * The buffer containing the bytes to be written to the target OutputStream.
+	 */
+	protected byte[] buf;
+
+	/**
+	 * The total number of bytes inside the byte array <code>buf</code>.
+	 */
+	protected int count;
+
+	/**
+	 * Constructs a new BufferedOutputStream on the OutputStream
+	 * <code>out</code>. The default buffer size (512 bytes) is allocated and
+	 * all writes are now filtered through this stream.
+	 * 
+	 * @param out
+	 *            the OutputStream to buffer writes on.
+	 * 
+	 */
+	public BufferedOutputStream(OutputStream out) {
+		super(out);
+		buf = new byte[512];
+	}
+
+	/**
+	 * Constructs a new BufferedOutputStream on the OutputStream
+	 * <code>out</code>. The buffer size is set to <code>size</code> and
+	 * all writes are now filtered through this stream.
+	 * 
+     * @param out
+	 *            the OutputStream to buffer writes on.
+	 * @param size
+	 *            the size of the buffer in bytes.
+	 * 
+	 */
+	public BufferedOutputStream(OutputStream out, int size) {
+		super(out);
+		if (size > 0)
+			buf = new byte[size];
+		else
+			throw new IllegalArgumentException(com.ibm.oti.util.Msg
+					.getString("K0058")); //$NON-NLS-1$
+	}
+
+	/**
+	 * Flush this BufferedOutputStream to ensure all pending data is written out
+	 * to the target OutputStream. In addition, the target stream is also
+	 * flushed.
+	 * 
+	 * @throws IOException
+	 *             If an error occurs attempting to flush this
+	 *             BufferedOutputStream.
+	 */
+	public synchronized void flush() throws IOException {
+		if (count > 0)
+			out.write(buf, 0, count);
+		count = 0;
+		out.flush();
+	}
+
+	/**
+	 * Writes <code>count</code> <code>bytes</code> from the byte array
+	 * <code>buffer</code> starting at <code>offset</code> to this
+	 * BufferedOutputStream. If there is room in the buffer to hold the bytes,
+	 * they are copied in. If not, the buffered bytes plus the bytes in
+	 * <code>buffer</code> are written to the target stream, the target is
+	 * flushed, and the buffer is cleared.
+	 * 
+	 * @param buffer
+	 *            the buffer to be written
+	 * @param offset
+	 *            offset in buffer to get bytes
+	 * @param length
+	 *            number of bytes in buffer to write
+	 * 
+	 * @throws IOException
+	 *             If an error occurs attempting to write to this
+	 *             BufferedOutputStream.
+	 * @throws NullPointerException
+	 *             If buffer is null.
+	 * @throws IndexOutOfBoundsException
+	 *             If offset or count are outside of bounds.
+	 */
+	public synchronized void write(byte[] buffer, int offset, int length)
+			throws IOException {
+		if (buffer != null) {
+			// avoid int overflow
+			if (0 <= offset && offset <= buffer.length && 0 <= length
+					&& length <= buffer.length - offset) {
+				if (count == 0 && length >= buf.length) {
+					out.write(buffer, offset, length);
+					return;
+				}
+				int available = buf.length - count;
+				if (length < available)
+					available = length;
+				if (available > 0) {
+					System.arraycopy(buffer, offset, buf, count, available);
+					count += available;
+				}
+				if (count == buf.length) {
+					out.write(buf, 0, buf.length);
+					count = 0;
+					if (length > available) {
+						offset += available;
+						available = length - available;
+						if (available >= buf.length) {
+							out.write(buffer, offset, available);
+						} else {
+							System.arraycopy(buffer, offset, buf, count,
+									available);
+							count += available;
+						}
+					}
+				}
+			} else
+				throw new ArrayIndexOutOfBoundsException(com.ibm.oti.util.Msg
+						.getString("K002f")); //$NON-NLS-1$
+		} else
+			throw new NullPointerException(com.ibm.oti.util.Msg
+					.getString("K0047")); //$NON-NLS-1$
+	}
+
+	/**
+	 * Writes the specified byte <code>oneByte</code> to this
+	 * BufferedOutputStream. Only the low order byte of <code>oneByte</code>
+	 * is written. If there is room in the buffer, the byte is copied in and the
+	 * count incremented. Otherwise, the buffer plus <code>oneByte</code> are
+	 * written to the target stream, the target is flushed, and the buffer is
+	 * reset.
+	 * 
+	 * @param oneByte
+	 *            the byte to be written
+	 * 
+	 * @throws IOException
+	 *             If an error occurs attempting to write to this
+	 *             BufferedOutputStream.
+	 */
+	public synchronized void write(int oneByte) throws IOException {
+		if (count == buf.length) {
+			out.write(buf, 0, count);
+			count = 0;
+		}
+		buf[count++] = (byte) oneByte;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedReader.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedReader.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedReader.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/BufferedReader.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,439 @@
+/* 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.io;
+
+
+/**
+ * BufferedReader is a buffered character input reader. Buffering allows reading
+ * from character streams more efficiently. If the default size of the buffer is
+ * not practical, another size may be specified. Reading a character from a
+ * Reader class usually involves reading a character from its Stream or
+ * subsequent Reader. It is advisable to wrap a BufferedReader around those
+ * Readers whose read operations may have high latency. For example, the
+ * following code
+ * 
+ * <pre>
+ * BufferedReader inReader = new BufferedReader(new FileReader(&quot;file.java&quot;));
+ * </pre>
+ * 
+ * will buffer input for the file <code>file.java</code>.
+ * 
+ * @see BufferedWriter
+ */
+
+public class BufferedReader extends Reader {
+	private Reader in;
+
+	private char[] buf;
+
+	private int marklimit = -1;
+
+	private int count;
+
+	private int markpos = -1;
+
+	private int pos;
+
+	/**
+	 * Constructs a new BufferedReader on the Reader <code>in</code>. The
+	 * default buffer size (8K) is allocated and all reads can now be filtered
+	 * through this BufferedReader.
+	 * 
+	 * @param in
+	 *            the Reader to buffer reads on.
+	 */
+
+	public BufferedReader(Reader in) {
+		super(in);
+		this.in = in;
+		buf = new char[8192];
+	}
+
+	/**
+	 * Constructs a new BufferedReader on the Reader <code>in</code>. The
+	 * buffer size is specified by the parameter <code>size</code> and all
+	 * reads can now be filtered through this BufferedReader.
+	 * 
+	 * @param in
+	 *            the Reader to buffer reads on.
+	 * @param size
+	 *            the size of buffer to allocate.
+	 */
+
+	public BufferedReader(Reader in, int size) {
+		super(in);
+		if (size > 0) {
+			this.in = in;
+			buf = new char[size];
+		} else
+			throw new IllegalArgumentException(com.ibm.oti.util.Msg
+					.getString("K0058")); //$NON-NLS-1$
+	}
+
+	/**
+	 * Close the Reader. This implementation closes the Reader being filtered
+	 * and releases the buffer used by this reader. If this BufferedReader has
+	 * already been closed, nothing is done.
+	 * 
+	 * @throws IOException
+	 *             If an error occurs attempting to close this BufferedReader.
+	 */
+
+	public void close() throws IOException {
+		synchronized (lock) {
+			if (isOpen()) {
+				in.close();
+				buf = null;
+			}
+		}
+	}
+
+	private int fillbuf() throws IOException {
+		if (markpos == -1 || (pos - markpos >= marklimit)) {
+			/* Mark position not set or exceeded readlimit */
+			int result = in.read(buf, 0, buf.length);
+			markpos = -1;
+			pos = 0;
+			count = result == -1 ? 0 : result;
+			return result;
+		}
+		if (marklimit > buf.length) {
+			/* Increase buffer size to accomodate the readlimit */
+			char[] newbuf = new char[marklimit];
+			System.arraycopy(buf, markpos, newbuf, 0, buf.length - markpos);
+			buf = newbuf;
+		} else if (markpos > 0) {
+			System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
+		}
+		/* Set the new position and mark position */
+		pos -= markpos;
+		count = markpos = 0;
+		int charsread = in.read(buf, pos, buf.length - pos);
+		count = charsread == -1 ? pos : pos + charsread;
+		return charsread;
+	}
+
+	/**
+	 * Answer a boolean indicating whether or not this BufferedReader is open.
+	 * 
+	 * @return <code>true</code> if this reader is open, <code>false</code>
+	 *         otherwise
+	 */
+	private boolean isOpen() {
+		return buf != null;
+	}
+
+	/**
+	 * Set a Mark position in this BufferedReader. The parameter
+	 * <code>readLimit</code> indicates how many characters can be read before
+	 * a mark is invalidated. Sending reset() will reposition the reader back to
+	 * the marked position provided <code>readLimit</code> has not been
+	 * surpassed.
+	 * 
+	 * @param readlimit
+	 *            an int representing how many characters must be read
+	 *            beforeinvalidating the mark.
+	 * 
+	 * @throws IOException
+	 *             If an error occurs attempting mark this BufferedReader.
+	 */
+
+	public void mark(int readlimit) throws IOException {
+		if (readlimit >= 0) {
+			synchronized (lock) {
+				if (isOpen()) {
+					marklimit = readlimit;
+					markpos = pos;
+				} else
+					throw new IOException(com.ibm.oti.util.Msg
+							.getString("K005b")); //$NON-NLS-1$
+			}
+		} else
+			throw new IllegalArgumentException();
+	}
+
+	/**
+	 * Answers a boolean indicating whether or not this Reader supports mark()
+	 * and reset(). This implementation answers <code>true</code>.
+	 * 
+	 * @return <code>true</code> if mark() and reset() are supported,
+	 *         <code>false</code> otherwise
+	 */
+
+	public boolean markSupported() {
+		return true;
+	}
+
+	/**
+	 * Reads a single character from this reader and returns the result as an
+	 * int. The 2 higher-order characters are set to 0. If the end of reader was
+	 * encountered then return -1. This implementation either returns a
+	 * character from the buffer or if there are no characters available, fill
+	 * the buffer then return a character or -1.
+	 * 
+	 * @return the character read or -1 if end of reader.
+	 * 
+	 * @throws IOException
+	 *             If the BufferedReader is already closed or some other IO
+	 *             error occurs.
+	 */
+
+	public int read() throws IOException {
+		synchronized (lock) {
+			if (isOpen()) {
+				/* Are there buffered characters available? */
+				if (pos < count || fillbuf() != -1)
+					return buf[pos++];
+				return -1;
+			}
+			throw new IOException(com.ibm.oti.util.Msg.getString("K005b")); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Reads at most <code>length</code> characters from this BufferedReader
+	 * and stores them at <code>offset</code> in the character array
+	 * <code>buffer</code>. Returns the number of characters actually read or
+	 * -1 if the end of reader was encountered. If all the buffered characters
+	 * have been used, a mark has not been set, and the requested number of
+	 * characters is larger than this Readers buffer size, this implementation
+	 * bypasses the buffer and simply places the results directly into
+	 * <code>buffer</code>.
+	 * 
+	 * @param buffer
+	 *            character array to store the read characters
+	 * @param offset
+	 *            offset in buf to store the read characters
+	 * @param length
+	 *            maximum number of characters to read
+	 * @return number of characters read or -1 if end of reader.
+	 * 
+	 * @throws IOException
+	 *             If the BufferedReader is already closed or some other IO
+	 *             error occurs.
+	 */
+
+	public int read(char[] buffer, int offset, int length) throws IOException {
+		synchronized (lock) {
+			if (isOpen()) {
+				if (length == 0)
+					return 0;
+				// avoid int overflow
+				if (0 <= offset && offset <= buffer.length && 0 < length
+						&& length <= buffer.length - offset) {
+					int required;
+					if (pos < count) {
+						/* There are bytes available in the buffer. */
+						int copylength = count - pos >= length ? length : count
+								- pos;
+						System.arraycopy(buf, pos, buffer, offset, copylength);
+						pos += copylength;
+						if (copylength == length || !in.ready())
+							return copylength;
+						offset += copylength;
+						required = length - copylength;
+					} else
+						required = length;
+
+					while (true) {
+						int read;
+						/*
+						 * If we're not marked and the required size is greater
+						 * than the buffer, simply read the bytes directly
+						 * bypassing the buffer.
+						 */
+						if (markpos == -1 && required >= buf.length) {
+							read = in.read(buffer, offset, required);
+							if (read == -1)
+								return required == length ? -1 : length
+										- required;
+						} else {
+							if (fillbuf() == -1)
+								return required == length ? -1 : length
+										- required;
+							read = count - pos >= required ? required : count
+									- pos;
+							System.arraycopy(buf, pos, buffer, offset, read);
+							pos += read;
+						}
+						required -= read;
+						if (required == 0)
+							return length;
+						if (!in.ready())
+							return length - required;
+						offset += read;
+					}
+				}
+				throw new ArrayIndexOutOfBoundsException();
+			}
+			throw new IOException(com.ibm.oti.util.Msg.getString("K005b")); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Answers a <code>String</code> representing the next line of text
+	 * available in this BufferedReader. A line is represented by 0 or more
+	 * characters followed by <code>'\n'</code>, <code>'\r'</code>,
+	 * <code>'\r\n'</code> or end of stream. The <code>String</code> does
+	 * not include the newline sequence.
+	 * 
+	 * @return the contents of the line or null if no characters were read
+	 *         before end of stream.
+	 * 
+	 * @throws IOException
+	 *             If the BufferedReader is already closed or some other IO
+	 *             error occurs.
+	 */
+
+	public String readLine() throws IOException {
+		synchronized (lock) {
+			if (isOpen()) {
+				char eol = '\0';
+				StringBuffer result = new StringBuffer(80);
+				/* Typical Line Length */
+
+				while (true) {
+					/* Are there buffered characters available? */
+					if (pos >= count) {
+						if (eol == '\n')
+							return result.toString();
+						// attempt to fill buffer
+						if (fillbuf() == -1) // EOF case returns already read
+												// characters or null.
+							return result.length() > 0 || eol != '\0' ? result
+									.toString() : null;
+					}
+					for (int charPos = pos; charPos < count; charPos++) {
+						if (eol == '\0'
+								&& (buf[charPos] == '\n' || buf[charPos] == '\r')) {
+							eol = buf[charPos];
+						} else if (eol == '\r' && (buf[charPos] == '\n')) {
+							if (charPos > pos)
+								result.append(buf, pos, charPos - pos - 1);
+							pos = charPos + 1;
+							return result.toString();
+						} else if (eol != '\0') {
+							if (charPos > pos)
+								result.append(buf, pos, charPos - pos - 1);
+							pos = charPos;
+							return result.toString();
+						}
+					}
+					if (eol != '\0') // eol could only be last character.
+						result.append(buf, pos, count - pos - 1);
+					else
+						result.append(buf, pos, count - pos);
+					pos = count;
+				}
+			}
+			throw new IOException(com.ibm.oti.util.Msg.getString("K005b")); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Answers a <code>boolean</code> indicating whether or not this Reader is
+	 * ready to be read without blocking. If the result is <code>true</code>,
+	 * the next <code>read()</code> will not block. If the result is
+	 * <code>false</code> this Reader may or may not block when
+	 * <code>read()</code> is sent.
+	 * 
+	 * @return <code>true</code> if the receiver will not block when
+	 *         <code>read()</code> is called, <code>false</code> if unknown
+	 *         or blocking will occur.
+	 * 
+	 * @throws IOException
+	 *             If the BufferedReader is already closed or some other IO
+	 *             error occurs.
+	 */
+
+	public boolean ready() throws IOException {
+		synchronized (lock) {
+			if (isOpen())
+				return ((count - pos) > 0) || in.ready();
+			throw new IOException(com.ibm.oti.util.Msg.getString("K005b")); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Reset this BufferedReader's position to the last <code>mark()</code>
+	 * location. Invocations of <code>read()/skip()</code> will occur from
+	 * this new location. If this Reader was not marked, throw IOException.
+	 * 
+	 * @throws IOException
+	 *             If a problem occured, the receiver does not support
+	 *             <code>mark()/reset()</code>, or no mark has been set.
+	 */
+
+	public void reset() throws IOException {
+		synchronized (lock) {
+			if (isOpen()) {
+				if (markpos != -1)
+					pos = markpos;
+				else
+					throw new IOException(com.ibm.oti.util.Msg
+							.getString("K005c")); //$NON-NLS-1$
+			} else
+				throw new IOException(com.ibm.oti.util.Msg.getString("K005b")); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Skips <code>amount</code> number of characters in this Reader.
+	 * Subsequent <code>read()</code>'s will not return these characters
+	 * unless <code>reset()</code> is used. Skipping characters may invalidate
+	 * a mark if marklimit is surpassed.
+	 * 
+	 * @param amount
+	 *            the maximum number of characters to skip.
+	 * @return the number of characters actually skipped.
+	 * 
+	 * @throws IOException
+	 *             If the BufferedReader is already closed or some other IO
+	 *             error occurs.
+	 */
+
+	public long skip(long amount) throws IOException {
+		if (amount >= 0) {
+			synchronized (lock) {
+				if (isOpen()) {
+					if (amount < 1)
+						return 0;
+					if (count - pos >= amount) {
+						pos += amount;
+						return amount;
+					}
+
+					long read = count - pos;
+					pos = count;
+					while (read < amount) {
+						if (fillbuf() == -1)
+							return read;
+						if (count - pos >= amount - read) {
+							pos += amount - read;
+							return amount;
+						}
+						// Couldn't get all the characters, skip what we read
+						read += (count - pos);
+						pos = count;
+					}
+					return amount;
+				}
+				throw new IOException(com.ibm.oti.util.Msg.getString("K005b")); //$NON-NLS-1$
+			}
+		}
+		throw new IllegalArgumentException();
+	}
+}



Mime
View raw message