From 98e2821b38a775737e42a2479a6bc65107210859 Mon Sep 17 00:00:00 2001 From: Elliot Kroo Date: Thu, 11 Mar 2010 15:21:30 -0800 Subject: reorganizing the first level of folders (trunk/branch folders are not the git way :) --- .../rhino1_7R1/src/org/mozilla/javascript/Kit.java | 486 +++++++++++++++++++++ 1 file changed, 486 insertions(+) create mode 100644 infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java (limited to 'infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java') diff --git a/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java b/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java new file mode 100644 index 0000000..f7b4cad --- /dev/null +++ b/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java @@ -0,0 +1,486 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Igor Bukanov, igor@fastmail.fm + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.lang.reflect.Method; +import java.util.Hashtable; + +/** + * Collection of utilities + */ + +public class Kit +{ + /** + * Reflection of Throwable.initCause(Throwable) from JDK 1.4 + * or nul if it is not available. + */ + private static Method Throwable_initCause = null; + + static { + // Are we running on a JDK 1.4 or later system? + try { + Class ThrowableClass = Kit.classOrNull("java.lang.Throwable"); + Class[] signature = { ThrowableClass }; + Throwable_initCause + = ThrowableClass.getMethod("initCause", signature); + } catch (Exception ex) { + // Assume any exceptions means the method does not exist. + } + } + + public static Class classOrNull(String className) + { + try { + return Class.forName(className); + } catch (ClassNotFoundException ex) { + } catch (SecurityException ex) { + } catch (LinkageError ex) { + } catch (IllegalArgumentException e) { + // Can be thrown if name has characters that a class name + // can not contain + } + return null; + } + + public static Class classOrNull(ClassLoader loader, String className) + { + try { + return loader.loadClass(className); + } catch (ClassNotFoundException ex) { + } catch (SecurityException ex) { + } catch (LinkageError ex) { + } catch (IllegalArgumentException e) { + // Can be thrown if name has characters that a class name + // can not contain + } + return null; + } + + static Object newInstanceOrNull(Class cl) + { + try { + return cl.newInstance(); + } catch (SecurityException x) { + } catch (LinkageError ex) { + } catch (InstantiationException x) { + } catch (IllegalAccessException x) { + } + return null; + } + + /** + * Check that testClass is accesible from the given loader. + */ + static boolean testIfCanLoadRhinoClasses(ClassLoader loader) + { + Class testClass = ScriptRuntime.ContextFactoryClass; + Class x = Kit.classOrNull(loader, testClass.getName()); + if (x != testClass) { + // The check covers the case when x == null => + // loader does not know about testClass or the case + // when x != null && x != testClass => + // loader loads a class unrelated to testClass + return false; + } + return true; + } + + /** + * If initCause methods exists in Throwable, call + * ex.initCause(cause) or otherwise do nothing. + * @return The ex argument. + */ + public static RuntimeException initCause(RuntimeException ex, + Throwable cause) + { + if (Throwable_initCause != null) { + Object[] args = { cause }; + try { + Throwable_initCause.invoke(ex, args); + } catch (Exception e) { + // Ignore any exceptions + } + } + return ex; + } + + /** + * Split string into array of strings using semicolon as string terminator + * (; after the last string is required). + */ + public static String[] semicolonSplit(String s) + { + String[] array = null; + for (;;) { + // loop 2 times: first to count semicolons and then to fill array + int count = 0; + int cursor = 0; + for (;;) { + int next = s.indexOf(';', cursor); + if (next < 0) { + break; + } + if (array != null) { + array[count] = s.substring(cursor, next); + } + ++count; + cursor = next + 1; + } + // after the last semicolon + if (array == null) { + // array size counting state: + // check for required terminating ';' + if (cursor != s.length()) + throw new IllegalArgumentException(); + array = new String[count]; + } else { + // array filling state: stop the loop + break; + } + } + return array; + } + + /** + * If character c is a hexadecimal digit, return + * accumulator * 16 plus corresponding + * number. Otherise return -1. + */ + public static int xDigitToInt(int c, int accumulator) + { + check: { + // Use 0..9 < A..Z < a..z + if (c <= '9') { + c -= '0'; + if (0 <= c) { break check; } + } else if (c <= 'F') { + if ('A' <= c) { + c -= ('A' - 10); + break check; + } + } else if (c <= 'f') { + if ('a' <= c) { + c -= ('a' - 10); + break check; + } + } + return -1; + } + return (accumulator << 4) | c; + } + + /** + * Add listener to bag of listeners. + * The function does not modify bag and return a new collection + * containing listener and all listeners from bag. + * Bag without listeners always represented as the null value. + *

+ * Usage example: + *

+     *     private volatile Object changeListeners;
+     *
+     *     public void addMyListener(PropertyChangeListener l)
+     *     {
+     *         synchronized (this) {
+     *             changeListeners = Kit.addListener(changeListeners, l);
+     *         }
+     *     }
+     *
+     *     public void removeTextListener(PropertyChangeListener l)
+     *     {
+     *         synchronized (this) {
+     *             changeListeners = Kit.removeListener(changeListeners, l);
+     *         }
+     *     }
+     *
+     *     public void fireChangeEvent(Object oldValue, Object newValue)
+     *     {
+     *     // Get immune local copy
+     *         Object listeners = changeListeners;
+     *         if (listeners != null) {
+     *             PropertyChangeEvent e = new PropertyChangeEvent(
+     *                 this, "someProperty" oldValue, newValue);
+     *             for (int i = 0; ; ++i) {
+     *                 Object l = Kit.getListener(listeners, i);
+     *                 if (l == null)
+     *                     break;
+     *                 ((PropertyChangeListener)l).propertyChange(e);
+     *             }
+     *         }
+     *     }
+     * 
+ * + * @param listener Listener to add to bag + * @param bag Current collection of listeners. + * @return A new bag containing all listeners from bag and + * listener. + * @see #removeListener(Object bag, Object listener) + * @see #getListener(Object bag, int index) + */ + public static Object addListener(Object bag, Object listener) + { + if (listener == null) throw new IllegalArgumentException(); + if (listener instanceof Object[]) throw new IllegalArgumentException(); + + if (bag == null) { + bag = listener; + } else if (!(bag instanceof Object[])) { + bag = new Object[] { bag, listener }; + } else { + Object[] array = (Object[])bag; + int L = array.length; + // bag has at least 2 elements if it is array + if (L < 2) throw new IllegalArgumentException(); + Object[] tmp = new Object[L + 1]; + System.arraycopy(array, 0, tmp, 0, L); + tmp[L] = listener; + bag = tmp; + } + + return bag; + } + + /** + * Remove listener from bag of listeners. + * The function does not modify bag and return a new collection + * containing all listeners from bag except listener. + * If bag does not contain listener, the function returns + * bag. + *

+ * For usage example, see {@link #addListener(Object bag, Object listener)}. + * + * @param listener Listener to remove from bag + * @param bag Current collection of listeners. + * @return A new bag containing all listeners from bag except + * listener. + * @see #addListener(Object bag, Object listener) + * @see #getListener(Object bag, int index) + */ + public static Object removeListener(Object bag, Object listener) + { + if (listener == null) throw new IllegalArgumentException(); + if (listener instanceof Object[]) throw new IllegalArgumentException(); + + if (bag == listener) { + bag = null; + } else if (bag instanceof Object[]) { + Object[] array = (Object[])bag; + int L = array.length; + // bag has at least 2 elements if it is array + if (L < 2) throw new IllegalArgumentException(); + if (L == 2) { + if (array[1] == listener) { + bag = array[0]; + } else if (array[0] == listener) { + bag = array[1]; + } + } else { + int i = L; + do { + --i; + if (array[i] == listener) { + Object[] tmp = new Object[L - 1]; + System.arraycopy(array, 0, tmp, 0, i); + System.arraycopy(array, i + 1, tmp, i, L - (i + 1)); + bag = tmp; + break; + } + } while (i != 0); + } + } + + return bag; + } + + /** + * Get listener at index position in bag or null if + * index equals to number of listeners in bag. + *

+ * For usage example, see {@link #addListener(Object bag, Object listener)}. + * + * @param bag Current collection of listeners. + * @param index Index of the listener to access. + * @return Listener at the given index or null. + * @see #addListener(Object bag, Object listener) + * @see #removeListener(Object bag, Object listener) + */ + public static Object getListener(Object bag, int index) + { + if (index == 0) { + if (bag == null) + return null; + if (!(bag instanceof Object[])) + return bag; + Object[] array = (Object[])bag; + // bag has at least 2 elements if it is array + if (array.length < 2) throw new IllegalArgumentException(); + return array[0]; + } else if (index == 1) { + if (!(bag instanceof Object[])) { + if (bag == null) throw new IllegalArgumentException(); + return null; + } + Object[] array = (Object[])bag; + // the array access will check for index on its own + return array[1]; + } else { + // bag has to array + Object[] array = (Object[])bag; + int L = array.length; + if (L < 2) throw new IllegalArgumentException(); + if (index == L) + return null; + return array[index]; + } + } + + static Object initHash(Hashtable h, Object key, Object initialValue) + { + synchronized (h) { + Object current = h.get(key); + if (current == null) { + h.put(key, initialValue); + } else { + initialValue = current; + } + } + return initialValue; + } + + private final static class ComplexKey + { + private Object key1; + private Object key2; + private int hash; + + ComplexKey(Object key1, Object key2) + { + this.key1 = key1; + this.key2 = key2; + } + + public boolean equals(Object anotherObj) + { + if (!(anotherObj instanceof ComplexKey)) + return false; + ComplexKey another = (ComplexKey)anotherObj; + return key1.equals(another.key1) && key2.equals(another.key2); + } + + public int hashCode() + { + if (hash == 0) { + hash = key1.hashCode() ^ key2.hashCode(); + } + return hash; + } + } + + public static Object makeHashKeyFromPair(Object key1, Object key2) + { + if (key1 == null) throw new IllegalArgumentException(); + if (key2 == null) throw new IllegalArgumentException(); + return new ComplexKey(key1, key2); + } + + public static String readReader(Reader r) + throws IOException + { + char[] buffer = new char[512]; + int cursor = 0; + for (;;) { + int n = r.read(buffer, cursor, buffer.length - cursor); + if (n < 0) { break; } + cursor += n; + if (cursor == buffer.length) { + char[] tmp = new char[buffer.length * 2]; + System.arraycopy(buffer, 0, tmp, 0, cursor); + buffer = tmp; + } + } + return new String(buffer, 0, cursor); + } + + public static byte[] readStream(InputStream is, int initialBufferCapacity) + throws IOException + { + if (initialBufferCapacity <= 0) { + throw new IllegalArgumentException( + "Bad initialBufferCapacity: "+initialBufferCapacity); + } + byte[] buffer = new byte[initialBufferCapacity]; + int cursor = 0; + for (;;) { + int n = is.read(buffer, cursor, buffer.length - cursor); + if (n < 0) { break; } + cursor += n; + if (cursor == buffer.length) { + byte[] tmp = new byte[buffer.length * 2]; + System.arraycopy(buffer, 0, tmp, 0, cursor); + buffer = tmp; + } + } + if (cursor != buffer.length) { + byte[] tmp = new byte[cursor]; + System.arraycopy(buffer, 0, tmp, 0, cursor); + buffer = tmp; + } + return buffer; + } + + /** + * Throws RuntimeException to indicate failed assertion. + * The function never returns and its return type is RuntimeException + * only to be able to write throw Kit.codeBug() if plain + * Kit.codeBug() triggers unreachable code error. + */ + public static RuntimeException codeBug() + throws RuntimeException + { + RuntimeException ex = new IllegalStateException("FAILED ASSERTION"); + // Print stack trace ASAP + ex.printStackTrace(System.err); + throw ex; + } +} + -- cgit v1.2.3