org.mozilla.javascript.Kit Maven / Gradle / Ivy
Show all versions of rhino-runtime Show documentation
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.javascript;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
/** Collection of utilities */
public class Kit {
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;
}
/** Attempt to load the class of the given name. Note that the type parameter isn't checked. */
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.getDeclaredConstructor().newInstance();
} catch (SecurityException
| LinkageError
| InstantiationException
| IllegalAccessException
| NoSuchMethodException
| InvocationTargetException x) {
}
return null;
}
/** Check that testClass is accessible 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 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(Map