diff --git a/JavaInJava/src/com/sun/max/AbstractScheme.java b/JavaInJava/src/com/sun/max/AbstractScheme.java new file mode 100644 index 0000000..c1f4052 --- /dev/null +++ b/JavaInJava/src/com/sun/max/AbstractScheme.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max; + +/** + * @author Bernd Mathiske + */ +public abstract class AbstractScheme { + + public final String name; + + protected AbstractScheme() { + name = getClass().getSimpleName(); + } + + public String name() { + return name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/JavaInJava/src/com/sun/max/BasePackage.java b/JavaInJava/src/com/sun/max/BasePackage.java new file mode 100644 index 0000000..8125552 --- /dev/null +++ b/JavaInJava/src/com/sun/max/BasePackage.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class BasePackage extends MaxPackage { + protected BasePackage() { + } +} diff --git a/JavaInJava/src/com/sun/max/MaxPackage.java b/JavaInJava/src/com/sun/max/MaxPackage.java new file mode 100755 index 0000000..0254cfb --- /dev/null +++ b/JavaInJava/src/com/sun/max/MaxPackage.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max; + +import java.lang.reflect.*; +import java.util.*; + +import com.sun.max.lang.*; +import com.sun.max.program.*; + +/** + * Describes a package in the com.sun.max project, + * providing programmatic package information manipulation, + * which is lacking in java.lang.Package. + *

+ * You must create a class called 'Package extends MaxPackage' + * in each and every package in this project. + *

+ * For example you can call: + * + * new com.sun.max.program.Package().superPackage() + * + * Also make sure that you have a file called 'package-info.java' in every package. + * This is where you can put package-related JavaDoc comments. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public abstract class MaxPackage implements Comparable { + + private final String packageName; + private static final Class[] NO_CLASSES = new Class[0]; + + protected MaxPackage() { + packageName = toJava().getName(); + assert getClass().getSimpleName().equals(Package.class.getSimpleName()); + } + + /** + * Gets an instance of the class named "Package" in a named package. + * + * @param packageName denotes the name of a package which may contain a subclass of {@link MaxPackage} named + * "Package" + * @return an instance of the class name "Package" in {@code packageName}. If such a class does not exist or there + * was an error {@linkplain Class#newInstance() instantiating} it, then {@code null} is returned + */ + public static MaxPackage fromName(String packageName) { + final String name = packageName + "." + Package.class.getSimpleName(); + if (name.equals(java.lang.Package.class.getName())) { + // Special case! + return null; + } + try { + final Class packageClass = Class.forName(name); + return (MaxPackage) packageClass.newInstance(); + } catch (ClassNotFoundException e) { + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } + return null; + } + + private MaxPackage(String packageName) { + this.packageName = packageName; + } + + public static MaxPackage fromJava(String name) { + return new MaxPackage(name) { + @Override + public java.lang.Package toJava() { + return java.lang.Package.getPackage(name()); + } + }; + } + + public static MaxPackage fromClass(Class javaClass) { + final java.lang.Package javaPackage = javaClass.getPackage(); + if (javaPackage == null) { + return null; + } + return fromName(javaPackage.getName()); + } + + public java.lang.Package toJava() { + return getClass().getPackage(); + } + + public String name() { + return packageName; + } + + public String lastIdentifier() { + return packageName.substring(packageName.lastIndexOf('.') + 1); + } + + public MaxPackage superPackage() { + final int end = name().lastIndexOf('.'); + if (end < 0) { + return null; + } + return fromName(name().substring(0, end)); + } + + /** + * Gets the subclasses of {@code com.sun.max.unsafe.Word} in this package. + * The returned array must not include boxed (see com.sun.max.unsafe.Boxed) + * word types as they are derived from the name of the unboxed types. + */ + public Class[] wordSubclasses() { + return NO_CLASSES; + } + + public MaxPackage subPackage(String... suffices) { + String name = name(); + for (String suffix : suffices) { + name += "." + suffix; + } + final MaxPackage subPackage = fromName(name); + ProgramError.check(subPackage != null, "Could not find sub-package of " + this + " named " + name); + return subPackage; + } + + public boolean isSubPackageOf(MaxPackage superPackage) { + return name().startsWith(superPackage.name()); + } + + public List getTransitiveSubPackages(Classpath classpath) { + final Set packageNames = new TreeSet(); + new ClassSearch() { + @Override + protected boolean visitClass(String className) { + final String pkgName = Classes.getPackageName(className); + if (pkgName.startsWith(name())) { + packageNames.add(pkgName); + } + return true; + } + }.run(classpath, name().replace('.', '/')); + + final List packages = new ArrayList(packageNames.size()); + for (String pkgName : packageNames) { + final MaxPackage maxPackage = MaxPackage.fromName(pkgName); + if (maxPackage == null) { + System.err.println("WARNING: missing Package class in package: " + pkgName); + } else { + packages.add(maxPackage); + } + } + return packages; + } + + private Map, Class> schemeTypeToImplementation; + + /** + * Registers a class in this package that implements a given scheme type. + * + * @param schemeType a scheme type + * @param schemeImplementation a class that implements {@code schemType} + */ + public synchronized void registerScheme(Class schemeType, Class schemeImplementation) { + assert schemeType.isInterface() || Modifier.isAbstract(schemeType.getModifiers()); + assert schemeImplementation.getPackage().getName().equals(name()) : "cannot register implmentation class from another package: " + schemeImplementation; + if (schemeTypeToImplementation == null) { + schemeTypeToImplementation = new IdentityHashMap, Class>(); + } + Class oldValue = schemeTypeToImplementation.put(schemeType, schemeImplementation); + assert oldValue == null; + } + + /** + * Gets the class within this package implementing a given scheme type (represented as an abstract class or interface). + * + * @return the class directly within this package that implements {@code scheme} or null if no such class + * exists + */ + public synchronized Class schemeTypeToImplementation(Class schemeType) { + if (schemeTypeToImplementation == null) { + return null; + } + final Class< ? extends Scheme> implementation = schemeTypeToImplementation.get(schemeType); + if (implementation == null) { + return null; + } + return implementation.asSubclass(schemeType); + } + + public static boolean equal(MaxPackage p1, MaxPackage p2) { + if (p1 == null) { + return p2 == null; + } + return p1.equals(p2); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (other instanceof MaxPackage) { + return packageName.equals(((MaxPackage) other).packageName); + } + return false; + } + + @Override + public int hashCode() { + return name().hashCode(); + } + + public Set prerequisites() { + return Collections.emptySet(); + } + + /** + * Gets the set of packages excluded by this package. Excluded packages will not be loaded into a system that is + * configured by package loading (such as the Maxine VM) if the package represented by this object is loaded. Such a + * system should ensure that configuration fails if any excluded packages encountered on the class path before the + * package that excludes them. + */ + public Set excludes() { + return Collections.emptySet(); + } + + public int compareTo(MaxPackage other) { + final Set myPrerequisites = prerequisites(); + final Set otherPrerequisites = other.prerequisites(); + if (myPrerequisites.isEmpty()) { + if (otherPrerequisites.isEmpty()) { + return packageName.compareTo(other.packageName); + } + return -1; + } + for (MaxPackage myPrerequisite : myPrerequisites) { + if (other.equals(myPrerequisite)) { + return 1; + } + } + if (otherPrerequisites.isEmpty()) { + return 1; + } + for (MaxPackage otherPrerequisite : otherPrerequisites) { + if (equals(otherPrerequisite)) { + return -1; + } + } + return packageName.compareTo(other.packageName); + } + + public synchronized Class loadSchemeImplementation(Class schemeType) { + final Class schemeImplementation = schemeTypeToImplementation(schemeType); + if (schemeImplementation == null) { + ProgramError.unexpected("could not find subclass of " + schemeType + " in " + this); + } else { + final Class loadedImplementation = Classes.load(schemeType.getClassLoader(), schemeImplementation.getName()); + return loadedImplementation.asSubclass(schemeType); + } + return null; + } + + /** + * Instantiates the scheme implementation class in this package implementing a given scheme type. + * + * @param schemeType the interface or abstract class defining a scheme type + * @return a new instance of the scheme implementation class + */ + public synchronized S loadAndInstantiateScheme(Class schemeType) { + final Class schemeImplementation = loadSchemeImplementation(schemeType); + try { + return schemeImplementation.newInstance(); + } catch (Throwable throwable) { + throw ProgramError.unexpected("could not instantiate class: " + schemeImplementation.getName(), throwable); + } + } + + @Override + public String toString() { + return name(); + } +} diff --git a/JavaInJava/src/com/sun/max/Package.java b/JavaInJava/src/com/sun/max/Package.java new file mode 100755 index 0000000..63cbee2 --- /dev/null +++ b/JavaInJava/src/com/sun/max/Package.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { +} diff --git a/JavaInJava/src/com/sun/max/PackageLoader.java b/JavaInJava/src/com/sun/max/PackageLoader.java new file mode 100755 index 0000000..f79fd2e --- /dev/null +++ b/JavaInJava/src/com/sun/max/PackageLoader.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max; + +import java.util.*; + +import com.sun.max.lang.*; +import com.sun.max.program.*; + +/** + * Loads all the classes in or under a given package. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public class PackageLoader { + + public final Classpath classpath; + public final ClassLoader classLoader; + private int traceLevel = 1; + + public PackageLoader(ClassLoader classLoader, Classpath classpath) { + this.classpath = classpath; + this.classLoader = classLoader; + } + + public void setTraceLevel(int level) { + traceLevel = level; + } + + /** + * Loads a given class. + * A subclass can override this method to omit loading of certain classes in a package + * which can result in this method returning {@code null}. + * + * @param className + * @return the {@code Class} instance for {@code className} + */ + protected Class loadClass(String className) { + return Classes.load(classLoader, className); + } + + /** + * Loads classes under a given package. + * + * @param packageName the name of the package from which classes are loaded + * @param recursive if true, then classes in sub-packages are loaded as well, otherwise only classes in the package + * denoted by {@code packageName} are loaded + * @return the loaded classes + */ + public List load(final String packageName, final boolean recursive) { + Trace.line(traceLevel, "loading: " + packageName); + final List classes = new ArrayList(); + String[] classNames = listClassesInPackage(packageName, recursive); + for (String className : classNames) { + final Class javaClass = loadClass(className); + if (javaClass != null) { + Classes.initialize(javaClass); + classes.add(javaClass); + } + } + ProgramWarning.check(classNames.length != 0, "no classes found in package: " + packageName); + return classes; + } + + /** + * Lists the classes under a given package. + * + * @param packageName the name of the package to search + * @param recursive if true, then classes in sub-packages are listed as well + * @return the class names + */ + public String[] listClassesInPackage(final String packageName, final boolean recursive) { + final HashSet classNames = new HashSet(); + final ClassSearch classSearch = new ClassSearch() { + @Override + protected boolean visitClass(boolean isArchiveEntry, String className) { + if (!className.endsWith("package-info")) { + if (!classNames.contains(className)) { + if (recursive || Classes.getPackageName(className).equals(packageName)) { + classNames.add(className); + } + } + } + return true; + } + }; + classSearch.run(classpath, packageName.replace('.', '/')); + return classNames.toArray(new String[classNames.size()]); + } + + /** + * Loads classes under a given package. + * + * @param maxPackage the package from which classes are loaded + * @param recursive if true, then classes in sub-packages are loaded as well, otherwise only classes in + * {@code maxPackage} are loaded + * @return the loaded classes + */ + public List load(MaxPackage maxPackage, boolean recursive) { + return load(maxPackage.name(), recursive); + } + + /** + * Initializes the given class and all its inner classes, recursively. + */ + private void initializeAll(Class outerClass) { + Classes.initialize(outerClass); + for (Class innerClass : outerClass.getDeclaredClasses()) { + initializeAll(innerClass); + } + } + + public void loadAndInitializeAll(Class representative) { + try { + for (Class outerClass : load(MaxPackage.fromClass(representative), false)) { + initializeAll(outerClass); + } + } catch (Throwable throwable) { + ProgramError.unexpected(throwable); + } + } +} diff --git a/JavaInJava/src/com/sun/max/Scheme.java b/JavaInJava/src/com/sun/max/Scheme.java new file mode 100644 index 0000000..d17701c --- /dev/null +++ b/JavaInJava/src/com/sun/max/Scheme.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max; + +/** + * @author Bernd Mathiske + */ +public interface Scheme { + + String name(); + +} diff --git a/JavaInJava/src/com/sun/max/Utils.java b/JavaInJava/src/com/sun/max/Utils.java new file mode 100644 index 0000000..c843f9b --- /dev/null +++ b/JavaInJava/src/com/sun/max/Utils.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max; + +import java.io.*; +import java.util.*; + +import com.sun.max.program.*; + +/** + * Miscellaneous utility methods. + * + * @author Doug Simon + */ +public final class Utils { + + private Utils() { + } + + /** + * Gets the first element in a list. + */ + public static T first(List list) { + if (list instanceof Queue) { + Queue queue = (Queue) list; + Class type = null; + T t = cast(type, queue.peek()); + return t; + } + return list.get(0); + } + + /** + * Gets the last element in a list. + */ + public static T last(List list) { + if (list instanceof Deque) { + Deque deque = (Deque) list; + Class type = null; + T t = cast(type, deque.getLast()); + return t; + } + return list.get(list.size() - 1); + } + + /** + * Creates an array of a generic type. + * + * @param the type of the array elements + * @param length the length of the array to create + * @return a generic array of type {@code } with a length of {@code length} + */ + public static T[] newArray(int length) { + return cast(new Object[length]); + } + + /** + * Creates an array of a generic type. + * + * @param the type of the array elements + * @param type explicit class of {@code } needed due to javac bug (see {@link #cast(Class, Object)}) + * @param length the length of the array to create + * @return a generic array of type {@code } with a length of {@code length} + */ + public static T[] newArray(Class type, int length) { + return cast(type, new Object[length]); + } + + /** + * Creates an array of a generic type and {@linkplain Arrays#asList(Object...) wraps} it with + * a fixed-size list. + * + * @param the type of the array elements + * @param length the length of the array to create + * @return a fixed-size list backed by a new generic array of type {@code } with a length of {@code length} + */ + public static List newArrayAsList(int length) { + Class type = null; + T[] array = newArray(type, length); + return Arrays.asList(array); + } + + /** + * Returns the index in {@code list} of the first occurrence identical to {@code value}, or -1 if + * {@code list} does not contain {@code value}. More formally, returns the lowest index + * {@code i} such that {@code (list.get(i) == value)}, or -1 if there is no such index. + */ + public static int indexOfIdentical(List list, Object value) { + int i = 0; + for (Object element : list) { + if (element == value) { + return i; + } + ++i; + } + return -1; + } + + /** + * Returns the index in {@code array} of the first occurrence identical to {@code value}, or -1 if + * {@code array} does not contain {@code value}. More formally, returns the lowest index + * {@code i} such that {@code (array[i] == value)}, or -1 if there is no such index. + */ + public static int indexOfIdentical(Object[] array, Object value) { + for (int i = 0; i < array.length; i++) { + if (array[i] == value) { + return i; + } + } + return -1; + } + + /** + * Statically cast an object to an arbitrary type. The cast is still dynamically checked. + * + * This alternate version of {@link #cast(Object)} is required due to bug + * 6302954 in javac. + * + * The pattern for calling this method is: + *

+     *     Foo foo = ...;
+     *     Class> type = null;
+     *     Foo genericFoo = uncheckedCast(type, foo);
+     * 
+ * + */ + @SuppressWarnings("unchecked") + public static T cast(Class type, Object object) { + return (T) object; + } + + /** + * Statically cast an object to an arbitrary type. The cast is still dynamically checked. + */ + @SuppressWarnings("unchecked") + public static T cast(Object object) { + return (T) object; + } + + /** + * Concatenates two arrays. + * + * @param the type of elements in the source arrays + * @param head the prefix of the result array + * @param tail the elements to be concatenated to {@code head} + * @return the result of concatenating {@code tail} to the end of {@code head} + */ + public static T[] concat(T[] head, T... tail) { + T[] result = Arrays.copyOf(head, head.length + tail.length); + System.arraycopy(tail, 0, result, head.length, tail.length); + return result; + } + + /** + * Concatenates two arrays. + * + * @param the type of elements in the source arrays + * @param tail the elements to be concatenated to the end of {@code head} + * @param head the prefix of the result array + * @return the result of concatenating {@code tail} to the end of {@code head} + */ + public static T[] prepend(T[] tail, T... head) { + return concat(head, tail); + } + + /** + * Returns a string representation of the contents of the specified array. + * If the array contains other arrays as elements, they are converted to + * strings by the {@link Object#toString} method inherited from + * Object, which describes their identities rather than + * their contents. + * + * @param array the array whose string representation to return + * @param separator the separator to use + * @return a string representation of array + * @throws NullPointerException if {@code array} or {@code separator} is null + */ + public static String toString(T[] array, String separator) { + if (array == null || separator == null) { + throw new NullPointerException(); + } + if (array.length == 0) { + return ""; + } + + final StringBuilder builder = new StringBuilder(); + builder.append(array[0]); + + for (int i = 1; i < array.length; i++) { + builder.append(separator); + builder.append(array[i]); + } + + return builder.toString(); + } + + /** + * Tests a given exception to see if it is an instance of a given exception type, casting and throwing it if so. + * Otherwise if the exception is an unchecked exception (i.e. an instance of a {@link RuntimeException} or + * {@link Error}) then it is cast to the appropriate unchecked exception type and thrown. Otherwise, it is wrapped + * in a {@link ProgramError} and thrown. + * + * This method declares a return type simply so that a call to this method can be the expression to a throw + * instruction. + */ + public static T cast(Class exceptionType, Throwable exception) throws T { + if (exceptionType.isInstance(exception)) { + throw exceptionType.cast(exception); + } + if (exception instanceof Error) { + throw (Error) exception; + } + if (exception instanceof RuntimeException) { + throw (RuntimeException) exception; + } + throw ProgramError.unexpected(exception); + } + + /** + * Gets the stack trace for a given exception as a string. + */ + public static String stackTraceAsString(Throwable throwable) { + final StringWriter stringWriter = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.getBuffer().toString(); + } +} diff --git a/JavaInJava/src/com/sun/max/annotate/INLINE.java b/JavaInJava/src/com/sun/max/annotate/INLINE.java new file mode 100644 index 0000000..4facc57 --- /dev/null +++ b/JavaInJava/src/com/sun/max/annotate/INLINE.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.annotate; +import java.lang.annotation.*; + +/** + * Every thus annotated method is to be inlined unconditionally by the VM's optimizing compiler + * and the receiver is never null-checked. + * + * This annotation exists primarily for annotating methods that must be inlined + * for semantic reasons as opposed to those that could be inlined for performance reasons. + * Using this annotation for the latter should be done very rarely and only when + * profiling highlights a performance bottleneck or such a bottleneck is known a priori. + * + * If the {@linkplain #override() override} element of this annotation is set to true, then + * an annotated method must be {@code static} or {@code final} (implicitly or explicitly). + * Additionally, only a INLINE virtual method with this element set to true can be overridden. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface INLINE { + + /** + * If true, this element specifies that the annotated method provides the prototypical implementation + * of the functionality expected (in the target VM) of every method that overrides + * the annotated method. That is, the code produced by the compiler for every overriding method + * must be functionality equivalent to the code produced for the prototypical method. + * + * WARNING: Setting this element to true implies that you guarantee that all overriders + * satisfy the above stated invariant. There is no (easy) way to test for violations of + * the invariant. + * + * A method annotated with INLINE should only be overridden for one of the following reasons: + * + * 1. To coerce the value returned by the overridden method to a subtype. + * See {@link MemberActor#holder()} and {@link FieldActor#holder()} for an example. + * + * 2. A method is overridden to make bootstrapping work. + * See {@link ClassActor#toJava()} and {@link ArrayClassActor#toJava()} for an example. + * + * 3. A method is overridden because a subclass can provide a more efficient implementation + * and it is known that certain call sites will be reduced to a constant receiver + * (not just a known receiver type but a known receiver object) via annotation driven + * compile-time {@linkplain FOLD folding}. This is how calls to the {@link GeneralLayout layout} + * interface methods are reduced to monomorphic calls at compile-time. + * + * See {@link ClassActor#toJava()} and {@link ArrayClassActor#toJava()} for an example. + */ + boolean override() default false; + + /** + * If true, this element specifies that inlining of the thus annotated method is only allowed + * after snippet compilation has concluded. + * + * @see CompilerScheme#areSnippetsCompiled() + */ + boolean afterSnippetsAreCompiled() default false; +} diff --git a/JavaInJava/src/com/sun/max/annotate/INSPECTED.java b/JavaInJava/src/com/sun/max/annotate/INSPECTED.java new file mode 100644 index 0000000..5a37bd6 --- /dev/null +++ b/JavaInJava/src/com/sun/max/annotate/INSPECTED.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.annotate; + +import java.lang.annotation.*; + +/** + * Marks a field, method or constructor that is reflected upon by the Inspector. + * + * The Inspector uses this annotation to auto-generate objects for accessing the + * annotated entity in the remote VM process. See the {@code TeleFields} + * and {@code TeleMethods} classes in the Tele project. + * + * @author Doug Simon + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD }) +public @interface INSPECTED { + +} diff --git a/JavaInJava/src/com/sun/max/annotate/Package.java b/JavaInJava/src/com/sun/max/annotate/Package.java new file mode 100755 index 0000000..e8e1252 --- /dev/null +++ b/JavaInJava/src/com/sun/max/annotate/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.annotate; + +import com.sun.max.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/annotate/RESET.java b/JavaInJava/src/com/sun/max/annotate/RESET.java new file mode 100644 index 0000000..761bea2 --- /dev/null +++ b/JavaInJava/src/com/sun/max/annotate/RESET.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.annotate; + +import java.lang.annotation.*; + +/** + * Denotes a field whose value is reset to the default value for its type when it is copied into the Maxine boot image. + * + * @author Doug Simon + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface RESET { +} diff --git a/JavaInJava/src/com/sun/max/annotate/package-info.java b/JavaInJava/src/com/sun/max/annotate/package-info.java new file mode 100644 index 0000000..6ac3db3 --- /dev/null +++ b/JavaInJava/src/com/sun/max/annotate/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * Annotations used throughout the Maxine project. + * + * @author Bernd Mathiske + */ +package com.sun.max.annotate; diff --git a/JavaInJava/src/com/sun/max/gui/Package.java b/JavaInJava/src/com/sun/max/gui/Package.java new file mode 100755 index 0000000..09ba7ef --- /dev/null +++ b/JavaInJava/src/com/sun/max/gui/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.gui; + +import com.sun.max.*; + +/** + * This package is not included in the bootstrap as it would drag in most of Swing. + * + * @author Doug Simon + */ +public class Package extends MaxPackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/gui/SpringUtilities.java b/JavaInJava/src/com/sun/max/gui/SpringUtilities.java new file mode 100644 index 0000000..cffa05d --- /dev/null +++ b/JavaInJava/src/com/sun/max/gui/SpringUtilities.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.gui; + +import java.awt.*; + +import javax.swing.*; +/** + * Partially copied from the "Swing Tutorial". + * Minor changes to comply with our CheckStyle settings. + * + * A 1.4 file that provides utility methods for + * creating form- or grid-style layouts with SpringLayout. + * These utilities are used by several programs, such as + * SpringBox and SpringCompactGrid. + * + * @author original SpringUtilities author + * @author Bernd Mathiske + */ +public final class SpringUtilities { + private SpringUtilities() { + } + + /** + * A debugging utility that prints to stdout the component's + * minimum, preferred, and maximum sizes. + */ + public static void printSizes(Component c) { + System.out.println("minimumSize = " + c.getMinimumSize()); + System.out.println("preferredSize = " + c.getPreferredSize()); + System.out.println("maximumSize = " + c.getMaximumSize()); + } + + /** + * Aligns the first {@code rows} * {@code cols} + * components of {@code parent} in + * a grid. Each component is as big as the maximum + * preferred width and height of the components. + * The parent is made just big enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeGrid(Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout) parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeGrid must use SpringLayout."); + return; + } + + final Spring xPadSpring = Spring.constant(xPad); + final Spring yPadSpring = Spring.constant(yPad); + final Spring initialXSpring = Spring.constant(initialX); + final Spring initialYSpring = Spring.constant(initialY); + final int max = rows * cols; + + //Calculate Springs that are the max of the width/height so that all + //cells have the same size. + Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)). + getWidth(); + Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)). + getWidth(); + for (int i = 1; i < max; i++) { + final SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + + maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); + maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); + } + + //Apply the new width/height Spring. This forces all the + //components to have the same size. + for (int i = 0; i < max; i++) { + final SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + + cons.setWidth(maxWidthSpring); + cons.setHeight(maxHeightSpring); + } + + //Then adjust the x/y constraints of all the cells so that they + //are aligned in a grid. + SpringLayout.Constraints lastCons = null; + SpringLayout.Constraints lastRowCons = null; + for (int i = 0; i < max; i++) { + final SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + if (i % cols == 0) { //start of new row + lastRowCons = lastCons; + cons.setX(initialXSpring); + } else if (lastCons != null) { //x position depends on previous component + cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), + xPadSpring)); + } + + if (i / cols == 0) { //first row + cons.setY(initialYSpring); + } else if (lastRowCons != null) { //y position depends on previous row + cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), + yPadSpring)); + } + lastCons = cons; + } + + //Set the parent's size. + final SpringLayout.Constraints pCons = layout.getConstraints(parent); + if (lastCons != null) { + pCons.setConstraint(SpringLayout.SOUTH, Spring.sum(Spring.constant(yPad), lastCons.getConstraint(SpringLayout.SOUTH))); + pCons.setConstraint(SpringLayout.EAST, Spring.sum(Spring.constant(xPad), lastCons.getConstraint(SpringLayout.EAST))); + } + } + + public static void makeGrid(Container parent, int numberOfColumns) { + makeGrid(parent, parent.getComponentCount() / numberOfColumns, numberOfColumns, 0, 0, 5, 5); + } + + /* Used by makeCompactGrid. */ + private static SpringLayout.Constraints getConstraintsForCell( + int row, int col, + Container parent, + int cols) { + final SpringLayout layout = (SpringLayout) parent.getLayout(); + final Component c = parent.getComponent(row * cols + col); + return layout.getConstraints(c); + } + + /** + * Aligns the first {@code rows} * {@code cols} + * components of {@code parent} in + * a grid. Each component in a column is as wide as the maximum + * preferred width of the components in that column; + * height is similarly determined for each row. + * The parent is made just big enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeCompactGrid(Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout) parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeCompactGrid must use SpringLayout."); + return; + } + + //Align all cells in each column and make them the same width. + Spring x = Spring.constant(initialX); + for (int c = 0; c < cols; c++) { + Spring width = Spring.constant(0); + for (int r = 0; r < rows; r++) { + width = Spring.max(width, + getConstraintsForCell(r, c, parent, cols). + getWidth()); + } + for (int r = 0; r < rows; r++) { + final SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); + constraints.setX(x); + constraints.setWidth(width); + } + x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); + } + + //Align all cells in each row and make them the same height. + Spring y = Spring.constant(initialY); + for (int r = 0; r < rows; r++) { + Spring height = Spring.constant(0); + for (int c = 0; c < cols; c++) { + height = Spring.max(height, + getConstraintsForCell(r, c, parent, cols). + getHeight()); + } + for (int c = 0; c < cols; c++) { + final SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); + constraints.setY(y); + constraints.setHeight(height); + } + y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); + } + + //Set the parent's size. + final SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, y); + pCons.setConstraint(SpringLayout.EAST, x); + } + + public static void makeCompactGrid(Container parent, int numberOfColumns) { + makeCompactGrid(parent, parent.getComponentCount() / numberOfColumns, numberOfColumns, 0, 0, 3, 3); + } + +} diff --git a/JavaInJava/src/com/sun/max/gui/ThrowableDialog.java b/JavaInJava/src/com/sun/max/gui/ThrowableDialog.java new file mode 100644 index 0000000..78ea1c7 --- /dev/null +++ b/JavaInJava/src/com/sun/max/gui/ThrowableDialog.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.gui; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; + +import javax.swing.*; +import javax.swing.border.*; + +/** + * A dialog for displaying the details of an exception. Initially the dialog only shows the exception's + * {@linkplain Throwable#getMessage() message}. It includes a button for expanding the dialog to also show the stack + * trace. When the stack trace is shown, pressing the same button hides the stack trace. + * + * @author Doug Simon + * @author Aritra Bandyopadhyay + */ +public final class ThrowableDialog extends JDialog { + + /** + * Creates a dialog to display the details of an exception and makes it visible. + * + * @param throwable the exception whose details are being displayed + * @param owner the {@code Frame} from which the dialog is displayed + * @param title the {@code String} to display in the dialog's title bar + */ + public static void show(Throwable throwable, Frame owner, String title) { + new ThrowableDialog(throwable, owner, title).setVisible(true); + } + + /** + * Creates a dialog to display the details of an exception and makes it visible on the + * {@linkplain SwingUtilities#invokeLater(Runnable) AWT dispatching thread}. + * + * @param throwable the exception whose details are being displayed + * @param owner the {@code Frame} from which the dialog is displayed + * @param title the {@code String} to display in the dialog's title bar + */ + public static void showLater(Throwable throwable, Frame owner, String title) { + final ThrowableDialog dialog = new ThrowableDialog(throwable, owner, title); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + dialog.setVisible(true); + } + }); + } + + /** + * Creates a dialog to display the details of an exception. The dialog is not displayed by this method. + * + * @param throwable the exception whose details are being displayed + * @param owner the {@code Frame} from which the dialog is displayed + * @param title the {@code String} to display in the dialog's title bar + */ + private ThrowableDialog(Throwable throwable, Frame owner, String title) { + super(owner, title, true); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setAlwaysOnTop(true); + + final JToggleButton stackTraceButton = new JToggleButton("Show stack trace"); + final JButton closeButton = new JButton("Close"); + closeButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setVisible(false); + dispose(); + } + }); + + final JPanel buttonsPanel = new JPanel(); + buttonsPanel.add(closeButton); + buttonsPanel.add(stackTraceButton); + + final Container mainPane = getContentPane(); + //mainPane.setLayout(new FlowLayout()); + mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.PAGE_AXIS)); + final JLabel message = new JLabel(throwable.getMessage()); + final JPanel messagePanel = new JPanel(); + messagePanel.add(message); + mainPane.add(messagePanel); + mainPane.add(buttonsPanel); + pack(); + + final Dimension dialogWithoutStackTracePreferredSize = getPreferredSize(); + + final JTextArea stackTraceText = new JTextArea(20, 40); + throwable.printStackTrace(new PrintWriter(new Writer() { + + @Override + public void close() throws IOException { + } + + @Override + public void flush() throws IOException { + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + stackTraceText.append(new String(cbuf, off, len)); + } + })); + + final JScrollPane stackTracePanel = new JScrollPane(stackTraceText, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + final Dimension stackTraceTextPreferredSize = stackTraceText.getPreferredSize(); + stackTracePanel.setBorder(new TitledBorder("Stack trace")); + final Dimension stackTracePanelPreferredSize = new Dimension( + stackTraceTextPreferredSize.width + stackTracePanel.getVerticalScrollBar().getPreferredSize().width * 2, + stackTraceTextPreferredSize.height + stackTracePanel.getHorizontalScrollBar().getPreferredSize().height); + stackTracePanel.setPreferredSize(stackTracePanelPreferredSize); + stackTracePanel.setVisible(false); + + stackTraceButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (stackTraceButton.isSelected()) { + stackTraceButton.setText("Hide stack trace"); + stackTracePanel.setVisible(true); + setSize(new Dimension(Math.max(dialogWithoutStackTracePreferredSize.width, stackTracePanelPreferredSize.width), + dialogWithoutStackTracePreferredSize.height + Math.min(1000, stackTracePanelPreferredSize.height))); + } else { + stackTraceButton.setText("Show stack trace"); + stackTracePanel.setVisible(false); + setSize(dialogWithoutStackTracePreferredSize); + } + validate(); + } + }); + mainPane.add(stackTracePanel); + + setSize(dialogWithoutStackTracePreferredSize); + pack(); + setLocationRelativeTo(owner); + } + + // Test code + + public static void main(String[] args) { + try { + recurse(0); + } catch (RuntimeException runtimeException) { + new ThrowableDialog(runtimeException, null, "Runtime Exception"); + } + } + + static void recurse(int more) { + if (more > 345) { + throw new RuntimeException("This is a test. Repeat. This is a test."); + } + recurse(more + 1); + } +} diff --git a/JavaInJava/src/com/sun/max/gui/package-info.java b/JavaInJava/src/com/sun/max/gui/package-info.java new file mode 100644 index 0000000..d7545f6 --- /dev/null +++ b/JavaInJava/src/com/sun/max/gui/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * GUI utilities. + * + * @author Bernd Mathiske + */ +package com.sun.max.gui; diff --git a/JavaInJava/src/com/sun/max/io/CharArraySource.java b/JavaInJava/src/com/sun/max/io/CharArraySource.java new file mode 100644 index 0000000..0edca3d --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/CharArraySource.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +/** + * + * + * @author Doug Simon + */ +public class CharArraySource extends CharArrayWriter implements ReadableSource { + + public CharArraySource() { + } + + public CharArraySource(int initialSize) { + super(initialSize); + } + + public Reader reader(boolean buffered) { + final Reader reader = new CharArrayReader(buf, 0, count); + return buffered ? new BufferedReader(reader) : reader; + } +} diff --git a/JavaInJava/src/com/sun/max/io/FileTraversal.java b/JavaInJava/src/com/sun/max/io/FileTraversal.java new file mode 100644 index 0000000..97834cf --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/FileTraversal.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +/** + * Provides a facility for walking a file system hierarchy similar to that provided by the Unix find(1) facility. + * + * @author Doug Simon + */ +public class FileTraversal { + + private boolean stopped; + + /** + * Handles a standard file resource encountered during the traversal. + * + * @param file a file resource for which {@link File#isFile()} returns {@code true} + */ + protected void visitFile(File file) { + } + + /** + * Handles a directory encountered during the traversal. + * + * @param directory a file resource for which {@link File#isDirectory()} returns {@code true} + * @return true if the traversal should process the file system hierarchy rooted at {@code directory}, false if it + * should be skipped + */ + protected boolean visitDirectory(File directory) { + return true; + } + + /** + * Handles a file resource encountered during the traversal that is neither a standard file or directory. + * + * @param other a file resource for which neither {@link File#isFile()} nor {@link File#isDirectory()} returns + * {@code true} + */ + protected void visitOther(File other) { + } + + /** + * Stops the traversal after the current file resource has been processed. This can be called from within an + * overriding implementation of {@link #visitFile(File)}, {@link #visitDirectory(File)} or + * {@link #visitOther(File)} to prematurely terminate a traversal. + */ + protected final void stop() { + stopped = true; + } + + /** + * Traverses the file hierarchy rooted at a given file. The {@linkplain #wasStopped() stopped} status of this + * traversal object is reset to {@code false} before the traversal begins. + * + * @param file the file or directory at which to start the traversal + */ + public void run(File file) { + stopped = false; + visit(file); + } + + /** + * Determines if the traversal was stopped before every file in the file hierarchy was traversed. + */ + public boolean wasStopped() { + return stopped; + } + + private boolean visit(File entry) { + File subdirectoryToTraverse = null; + if (entry.isFile()) { + visitFile(entry); + } else if (entry.isDirectory()) { + if (visitDirectory(entry)) { + subdirectoryToTraverse = entry; + } + } else { + visitOther(entry); + } + if (stopped) { + return false; + } + if (subdirectoryToTraverse != null) { + traverse(subdirectoryToTraverse); + if (stopped) { + return false; + } + } + return true; + } + + private void traverse(File directory) { + final File[] entries = directory.listFiles(); + if (entries != null) { + for (File entry : entries) { + if (!visit(entry)) { + return; + } + } + } + } +} diff --git a/JavaInJava/src/com/sun/max/io/Files.java b/JavaInJava/src/com/sun/max/io/Files.java new file mode 100644 index 0000000..d9f8588 --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/Files.java @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + +import com.sun.max.program.*; +import com.sun.max.util.*; + +/** + * @author Doug Simon + */ +public final class Files { + + private Files() { + } + + public static void copy(File from, File to) throws FileNotFoundException, IOException { + InputStream inputStream = null; + OutputStream outputStream = null; + try { + inputStream = new FileInputStream(from); + outputStream = new FileOutputStream(to); + Streams.copy(inputStream, outputStream); + } finally { + if (inputStream != null) { + inputStream.close(); + } + if (outputStream != null) { + outputStream.close(); + } + } + } + + public static boolean equals(File file1, File file2) throws FileNotFoundException, IOException { + final long length1 = file1.length(); + final long length2 = file2.length(); + if (length1 != length2) { + return false; + } + if (length1 <= 0) { + return true; + } + InputStream inputStream1 = null; + InputStream inputStream2 = null; + try { + inputStream1 = new BufferedInputStream(new FileInputStream(file1), (int) length1); + inputStream2 = new BufferedInputStream(new FileInputStream(file2), (int) length2); + return Streams.equals(inputStream1, inputStream2); + } finally { + if (inputStream1 != null) { + inputStream1.close(); + } + if (inputStream2 != null) { + inputStream2.close(); + } + } + } + + public static boolean equals(File file, Iterator lines) throws FileNotFoundException, IOException { + final BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); + try { + String line; + while ((line = bufferedReader.readLine()) != null) { + if (!lines.hasNext()) { + return false; + } + if (!line.equals(lines.next())) { + return false; + } + } + } finally { + bufferedReader.close(); + } + return !lines.hasNext(); + } + + public static byte[] toBytes(File file) throws IOException { + if (file.length() > Integer.MAX_VALUE) { + throw new IOException("file is too big to read into an array: " + file); + } + final InputStream stream = new BufferedInputStream(new FileInputStream(file), (int) file.length()); + try { + return Streams.readFully(stream, new byte[(int) file.length()]); + } finally { + stream.close(); + } + } + + /** + * Creates/overwrites a file with a given string. + */ + public static void fill(File file, String content) throws IOException { + final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file)); + try { + bufferedWriter.write(content); + } finally { + bufferedWriter.close(); + } + } + + /** + * Creates/overwrites a file from a reader. + */ + public static void fill(File file, Reader reader, boolean append) throws IOException { + final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file)); + try { + int ch; + while ((ch = reader.read()) != -1) { + bufferedWriter.write(ch); + } + } finally { + bufferedWriter.close(); + } + } + + public static void readLines(File file, List lines) throws IOException { + final BufferedReader reader = new BufferedReader(new FileReader(file)); + String line; + while ((line = reader.readLine()) != null) { + lines.add(line); + } + reader.close(); + } + + public static List readLines(File file) throws IOException { + final List lines = new ArrayList(); + readLines(file, lines); + return lines; + } + + public static char[] toChars(File file) throws IOException { + if (file.length() > Integer.MAX_VALUE) { + throw new IOException("file is too big to read into an array: " + file); + } + int length = (int) file.length(); + if (length == 0) { + return new char[0]; + } + final Reader fileReader = new BufferedReader(new FileReader(file), length); + char[] chars = new char[length]; + try { + chars = Streams.readFully(fileReader, chars); + } catch (TruncatedInputException truncatedInputException) { + // Must have been multi-byte characters in the file + length = truncatedInputException.inputLength(); + final char[] oldChars = chars; + chars = new char[length]; + System.arraycopy(oldChars, 0, chars, 0, length); + } finally { + fileReader.close(); + } + return chars; + } + + /** + * Updates the generated content part of a file. A generated content part is delimited by a line containing only + * {@code start} and a line containing only {@code end}. If the given file already exists and has these delimiters, + * the content between these lines is compared with {@code content} and replaced if it is different. If the file + * does not exist, a new file is created with {@code content} surrounded by the specified delimiters. If the file + * exists and does not currently have the specified delimiters, an IOException is thrown. + * + * @param file the file to be modified (or created) with some generated content + * @param content the generated content + * @param start the starting delimiter of the section in {@code file} to be updated with {@code content} + * @param start the ending delimiter of the section in {@code file} to be updated with {@code content} + * @param checkOnly if {@code true}, then {@code file} is not updated; the value returned by this method indicates + * whether it would have been updated were this argument {@code true} + * @return true if {@code file} was modified or created (or would have been if {@code checkOnly} was {@code false}) + */ + public static boolean updateGeneratedContent(File file, ReadableSource content, String start, String end, boolean checkOnly) throws IOException { + + if (!file.exists()) { + if (checkOnly) { + return true; + } + final PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file))); + try { + final Reader reader = content.reader(true); + try { + printWriter.println(start); + Streams.copy(reader, printWriter); + printWriter.println(end); + } finally { + reader.close(); + } + } finally { + printWriter.close(); + } + return true; + } + + final File tempFile = File.createTempFile(file.getName() + ".", null); + PrintWriter printWriter = null; + BufferedReader contentReader = null; + BufferedReader existingFileReader = null; + try { + printWriter = new PrintWriter(new BufferedWriter(new FileWriter(tempFile))); + contentReader = (BufferedReader) content.reader(true); + existingFileReader = new BufferedReader(new FileReader(file)); + + // Copy existing file up to generated content opening delimiter + String line; + while ((line = existingFileReader.readLine()) != null) { + printWriter.println(line); + if (line.equals(start)) { + break; + } + } + + if (line == null) { + throw new IOException("generated content starting delimiter \"" + start + "\" not found in existing file: " + file); + } + + boolean changed = false; + boolean seenEnd = false; + + // Copy new content, noting if it differs from existing generated content + while ((line = contentReader.readLine()) != null) { + if (!seenEnd) { + final String existingLine = existingFileReader.readLine(); + if (existingLine != null) { + if (end.equals(existingLine)) { + seenEnd = true; + changed = true; + } else { + changed = changed || !line.equals(existingLine); + } + } + } + printWriter.println(line); + } + + // Find the generated content closing delimiter + if (!seenEnd) { + while ((line = existingFileReader.readLine()) != null) { + if (line.equals(end)) { + seenEnd = true; + break; + } + changed = true; + } + if (!seenEnd) { + throw new IOException("generated content ending delimiter \"" + end + "\" not found in existing file: " + file); + } + } + printWriter.println(end); + + // Copy existing file after generated content closing delimiter + while ((line = existingFileReader.readLine()) != null) { + printWriter.println(line); + } + + printWriter.close(); + printWriter = null; + existingFileReader.close(); + existingFileReader = null; + + if (changed) { + if (!checkOnly) { + copy(tempFile, file); + } + return true; + } + return false; + } finally { + quietClose(printWriter); + quietClose(contentReader); + quietClose(existingFileReader); + if (!tempFile.delete()) { + throw new IOException("could not delete file for update: " + file); + } + } + } + + private static void quietClose(Closeable closeable) { + if (closeable != null) { + try { + closeable.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static List find(File directory, final String suffix, List listing) { + final Predicate suffixPredicate = new Predicate() { + public boolean evaluate(File file) { + return file.getName().endsWith(suffix); + } + + }; + return find(directory, suffixPredicate, listing); + } + + public static List find(File directory, Predicate filter, List listing) { + assert directory.isDirectory(); + return find(directory, listing == null ? new LinkedList() : listing, filter); + } + + private static List find(File directory, List listing, Predicate filter) { + assert directory.isDirectory(); + final File[] entries = directory.listFiles(); + if (entries != null) { + for (File entry : entries) { + if (!entry.isDirectory()) { + if (filter == null || filter.evaluate(entry)) { + listing.add(entry); + } + } else { + find(entry, listing, filter); + } + } + } + return listing; + } + + public static void unzip(File zip, File destDir) { + if (!destDir.exists() && !destDir.mkdirs()) { + ProgramError.unexpected("Could not make directory " + destDir); + } + Enumeration entries; + ZipFile zipFile; + try { + Trace.line(2, "Extracting contents of " + zip.getAbsolutePath() + " to " + destDir); + zipFile = new ZipFile(zip); + entries = zipFile.entries(); + while (entries.hasMoreElements()) { + final ZipEntry entry = (ZipEntry) entries.nextElement(); + final File parentDir; + if (entry.isDirectory()) { + parentDir = new File(destDir, entry.getName()); + } else { + final String relParentDir = new File(entry.getName()).getParent(); + if (relParentDir != null) { + parentDir = new File(destDir, relParentDir); + } else { + parentDir = destDir; + } + } + if (!parentDir.exists() && !parentDir.mkdirs()) { + ProgramError.unexpected("Could not make directory " + parentDir); + } + if (!entry.isDirectory()) { + final File destFile = new File(destDir, entry.getName()); + Trace.line(2, " inflating: " + entry.getName() + " ..."); + Streams.copy(zipFile.getInputStream(entry), new FileOutputStream(destFile)); + } + } + zipFile.close(); + } catch (IOException ioe) { + ProgramError.unexpected("Error extracting " + zip.getAbsolutePath() + " to " + destDir, ioe); + } + } + + public static boolean compareFiles(File f1, File f2, String[] ignoredLinePatterns) { + try { + final BufferedReader f1Reader = new BufferedReader(new FileReader(f1)); + final BufferedReader f2Reader = new BufferedReader(new FileReader(f2)); + try { + String line1; + String line2; + nextLine: + while (true) { + line1 = f1Reader.readLine(); + line2 = f2Reader.readLine(); + if (line1 == null) { + if (line2 == null) { + return true; + } + return false; + } + if (!line1.equals(line2)) { + if (line2 == null) { + return false; + } + if (ignoredLinePatterns != null) { + for (String pattern : ignoredLinePatterns) { + if (line1.contains(pattern) && line2.contains(pattern)) { + continue nextLine; + } + } + } + return false; + } + } + } finally { + f1Reader.close(); + f2Reader.close(); + } + } catch (IOException e) { + return false; + } + } +} + diff --git a/JavaInJava/src/com/sun/max/io/IndentWriter.java b/JavaInJava/src/com/sun/max/io/IndentWriter.java new file mode 100644 index 0000000..93216b5 --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/IndentWriter.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +import com.sun.max.program.*; + +/** + * A line oriented character writer that indents line output on the left. + * + * @author Bernd Mathiske + */ +public class IndentWriter { + + private final PrintWriter writer; + private int lineCount; + + /** + * Gets an IndentWriter that wraps the {@linkplain Trace#stream() trace stream}. + * @return + */ + public static IndentWriter traceStreamWriter() { + return new IndentWriter(new OutputStreamWriter(Trace.stream())); + } + + public IndentWriter(Writer writer) { + this.writer = (writer instanceof PrintWriter) ? (PrintWriter) writer : new PrintWriter(writer); + } + + public void close() { + writer.close(); + } + + public void flush() { + writer.flush(); + } + + private int indentation = 4; + + public int indentation() { + return indentation; + } + + public void setIndentation(int indentation) { + this.indentation = indentation; + } + + private int prefix; + + public void indent() { + prefix += indentation; + } + + public void outdent() { + prefix -= indentation; + assert prefix >= 0; + } + + private boolean isCurrentLineIndented; + + private void writeIndentation() { + if (!isCurrentLineIndented) { + for (int i = 0; i < prefix; i++) { + writer.print(" "); + } + isCurrentLineIndented = true; + } + } + + public void printSpaces(int width) { + for (int i = 0; i < width; i++) { + writer.print(" "); + } + } + + public void printFixedWidth(String s, int width) { + assert width > 0 : "width must be positive"; + String text = s; + if (text.length() + 1 > width) { + if (width - 4 > 0) { + text = s.substring(0, width - 4) + "..."; + } else { + text = s.substring(0, width); + } + } + writer.print(text); + printSpaces(width - text.length()); + } + + public void print(String s) { + writeIndentation(); + writer.print(s); + } + + public void println() { + writer.println(); + isCurrentLineIndented = false; + ++lineCount; + } + + public void println(String s) { + writeIndentation(); + writer.println(s); + isCurrentLineIndented = false; + ++lineCount; + } + + public void printLines(InputStream inputStream) { + printLines(new InputStreamReader(inputStream)); + } + + public void printLines(Reader reader) { + final BufferedReader bufferedReader = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); + String line; + try { + while ((line = bufferedReader.readLine()) != null) { + println(line); + } + } catch (IOException e) { + ProgramWarning.message(e.toString()); + } + } + + public int lineCount() { + return lineCount; + } +} diff --git a/JavaInJava/src/com/sun/max/io/MultiOutputStream.java b/JavaInJava/src/com/sun/max/io/MultiOutputStream.java new file mode 100644 index 0000000..04ead3c --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/MultiOutputStream.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +/** + * Writes the same output to several streams. + * + * @author Bernd Mathiske + */ +public class MultiOutputStream extends OutputStream { + + private final OutputStream[] streams; + + public MultiOutputStream(OutputStream... streams) { + this.streams = streams; + } + + @Override + public void write(int b) throws IOException { + for (OutputStream stream : streams) { + stream.write(b); + } + } + + @Override + public void write(byte[] bytes) throws IOException { + for (OutputStream stream : streams) { + stream.write(bytes); + } + } + + @Override + public void write(byte[] bytes, int startOffset, int numberOfBytes) throws IOException { + for (OutputStream stream : streams) { + stream.write(bytes, startOffset, numberOfBytes); + } + } + + @Override + public void flush() throws IOException { + for (OutputStream stream : streams) { + stream.flush(); + } + } + + @Override + public void close() throws IOException { + for (OutputStream stream : streams) { + stream.close(); + } + } +} diff --git a/JavaInJava/src/com/sun/max/io/NullOutputStream.java b/JavaInJava/src/com/sun/max/io/NullOutputStream.java new file mode 100644 index 0000000..5a1a0bb --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/NullOutputStream.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +/** + * An output stream that discards everything written to it. + * + * @author Doug Simon + */ +public class NullOutputStream extends OutputStream { + + @Override + public void write(int b) throws IOException { + } + + @Override + public void close() throws IOException { + } + + @Override + public void flush() throws IOException { + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + } + + @Override + public void write(byte[] b) throws IOException { + } +} diff --git a/JavaInJava/src/com/sun/max/io/Package.java b/JavaInJava/src/com/sun/max/io/Package.java new file mode 100755 index 0000000..ddc44dc --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import com.sun.max.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/io/ReadableSource.java b/JavaInJava/src/com/sun/max/io/ReadableSource.java new file mode 100644 index 0000000..8d9439a --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/ReadableSource.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +/** + * A readable source is a character data source that provides a Reader to read the data. + * + * @author Doug Simon + */ +public interface ReadableSource { + + /** + * @param buffered if true, the returned reader is guaranteed to be a BufferedReader + * + * @return a reader to read the character data represented by this source + */ + Reader reader(boolean buffered) throws IOException; + + public static final class Static { + + private Static() { + + } + + /** + * Creates a ReadableSource to provides readers for the characters in a string. + */ + public static ReadableSource fromString(final String s) { + return new ReadableSource() { + public Reader reader(boolean buffered) throws IOException { + return buffered ? new BufferedReader(new StringReader(s)) : new StringReader(s); + } + }; + } + + /** + * Creates a ReadableSource to provides readers for the characters in a file. + */ + public static ReadableSource fromFile(final File file) { + return new ReadableSource() { + public Reader reader(boolean buffered) throws IOException { + return buffered ? new BufferedReader(new FileReader(file)) : new FileReader(file); + } + }; + + } + } +} diff --git a/JavaInJava/src/com/sun/max/io/SeekableByteArrayOutputStream.java b/JavaInJava/src/com/sun/max/io/SeekableByteArrayOutputStream.java new file mode 100644 index 0000000..a7f5a65 --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/SeekableByteArrayOutputStream.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +/** + * A {@link ByteArrayOutputStream} that can have its write position {@linkplain #seek(int) updated}. + * + * @author Doug Simon + */ +public class SeekableByteArrayOutputStream extends ByteArrayOutputStream { + + private int highestCount; + + /** + * @see ByteArrayOutputStream#ByteArrayOutputStream() + */ + public SeekableByteArrayOutputStream() { + } + + /** + * @see ByteArrayOutputStream#ByteArrayOutputStream(int) + */ + public SeekableByteArrayOutputStream(int size) { + super(size); + } + + /** + * Updates the write position of this stream. The stream can only be repositioned between 0 and the + * {@linkplain #endOfStream() end of the stream}. + * + * @param index + * the index to which the write position of this stream will be set + * @throws IllegalArgumentException + * if {@code index > highestSeekIndex()} + */ + public void seek(int index) throws IllegalArgumentException { + if (endOfStream() < index) { + throw new IllegalArgumentException(); + } + count = index; + } + + /** + * Gets the index one past the highest index that has been written to in this stream. + */ + public int endOfStream() { + if (highestCount < count) { + highestCount = count; + } + return highestCount; + } + + @Override + public void reset() { + super.reset(); + highestCount = 0; + } + + /** + * Copies the {@code length} bytes of this byte array output stream starting at {@code offset} to {@code buf} + * starting at {@code bufOffset}. + */ + public void copyTo(int offset, byte[] toBuffer, int toOffset, int length) { + System.arraycopy(this.buf, offset, toBuffer, toOffset, length); + } +} diff --git a/JavaInJava/src/com/sun/max/io/Streams.java b/JavaInJava/src/com/sun/max/io/Streams.java new file mode 100644 index 0000000..3206a35 --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/Streams.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +import com.sun.max.lang.*; + +/** + * Supplementary java.io utils. + * + * @author Bernd Mathiske + */ +public final class Streams { + + private Streams() { + } + + public static void copy(InputStream inputStream, OutputStream outputStream) throws IOException { + final byte[] buffer = new byte[8192]; + int count; + while ((count = inputStream.read(buffer, 0, buffer.length)) > 0) { + outputStream.write(buffer, 0, count); + } + outputStream.flush(); + } + + public static void copy(Reader reader, Writer writer) throws IOException { + final char[] buffer = new char[8192]; + int count; + while ((count = reader.read(buffer, 0, buffer.length)) > 0) { + writer.write(buffer, 0, count); + } + writer.flush(); + } + + public static boolean equals(InputStream inputStream1, InputStream inputStream2) throws IOException { + final int n = 8192; + final byte[] buffer1 = new byte[n]; + final byte[] buffer2 = new byte[n]; + while (true) { + final int n1 = inputStream1.read(buffer1, 0, n); + final int n2 = inputStream2.read(buffer2, 0, n); + if (n1 != n2) { + return false; + } + if (n1 <= 0) { + return true; + } + if (!Bytes.equals(buffer1, buffer2, n)) { + return false; + } + } + } + + public static final class Redirector extends Thread { + + private final InputStream inputStream; + private final OutputStream outputStream; + private final String name; + private final int maxLines; + private final Process process; + private boolean closed; + + private Redirector(Process process, InputStream inputStream, OutputStream outputStream, String name, int maxLines) { + super("StreamRedirector{" + name + "}"); + this.inputStream = inputStream; + this.outputStream = outputStream; + this.name = name; + this.maxLines = maxLines; + this.process = process; + start(); + } + + public void close() { + closed = true; + } + + @Override + public void run() { + try { + try { + int line = 1; + while (!closed) { + if (inputStream.available() == 0) { + // A busy yielding loop is used so that this thread can be + // stopped via a call to close() by another thread. Otherwise, + // this thread could be blocked forever on an input stream + // that is not closed and does not have any available data. + // The prime example of course is System.in. + Thread.yield(); + // wait for a few milliseconds to avoid eating too much CPU. + Thread.sleep(10); + continue; + } + + final int b = inputStream.read(); + if (b < 0) { + return; + } + if (line <= maxLines) { + outputStream.write(b); + } + if (b == '\n') { + if (line == maxLines) { + outputStream.write(("" + System.getProperty("line.separator", "\n")).getBytes()); + } + ++line; + } + } + outputStream.flush(); + } catch (IOException ioe) { + try { + process.exitValue(); + + // This just means the process was terminated and the relevant pipe no longer exists + } catch (IllegalThreadStateException e) { + // Some other unexpected IO error occurred -> rethrow + throw e; + } + } + } catch (Throwable throwable) { + if (name != null) { + System.err.println("Error while redirecting sub-process stream for \"" + name + "\""); + } + throwable.printStackTrace(); + } + } + + } + + public static Redirector redirect(Process process, InputStream inputStream, OutputStream outputStream, String name, int maxLines) { + return new Redirector(process, inputStream, outputStream, name, maxLines); + } + + public static Redirector redirect(Process process, InputStream inputStream, OutputStream outputStream, String name) { + return redirect(process, inputStream, outputStream, name, Integer.MAX_VALUE); + } + + public static Redirector redirect(Process process, InputStream inputStream, OutputStream outputStream) { + return redirect(process, inputStream, outputStream, null, Integer.MAX_VALUE); + } + + /** + * Scans a given buffered input stream for a given sequence of bytes. If the sequence is found, then the read + * position of the stream is immediately after the sequence. Otherwise, the read position is at the end of the + * stream. + * + * @param stream + * the stream to search + * @param bytes + * the byte pattern to search for + * @return true if {@code bytes} is found in {@code stream} + */ + public static boolean search(BufferedInputStream stream, byte[] bytes) throws IOException { + if (bytes.length == 0) { + return true; + } + int b1 = stream.read(); + top: + while (b1 != -1) { + if (b1 == (bytes[0] & 0xff)) { + for (int i = 1; i < bytes.length; ++i) { + b1 = stream.read(); + if (b1 != (bytes[i] & 0xff)) { + continue top; + } + } + return true; + } + b1 = stream.read(); + } + return false; + } + + /** + * Scans a given buffered reader for a given sequence of characters. If the sequence is found, then the read + * position of the reader is immediately after the sequence. Otherwise, the read position is at the end of the + * reader. + * + * @param reader + * the reader to search + * @param chars + * the char pattern to search for + * @return true if {@code chars} is found in {@code reader} + */ + public static boolean search(BufferedReader reader, char[] chars) throws IOException { + if (chars.length == 0) { + return true; + } + int c1 = reader.read(); + top: + while (c1 != -1) { + if (c1 == chars[0]) { + for (int i = 1; i < chars.length; ++i) { + c1 = reader.read(); + if (c1 != chars[i]) { + continue top; + } + } + return true; + } + c1 = reader.read(); + } + return false; + } + + public static boolean startsWith(BufferedInputStream bufferedInputStream, byte[] bytes) throws IOException { + final byte[] data = new byte[bytes.length]; + bufferedInputStream.mark(bytes.length); + try { + readFully(bufferedInputStream, data); + if (java.util.Arrays.equals(data, bytes)) { + return true; + } + } catch (IOException ioException) { + // This is OK + } + bufferedInputStream.reset(); + return false; + } + + public static boolean startsWith(BufferedReader bufferedReader, char[] chars) throws IOException { + final char[] data = new char[chars.length]; + bufferedReader.mark(chars.length); + try { + readFully(bufferedReader, data); + if (java.util.Arrays.equals(data, chars)) { + return true; + } + } catch (IOException ioException) { + // This is OK + } + bufferedReader.reset(); + return false; + } + + /** + * @see DataInput#readFully(byte[]) + */ + public static byte[] readFully(InputStream stream, byte[] buffer) throws IOException { + return readFully(stream, buffer, 0, buffer.length); + } + + /** + * @see DataInput#readFully(byte[], int, int) + */ + public static byte[] readFully(InputStream stream, byte[] buffer, int offset, int length) throws IOException { + if (length < 0) { + throw new IndexOutOfBoundsException(); + } + int n = 0; + while (n < length) { + final int count = stream.read(buffer, offset + n, length - n); + if (count < 0) { + throw new EOFException((length - n) + " of " + length + " bytes unread"); + } + n += count; + } + return buffer; + } + + /** + * The analogous operation as {@link DataInput#readFully(byte[])} for {@link Reader}s. + */ + public static char[] readFully(Reader reader, char[] buffer) throws IOException { + return readFully(reader, buffer, 0, buffer.length); + } + + /** + * The analogous operation as {@link DataInput#readFully(byte[], int, int)} for {@link Reader}s. + */ + public static char[] readFully(Reader reader, char[] buffer, int offset, int length) throws IOException { + if (length < 0) { + throw new IndexOutOfBoundsException(); + } + int n = 0; + while (n < length) { + final int count = reader.read(buffer, offset + n, length - n); + if (count < 0) { + throw new TruncatedInputException((length - n) + " of " + length + " characters unread", n); + } + n += count; + } + return buffer; + } +} diff --git a/JavaInJava/src/com/sun/max/io/TemporaryFiles.java b/JavaInJava/src/com/sun/max/io/TemporaryFiles.java new file mode 100644 index 0000000..2296d41 --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/TemporaryFiles.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +import com.sun.max.program.*; + +public final class TemporaryFiles { + private TemporaryFiles() { + } + + public static void cleanup(final String prefix, final String suffix) { + if ((prefix == null || prefix.length() == 0) && (suffix == null || suffix.length() == 0)) { + return; + } + try { + final File tempFile = File.createTempFile(prefix, suffix); + final File directory = tempFile.getParentFile(); + final FilenameFilter filter = new FilenameFilter() { + public boolean accept(File dir, String name) { + if (prefix != null && prefix.length() > 0 && !name.startsWith(prefix)) { + return false; + } + if (suffix != null && suffix.length() > 0 && !name.endsWith(suffix)) { + return false; + } + return true; + } + }; + for (File file : directory.listFiles(filter)) { + if (!file.delete()) { + ProgramWarning.message("could not delete temporary file: " + file.getAbsolutePath()); + } + } + } catch (IOException ioException) { + ProgramWarning.message("could not delete temporary files"); + } + } + + public static void cleanup(String prefix) { + cleanup(prefix, null); + } +} diff --git a/JavaInJava/src/com/sun/max/io/TruncatedInputException.java b/JavaInJava/src/com/sun/max/io/TruncatedInputException.java new file mode 100644 index 0000000..5e024e4 --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/TruncatedInputException.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.io; + +import java.io.*; + +/** + * Unexpected EOF during input. + * + * @author Michael Van De Vanter + */ +public class TruncatedInputException extends EOFException { + + private final int nRead; + + /** + * @param s Exception message + * @param n Length of input read before EOF. + */ + public TruncatedInputException(String s, int n) { + super(s); + nRead = n; + } + + /** + * + * @return Length of input read before EOF. + */ + public int inputLength() { + return nRead; + } + +} diff --git a/JavaInJava/src/com/sun/max/io/package-info.java b/JavaInJava/src/com/sun/max/io/package-info.java new file mode 100644 index 0000000..6684cba --- /dev/null +++ b/JavaInJava/src/com/sun/max/io/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * Supplementing java.io. + * + * @author Bernd Mathiske + */ +package com.sun.max.io; diff --git a/JavaInJava/src/com/sun/max/lang/Bytes.java b/JavaInJava/src/com/sun/max/lang/Bytes.java new file mode 100644 index 0000000..3ca16a6 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Bytes.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.io.*; + +import com.sun.max.io.*; +import com.sun.max.util.*; + +/** + * Byte and byte array operations. + * + * @author Bernd Mathiske + * @author Michael Van De Vanter + */ +public final class Bytes { + + private Bytes() { + } + + public static final int SIZE = 1; + public static final int WIDTH = 8; + public static final int MASK = 0xff; + + public static final Range VALUE_RANGE = new Range(Byte.MIN_VALUE, Byte.MAX_VALUE); + + public static int zeroExtendedToInt(byte b) { + final char ch = (char) b; + return ch; + } + + /** + * Returns the number of zero bits following the lowest-order ("rightmost") + * one-bit in the two's complement binary representation of the specified + * {@code byte} value. Returns 8 if the specified value has no + * one-bits in its two's complement representation, in other words if it is + * equal to zero. + * + * @return the number of zero bits following the lowest-order ("rightmost") + * one-bit in the two's complement binary representation of the + * specified {@code byte} value, or 8 if the value is equal + * to zero. + */ + public static int numberOfTrailingZeros(byte b) { + // HD, Figure 5-14 + int y; + int i = b & 0xFF; + if (i == 0) { + return 8; + } + int n = 7; + y = (i << 4) & 0xFF; + if (y != 0) { + n = n - 4; + i = y; + } + y = (i << 2) & 0xFF; + if (y != 0) { + n = n - 2; + i = y; + } + return n - (((i << 1) & 0xFF) >>> 7); + } + + /** + * Are the bytes of an array, starting at some position, equal to the contents + * of a second array. + * @param array1 An array of bytes + * @param startIndex1 Index in {@code array1} at which to start comparison + * @param array2 An array of bytes to be compared + * @return tree iff the entire contents of {@code array2} are equal to + * the contents of {@code array1}, starting at {@code startIndex1}. + */ + public static boolean equals(byte[] array1, int startIndex1, byte[] array2) { + if (array1.length < startIndex1 + array2.length) { + return false; + } + for (int i = 0; i < array2.length; i++) { + if (array1[startIndex1 + i] != array2[i]) { + return false; + } + } + return true; + } + + /** + * Compares the first {@code length} bytes in two byte arrays + * for equality. + */ + public static boolean equals(byte[] array1, byte[] array2, int length) { + if (array1.length < length || array2.length < length) { + return false; + } + for (int i = 0; i < length; i++) { + if (array1[i] != array2[i]) { + return false; + } + } + return true; + } + + /** + * Compares the contents of two byte arrays for equality. + */ + public static boolean equals(byte[] array1, byte[] array2) { + if (array1 == array2) { + return true; + } + if (array1.length != array2.length) { + return false; + } + return equals(array1, array2, array1.length); + } + + public static void copy(byte[] fromArray, int fromStartIndex, byte[] toArray, + final int toStartIndex, int nBytes) { + for (int i = 0; i < nBytes; i++) { + toArray[toStartIndex + i] = fromArray[fromStartIndex + i]; + } + } + + public static void copy(byte[] fromArray, byte[] toArray, int nBytes) { + copy(fromArray, 0, toArray, 0, nBytes); + } + + public static void copyAll(byte[] fromArray, byte[] toArray, int toStartIndex) { + copy(fromArray, 0, toArray, toStartIndex, fromArray.length); + } + + public static void copyAll(byte[] fromArray, byte[] toArray) { + copy(fromArray, 0, toArray, 0, fromArray.length); + } + + public static byte[] withLength(byte[] array, int length) { + final byte[] result = new byte[length]; + if (length >= array.length) { + copyAll(array, result); + } else { + copy(array, result, length); + } + return result; + } + + public static byte[] getSection(byte[] fromArray, int startIndex, int endIndex) { + final int length = endIndex - startIndex; + final byte[] result = new byte[length]; + copy(fromArray, startIndex, result, 0, length); + return result; + } + + /** + * Assigns zero to every byte in an array. + */ + public static void clear(byte[] array) { + for (int i = 0; i < array.length; i++) { + array[i] = (byte) 0; + } + } + + public static boolean areClear(byte[] array) { + for (int i = 0; i < array.length; i++) { + if (array[i] != (byte) 0) { + return false; + } + } + return true; + } + + /** + * @param value a byte + * @return A string representation of the byte in hexadecimal, e.g. "0x0A" + */ + public static String toHexLiteral(byte value) { + String hexString = Integer.toHexString(value).toUpperCase(); + if (hexString.length() == 1) { + hexString = "0" + hexString; + } else if (hexString.length() > 2) { + hexString = hexString.substring(hexString.length() - 2); + } + return "0x" + hexString; + } + + /** + * @param values an array of bytes + * @return A string representation of the bytes in hexadecimal, e.g. "0x01A203" + */ + public static String toHexLiteral(byte[] values) { + String s = "0x"; + for (byte value : values) { + String hexString = Integer.toHexString(value).toUpperCase(); + if (hexString.length() == 1) { + hexString = "0" + hexString; + } + s += hexString; + } + return s; + } + + /** + * Returns a string representation of the contents of the specified array. + * Adjacent elements are separated by the specified separator. Elements are + * converted to strings with {@link #toHexLiteral(byte)}. + * + * @param array the array whose string representation to return + * @param separator the separator to use + * @return a string representation of array + * @throws NullPointerException if {@code array} or {@code separator} is null + */ + public static String toHexString(byte[] array, String separator) { + if (array == null || separator == null) { + throw new NullPointerException(); + } + if (array.length == 0) { + return ""; + } + + final StringBuilder buf = new StringBuilder(); + buf.append(toHexLiteral(array[0])); + + for (int i = 1; i < array.length; i++) { + buf.append(separator); + buf.append(toHexLiteral(array[i])); + } + + return buf.toString(); + } + + public static byte[] fromInputStream(InputStream inputStream) throws IOException { + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Streams.copy(inputStream, outputStream); + return outputStream.toByteArray(); + } + +} diff --git a/JavaInJava/src/com/sun/max/lang/Chars.java b/JavaInJava/src/com/sun/max/lang/Chars.java new file mode 100644 index 0000000..f9b9986 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Chars.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import com.sun.max.util.*; + +/** + * @author Bernd Mathiske + */ +public final class Chars { + + private Chars() { + } + + public static final int SIZE = 2; + + public static final Range VALUE_RANGE = new Range(Character.MIN_VALUE, Character.MAX_VALUE); + + public static boolean isHexDigit(char c) { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + return true; + } + return false; + } + + public static boolean isOctalDigit(char c) { + if (c < '0') { + return false; + } + return c <= '7'; + } + + public static String toJavaLiteral(char c) { + if (c == '\n') { + return "'\\n'"; + } + if (c == '\t') { + return "'\\t'"; + } + if (c == '\r') { + return "'\\r'"; + } + if (c < ' ' || c > 127) { + return "'\\" + Integer.toOctalString(c) + "'"; + } + return "'" + c + "'"; + } +} diff --git a/JavaInJava/src/com/sun/max/lang/Classes.java b/JavaInJava/src/com/sun/max/lang/Classes.java new file mode 100644 index 0000000..3bde311 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Classes.java @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.lang.reflect.*; + +import com.sun.max.*; + +/** + * Methods that might be members of java.lang.Class. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public final class Classes { + + private Classes() { + } + + /** + * Wraps a call to {@link ClassLoader#loadClass(String)} that is expected not to fail. Should a + * {@link ClassNotFoundException} occur, it is converted to {@link NoClassDefFoundError} + * + * @return the value returned by calling {@link ClassLoader#loadClass(String)} on {@code classLoader} + */ + public static Class load(ClassLoader classLoader, String name) { + try { + return classLoader.loadClass(name); + } catch (ClassNotFoundException e) { + throw (NoClassDefFoundError) new NoClassDefFoundError(name).initCause(e); + } + } + + /** + * Wraps a call to {@link Class#forName(String)} that is expected not to fail. Should a + * {@link ClassNotFoundException} occur, it is converted to {@link NoClassDefFoundError} + */ + public static Class forName(String name) { + try { + return Class.forName(name); + } catch (ClassNotFoundException e) { + throw (NoClassDefFoundError) new NoClassDefFoundError(name).initCause(e); + } + } + + /** + * Wraps a call to {@link Class#forName(String, boolean, ClassLoader)} that is expected not to fail. Should a + * {@link ClassNotFoundException} occur, it is converted to {@link NoClassDefFoundError} + */ + public static Class forName(String name, boolean initialize, ClassLoader loader) { + try { + return Class.forName(name, initialize, loader); + } catch (ClassNotFoundException e) { + throw (NoClassDefFoundError) new NoClassDefFoundError(name).initCause(e); + } + } + + /** + * Links a given class. If the class {@code c} has already been linked, then this method simply returns. Otherwise, + * the class is linked as described in the "Execution" chapter of the Java Language Specification. + * + * @param c the class to link + */ + public static void link(Class c) { + if (c != null) { + try { + final Class linkedClass = Class.forName(c.getName(), false, c.getClassLoader()); + assert linkedClass == c; + } catch (ClassNotFoundException classNotFoundException) { + throw (NoClassDefFoundError) new NoClassDefFoundError(c.getName()).initCause(classNotFoundException); + } + } + } + + /** + * Initializes a given class. If the class {@code c} has already been initialized, then this method simply returns. Otherwise, + * the class is linked as described in the "Execution" chapter of the Java Language Specification. + * + * @param c the class to link + */ + public static void initialize(Class c) { + try { + Class.forName(c.getName(), true, c.getClassLoader()); + } catch (ClassNotFoundException classNotFoundException) { + throw (NoClassDefFoundError) new NoClassDefFoundError(c.getName()).initCause(classNotFoundException); + } + } + + public static boolean areRelated(Class class1, Class class2) { + return class1.isAssignableFrom(class2) || class2.isAssignableFrom(class1); + } + + public static boolean areAssignableFrom(Class[] superTypes, Class... subTypes) { + if (superTypes.length != subTypes.length) { + return false; + } + for (int i = 0; i < superTypes.length; i++) { + if (!superTypes[i].isAssignableFrom(subTypes[i])) { + return false; + } + } + return true; + } + + /** + * Extends the functionality of {@link Class#getConstructor(Class...)} to find a constructor whose formal parameter + * types are assignable from the types of a list of arguments. + * + * @param javaClass the class to search in + * @param arguments the list of arguments that will be passed to the constructor + * @return the first constructor in {@link Class#getConstructors() javaClass.getConstructors()} that will accept + * {@code arguments} or null if no such constructor exists + */ + public static Constructor findConstructor(Class javaClass, Object... arguments) { + nextConstructor: + for (Constructor constructor : javaClass.getConstructors()) { + final Class[] parameterTypes = constructor.getParameterTypes(); + if (parameterTypes.length == arguments.length) { + for (int i = 0; i != arguments.length; ++i) { + if (!parameterTypes[i].isAssignableFrom(arguments[i].getClass())) { + continue nextConstructor; + } + } + return constructor; + } + } + return null; + } + + /** + * Extends the functionality of {@link Class#getMethod(String, Class...)} to find a method whose formal parameter + * types are assignable from the types of a list of arguments. + * + * @param javaClass the class to search in + * @param name the name of the method to search for + * @param arguments the list of arguments that will be passed to the constructor + * @return the first method in {@link Class#getMethods() javaClass.getMethods()} that will accept {@code arguments} + * or null if no such method exists + */ + public static Method findMethod(Class javaClass, String name, Object... arguments) { + nextMethod: + for (Method method : javaClass.getMethods()) { + final Class[] parameterTypes = method.getParameterTypes(); + if (method.getName().equals(name) && parameterTypes.length == arguments.length) { + for (int i = 0; i != arguments.length; ++i) { + if (!parameterTypes[i].isAssignableFrom(arguments[i].getClass())) { + continue nextMethod; + } + } + return method; + } + } + return null; + } + + /** + * Extends the functionality of {@link Class#getDeclaredMethod(String, Class...)} to find a method whose formal + * parameter types are assignable from the types of a list of arguments. + * + * @param javaClass the class to search in + * @param name the name of the method to search for + * @param arguments the list of arguments that will be passed to the constructor + * @return the first method in {@link Class#getDeclaredMethods() javaClass.getDeclaredMethods()} that will accept + * {@code arguments} or null if no such method exists + */ + public static Method findDeclaredMethod(Class javaClass, String name, Object... arguments) { + nextMethod: + for (Method declaredMethod : javaClass.getDeclaredMethods()) { + final Class[] parameterTypes = declaredMethod.getParameterTypes(); + if (declaredMethod.getName().equals(name) && parameterTypes.length == arguments.length) { + for (int i = 0; i != arguments.length; ++i) { + if (!parameterTypes[i].isAssignableFrom(arguments[i].getClass())) { + continue nextMethod; + } + } + return declaredMethod; + } + } + return null; + } + + /** + * Performs method resolution as detailed in section 5.4.3.3 of the JVM specification except for the accessibility + * checks detailed in section 5.4.4. + * + * @param javaClass the class to start the resolution from + * @param returnType the return type of the method to resolve + * @param name the name of the method to resolve + * @param parameterTypes the parameter types of the method to resolve + * @return the resolved method + * @throws NoSuchMethodError if the method resolution fails + * @throws AbstractMethodError if the resolved method is abstract + */ + public static Method resolveMethod(Class javaClass, Class returnType, String name, Class... parameterTypes) { + if (!name.equals("") && !name.equals("")) { + Class declaringClass = javaClass; + if (javaClass.isInterface()) { + try { + return javaClass.getMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + throw new NoSuchMethodError(e.getMessage()); + } + } + do { + try { + final Method method = getDeclaredMethod(declaringClass, returnType, name, parameterTypes); + if (Modifier.isAbstract(method.getModifiers()) && !Modifier.isAbstract(declaringClass.getModifiers())) { + throw new AbstractMethodError(); + } + return method; + } catch (NoSuchMethodError e) { + declaringClass = declaringClass.getSuperclass(); + } + } while (declaringClass != null); + } + throw new NoSuchMethodError(returnType.getName() + " " + javaClass.getName() + "." + name + "(" + Utils.toString(parameterTypes, ", ") + ")"); + } + + /** + * Performs field resolution as detailed in section 5.4.3.2 of the JVM specification except for the accessibility + * checks detailed in section 5.4.4. + * @param javaClass the class to start the resolution from + * @param type the type of the field to resolve + * @param name the name of the field to resolve + * + * @return the resolved field + * @throws NoSuchFieldError if the field resolution fails + */ + public static Field resolveField(Class javaClass, Class type, String name) { + Class declaringClass = javaClass; + do { + try { + return getDeclaredField(declaringClass, name, type); + } catch (NoSuchFieldError e) { + for (Class superInterface : javaClass.getInterfaces()) { + try { + return resolveField(superInterface, type, name); + } catch (NoSuchFieldError noSuchFieldError) { + // Ignore + } + } + declaringClass = declaringClass.getSuperclass(); + } + } while (declaringClass != null); + throw new NoSuchFieldError(type.getName() + " " + javaClass.getName() + "." + name); + } + + /** + * Gets the class or interface that declares the method, field or constructor represented by {@code member}. + */ + public static Class getDeclaringClass(AccessibleObject member) { + if (member instanceof Method) { + final Method method = (Method) member; + return method.getDeclaringClass(); + } + if (member instanceof Field) { + final Field field = (Field) member; + return field.getDeclaringClass(); + } + assert member instanceof Constructor; + final Constructor constructor = (Constructor) member; + return constructor.getDeclaringClass(); + } + + /** + * Get hold of a non-public inner class. + */ + public static Class getInnerClass(Class outerClass, String innerClassSimpleName) { + for (Class innerClass : outerClass.getDeclaredClasses()) { + if (innerClass.getSimpleName().equals(innerClassSimpleName)) { + return innerClass; + } + } + return null; + } + + /** + * Extracts a package name from a fully qualified class name. + * + * @return "" if {@code className} denotes a class in the unnamed package + */ + public static String getPackageName(String className) { + final int index = className.lastIndexOf('.'); + if (index < 0) { + return ""; + } + return className.substring(0, index); + } + + /** + * Extracts a simple class name from a fully qualified class name. + */ + public static String getSimpleName(String className) { + final int index = className.lastIndexOf('.'); + if (index < 0) { + return className; + } + return className.substring(index + 1); + } + + /** + * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for anonymous and local + * classes. + * + * @param clazz the class for which the simple name is being requested + * @param withEnclosingClass specifies if the returned name should be qualified with the name(s) of the enclosing + * class/classes of {@code clazz} (if any). This option is ignored if {@code clazz} denotes an anonymous + * or local class. + * @return + */ + public static String getSimpleName(Class clazz, boolean withEnclosingClass) { + final String simpleName = clazz.getSimpleName(); + if (simpleName.length() != 0) { + if (withEnclosingClass) { + String prefix = ""; + Class enclosingClass = clazz; + while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) { + prefix = prefix + enclosingClass.getSimpleName() + "."; + } + return prefix + simpleName; + } + return simpleName; + } + // Must be an anonymous or local class + final String name = clazz.getName(); + int index = name.indexOf('$'); + if (index == -1) { + return name; + } + index = name.lastIndexOf('.', index); + if (index == -1) { + return name; + } + return name.substring(index + 1); + } + + /** + * Similar to {@link Class#getDeclaredMethod(String, Class...)} except that + * the search takes into account the return type. + */ + public static Method getDeclaredMethod(Class clazz, Class returnType, String name, Class... parameterTypes) throws NoSuchMethodError { + for (Method javaMethod : clazz.getDeclaredMethods()) { + if (javaMethod.getName().equals(name) && javaMethod.getReturnType().equals(returnType)) { + final Class[] declaredParameterTypes = javaMethod.getParameterTypes(); + if (java.util.Arrays.equals(declaredParameterTypes, parameterTypes)) { + return javaMethod; + } + } + } + throw new NoSuchMethodError(returnType.getName() + " " + clazz.getName() + "." + name + "(" + Utils.toString(parameterTypes, ",") + ")"); + } + + /** + * A wrapper for a call to {@link Class#getDeclaredMethod(String, Class...)} that must succeed. + */ + public static Method getDeclaredMethod(Class clazz, String name, Class... parameterTypes) { + try { + return clazz.getDeclaredMethod(name, parameterTypes); + } catch (NoSuchMethodException noSuchMethodException) { + throw (NoSuchMethodError) new NoSuchMethodError(clazz.getName() + "." + name + "(" + Utils.toString(parameterTypes, ",") + ")").initCause(noSuchMethodException); + } + } + + /** + * A wrapper for a call to {@link Class#getDeclaredConstructor(Class...)} that must succeed. + */ + public static Constructor getDeclaredConstructor(Class clazz, Class... parameterTypes) { + try { + return clazz.getDeclaredConstructor(parameterTypes); + } catch (NoSuchMethodException noSuchMethodException) { + throw (NoSuchMethodError) new NoSuchMethodError(clazz.getName() + "(" + Utils.toString(parameterTypes, ",") + ")").initCause(noSuchMethodException); + } + } + + /** + * A wrapper for a call to {@link Class#getDeclaredField(String)} that must succeed. + */ + public static Field getDeclaredField(Class clazz, String name) { + try { + return clazz.getDeclaredField(name); + } catch (NoSuchFieldException noSuchFieldException) { + throw (NoSuchFieldError) new NoSuchFieldError(clazz.getName() + "." + name).initCause(noSuchFieldException); + } + } + + /** + * Similar to {@link Class#getDeclaredField(String)} except that the lookup takes into account a given field type. + */ + public static Field getDeclaredField(Class clazz, String name, Class type) throws NoSuchFieldError { + for (Field field : clazz.getDeclaredFields()) { + if (field.getName().equals(name) && field.getType().equals(type)) { + return field; + } + } + throw new NoSuchFieldError(type.getName() + " " + clazz.getName() + "." + name); + } + + public static void main(Class classToRun, String[] args) { + try { + final Method mainMethod = classToRun.getMethod("main", String[].class); + mainMethod.invoke(null, (Object) args); + } catch (Exception e) { + throw (Error) new Error().initCause(e); + } + } + + public static void main(String classToRun, String[] args) { + main(forName(classToRun), args); + } + +} diff --git a/JavaInJava/src/com/sun/max/lang/Endianness.java b/JavaInJava/src/com/sun/max/lang/Endianness.java new file mode 100644 index 0000000..6192538 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Endianness.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.io.*; +import java.nio.*; + +/** + * Enumerated type with values for the most common more ways to arrange bits, bytes, etc. + * + * @author Bernd Mathiske + */ +public enum Endianness { + + LITTLE { + @Override + public short readShort(InputStream stream) throws IOException { + final int low = readByte(stream) & 0xff; + final int high = readByte(stream); + return (short) ((high << 8) | low); + } + + @Override + public int readInt(InputStream stream) throws IOException { + final int low = readShort(stream) & 0xffff; + final int high = readShort(stream); + return (high << 16) | low; + } + + @Override + public long readLong(InputStream stream) throws IOException { + final long low = readInt(stream) & 0xffffffffL; + final long high = readInt(stream); + return (high << 32) | low; + } + + @Override + public void writeShort(OutputStream stream, short value) throws IOException { + short v = value; + stream.write(v & 0xff); + v >>= 8; + stream.write(v & 0xff); + } + + @Override + public void writeInt(OutputStream stream, int value) throws IOException { + int v = value; + stream.write(v & 0xff); + v >>= 8; + stream.write(v & 0xff); + v >>= 8; + stream.write(v & 0xff); + v >>= 8; + stream.write(v & 0xff); + } + + @Override + public void writeLong(OutputStream stream, long value) throws IOException { + long v = value; + stream.write((int) v & 0xff); + v >>= 8; + stream.write((int) v & 0xff); + v >>= 8; + stream.write((int) v & 0xff); + v >>= 8; + stream.write((int) v & 0xff); + v >>= 8; + stream.write((int) v & 0xff); + v >>= 8; + stream.write((int) v & 0xff); + v >>= 8; + stream.write((int) v & 0xff); + v >>= 8; + stream.write((int) v & 0xff); + } + + @Override + public byte[] toBytes(short value) { + short v = value; + final byte[] bytes = new byte[2]; + bytes[0] = (byte) (v & 0xff); + v >>= 8; + bytes[1] = (byte) (v & 0xff); + return bytes; + } + + @Override + public byte[] toBytes(int value) { + int v = value; + final byte[] bytes = new byte[4]; + bytes[0] = (byte) (v & 0xff); + v >>= 8; + bytes[1] = (byte) (v & 0xff); + v >>= 8; + bytes[2] = (byte) (v & 0xff); + v >>= 8; + bytes[3] = (byte) (v & 0xff); + return bytes; + } + + @Override + public byte[] toBytes(long value) { + long v = value; + final byte[] bytes = new byte[8]; + bytes[0] = (byte) (v & 0xff); + v >>= 8; + bytes[1] = (byte) (v & 0xff); + v >>= 8; + bytes[2] = (byte) (v & 0xff); + v >>= 8; + bytes[3] = (byte) (v & 0xff); + v >>= 8; + bytes[4] = (byte) (v & 0xff); + v >>= 8; + bytes[5] = (byte) (v & 0xff); + v >>= 8; + bytes[6] = (byte) (v & 0xff); + v >>= 8; + bytes[7] = (byte) (v & 0xff); + return bytes; + } + + @Override + public void toBytes(short value, byte[] result, int offset) { + short v = value; + for (int i = 0; i < Shorts.SIZE && i < result.length; i++) { + result[i + offset] = (byte) (v & 0xff); + v >>= 8; + } + } + + @Override + public void toBytes(int value, byte[] result, int offset) { + int v = value; + for (int i = 0; i < Ints.SIZE && i < result.length; i++) { + result[i + offset] = (byte) (v & 0xff); + v >>= 8; + } + } + + @Override + public void toBytes(long value, byte[] result, int offset) { + long v = value; + for (int i = 0; i < Longs.SIZE && i < result.length; i++) { + result[i + offset] = (byte) (v & 0xff); + v >>= 8; + } + } + + @Override + public int offsetWithinWord(WordWidth wordWidth, WordWidth dataWidth) { + return 0; + } + + @Override + public ByteOrder asByteOrder() { + return ByteOrder.LITTLE_ENDIAN; + } + }, + BIG { + @Override + public short readShort(InputStream stream) throws IOException { + final int high = readByte(stream); + final int low = readByte(stream) & 0xff; + return (short) ((high << 8) | low); + } + + @Override + public int readInt(InputStream stream) throws IOException { + final int high = readShort(stream); + final int low = readShort(stream) & 0xffff; + return (high << 16) | low; + } + + @Override + public long readLong(InputStream stream) throws IOException { + final long high = readInt(stream); + final long low = readInt(stream) & 0xffffffffL; + return (high << 32) | low; + } + + @Override + public void writeShort(OutputStream stream, short value) throws IOException { + stream.write((value >> 8) & 0xff); + stream.write(value & 0xff); + } + + @Override + public void writeInt(OutputStream stream, int value) throws IOException { + stream.write((value >> 24) & 0xff); + stream.write((value >> 16) & 0xff); + stream.write((value >> 8) & 0xff); + stream.write(value & 0xff); + } + + @Override + public void writeLong(OutputStream stream, long value) throws IOException { + stream.write((int) (value >> 56) & 0xff); + stream.write((int) (value >> 48) & 0xff); + stream.write((int) (value >> 40) & 0xff); + stream.write((int) (value >> 32) & 0xff); + stream.write((int) (value >> 24) & 0xff); + stream.write((int) (value >> 16) & 0xff); + stream.write((int) (value >> 8) & 0xff); + stream.write((int) value & 0xff); + } + + @Override + public byte[] toBytes(short value) { + short v = value; + final byte[] bytes = new byte[2]; + bytes[1] = (byte) (v & 0xff); + v >>= 8; + bytes[0] = (byte) (v & 0xff); + return bytes; + } + + @Override + public byte[] toBytes(int value) { + int v = value; + final byte[] bytes = new byte[4]; + bytes[3] = (byte) (v & 0xff); + v >>= 8; + bytes[2] = (byte) (v & 0xff); + v >>= 8; + bytes[1] = (byte) (v & 0xff); + v >>= 8; + bytes[0] = (byte) (v & 0xff); + return bytes; + } + + @Override + public byte[] toBytes(long value) { + long v = value; + final byte[] bytes = new byte[8]; + bytes[7] = (byte) (v & 0xff); + v >>= 8; + bytes[6] = (byte) (v & 0xff); + v >>= 8; + bytes[5] = (byte) (v & 0xff); + v >>= 8; + bytes[4] = (byte) (v & 0xff); + v >>= 8; + bytes[3] = (byte) (v & 0xff); + v >>= 8; + bytes[2] = (byte) (v & 0xff); + v >>= 8; + bytes[1] = (byte) (v & 0xff); + v >>= 8; + bytes[0] = (byte) (v & 0xff); + return bytes; + } + + @Override + public void toBytes(short value, byte[] result, int offset) { + short v = value; + int toIndex = offset + Shorts.SIZE - 1; + for (int i = 1; i <= Shorts.SIZE && i <= result.length; i++) { + result[toIndex--] = (byte) (v & 0xff); + v >>= 8; + } + } + + @Override + public void toBytes(int value, byte[] result, int offset) { + int v = value; + int toIndex = offset + Ints.SIZE - 1; + for (int i = 1; i <= Ints.SIZE && i <= result.length; i++) { + result[toIndex--] = (byte) (v & 0xff); + v >>= 8; + } + } + + @Override + public void toBytes(long value, byte[] result, int offset) { + long v = value; + int toIndex = offset + Longs.SIZE - 1; + for (int i = 1; i <= Longs.SIZE && i <= result.length; i++) { + result[toIndex--] = (byte) (v & 0xff); + v >>= 8; + } + } + + @Override + public int offsetWithinWord(WordWidth wordWidth, WordWidth dataWidth) { + assert wordWidth.numberOfBytes >= dataWidth.numberOfBytes; + return wordWidth.numberOfBytes - dataWidth.numberOfBytes; + } + + @Override + public ByteOrder asByteOrder() { + return ByteOrder.BIG_ENDIAN; + } + }; + + @Override + public String toString() { + return name().toLowerCase(); + } + + public byte readByte(InputStream stream) throws IOException { + final int result = stream.read(); + if (result < 0) { + throw new IOException(); + } + return (byte) result; + } + + public abstract short readShort(InputStream stream) throws IOException; + + public abstract int readInt(InputStream stream) throws IOException; + + public abstract long readLong(InputStream stream) throws IOException; + + public abstract void writeShort(OutputStream stream, short value) throws IOException; + + public abstract void writeInt(OutputStream stream, int value) throws IOException; + + public abstract void writeLong(OutputStream stream, long value) throws IOException; + + public byte[] toBytes(byte value) { + final byte[] bytes = new byte[1]; + bytes[0] = value; + return bytes; + } + + public abstract byte[] toBytes(short value); + + public abstract byte[] toBytes(int value); + + public abstract byte[] toBytes(long value); + + public void toBytes(byte value, byte[] result, int offset) { + if (result.length > 0) { + result[0] = value; + } + } + + public abstract void toBytes(short value, byte[] result, int offset); + + public abstract void toBytes(int value, byte[] result, int offset); + + public abstract void toBytes(long value, byte[] result, int offset); + + public abstract int offsetWithinWord(WordWidth wordWith, WordWidth dataWidth); + + public abstract ByteOrder asByteOrder(); +} diff --git a/JavaInJava/src/com/sun/max/lang/Function.java b/JavaInJava/src/com/sun/max/lang/Function.java new file mode 100644 index 0000000..b6c44e9 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Function.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.util.concurrent.*; + +/** + * Creates a function wrapper for a method that returns a value and may throw a checked exception. + * This interface extends {@link Callable} so that {@code Function}s can be used with an {@link ExecutorService}. + * + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public interface Function extends Callable { + + /** + * Computes a result, or throws an exception if unable to do so. + * + * @return computed result (which will be {@code null} if {@code Result_Type} is {@link Void}) + * @throws Exception if unable to compute a result + */ + T call() throws Exception; + +} diff --git a/JavaInJava/src/com/sun/max/lang/Ints.java b/JavaInJava/src/com/sun/max/lang/Ints.java new file mode 100644 index 0000000..a746847 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Ints.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import com.sun.max.annotate.*; +import com.sun.max.util.*; + +/** + * Additional methods that one might want in java.lang.Integer + * and int array stuff. + * + * @author Bernd Mathiske + * @author Paul Caprioli + */ +public final class Ints { + + // Utility classes should not be instantiated. + private Ints() { + } + + public static final int SIZE = 4; + public static final int WIDTH = 32; + + public static final Range VALUE_RANGE = new Range(Integer.MIN_VALUE, Integer.MAX_VALUE); + + public static final int K = 1024; + public static final int M = K * K; + + public static int compare(int greater, int lesser) { + if (greater > lesser) { + return 1; + } + if (greater == lesser) { + return 0; + } + return -1; + } + + public static int numberOfEffectiveSignedBits(int signed) { + if (signed >= 0) { + return 33 - Integer.numberOfLeadingZeros(signed); + } + return 33 - Integer.numberOfLeadingZeros(~signed); + } + + public static int numberOfEffectiveUnsignedBits(int unsigned) { + return 32 - Integer.numberOfLeadingZeros(unsigned); + } + + /** + * Returns an integer with all the bits in its two's complement binary representation that are at index {@code + * highestBitIndex} or lower set to 1. + * + * @param highestBitIndex the index of the highest bit to be set in the returned value. Only the low 5 bits of {@code + * highestBitIndex} are used. That is, if {@code highestBitIndex > 31} or {@code highestBitIndex < 0} then + * the highest bit to be set is given by {@code highestBitSet & 0x1F}. + */ + public static int lowBitsSet(int highestBitIndex) { + final int n = highestBitIndex & 0x1f; + return (1 << n) | ((1 << n) - 1); + } + + /** + * Returns an integer with all the bits in its two's complement binary representation that are at index {@code + * lowestBitIndex} or higher set to 1. + * + * @param lowestBitIndex the index of the lowest bit to be set in the returned value. Only the low 5 bits of {@code + * lowestBitIndex} are used. That is, if {@code lowestBitIndex > 31} or {@code lowestBitIndex < 0} then + * the lowest bit to be set is given by {@code lowestBitSet & 0x1F}. + */ + public static int highBitsSet(int lowestBitIndex) { + return ~((1 << lowestBitIndex) - 1); + } + + /** + * Determines if a given number is zero or a power of two. + */ + public static boolean isPowerOfTwoOrZero(int n) { + return Integer.lowestOneBit(n) == n; + } + + public static int log2(int n) { + if (n <= 0) { + throw new ArithmeticException(); + } + return 31 - Integer.numberOfLeadingZeros(n); + } + + public static int roundUp(int value, int by) { + final int rest = value % by; + if (rest == 0) { + return value; + } + if (value < 0) { + return value - rest; + } + return value + (by - rest); + } + + /** + * Calculates an unsigned integer which is greater than or equal to {@code value} and + * is a multiple of {@code by}. Results are undefined if {@code by} is not + * a power of two. + * @param value the unsigned integer which is to be rounded upwards. + * @param by a positive power of two. + * @return the unsigned integer calculated by rounding upwards to a multiple of {@code by}. + */ + @INLINE + public static int roundUnsignedUpByPowerOfTwo(int value, int by) { + assert isPowerOfTwoOrZero(by); + final int mask = by - 1; + return (value + mask) & ~mask; + } + + /** + * Returns the hexadecimal string representation of the given value with at least 8 digits, e.g. 0x0000CAFE. + */ + public static String toHexLiteral(int value) { + return "0x" + toPaddedHexString(value, '0'); + } + + /** + * Returns the given value as a hexadecimal number with at least 8 digits, e.g. 0000CAFE. + */ + public static String toPaddedHexString(int n, char pad) { + final String s = Integer.toHexString(n).toUpperCase(); + return Strings.times(pad, 8 - s.length()) + s; + } + + public static boolean contains(int[] array, int value) { + for (int element : array) { + if (element == value) { + return true; + } + } + return false; + } + + public static int[] append(int[] array, int element) { + final int resultLength = array.length + 1; + final int[] result = new int[resultLength]; + System.arraycopy(array, 0, result, 0, array.length); + result[array.length] = element; + return result; + } + + public static int[] append(int[] head, int[] tail) { + final int[] result = new int[head.length + tail.length]; + System.arraycopy(head, 0, result, 0, head.length); + System.arraycopy(tail, 0, result, head.length, tail.length); + return result; + } + + public static int[] createRange(int first, int last) { + if (first > last) { + throw new IllegalArgumentException(); + } + final int n = last + 1 - first; + final int[] result = new int[n]; + for (int i = 0; i < n; i++) { + result[i] = first + i; + } + return result; + } + + public static void copyAll(int[] fromArray, int[] toArray) { + for (int i = 0; i < fromArray.length; i++) { + toArray[i] = fromArray[i]; + } + } + + /** + * Returns a string representation of the contents of the specified array. + * Adjacent elements are separated by the specified separator. Elements are + * converted to strings as by String.valueOf(int). + * + * @param array the array whose string representation to return + * @param separator the separator to use + * @return a string representation of array + * @throws NullPointerException if {@code array} or {@code separator} is null + */ + public static String toString(int[] array, String separator) { + if (array == null || separator == null) { + throw new NullPointerException(); + } + if (array.length == 0) { + return ""; + } + + final StringBuilder buf = new StringBuilder(); + buf.append(array[0]); + + for (int i = 1; i < array.length; i++) { + buf.append(separator); + buf.append(array[i]); + } + + return buf.toString(); + } + + private static final int [] sizeBase10Table = { + 9, + 99, + 999, + 9999, + 99999, + 999999, + 9999999, + 99999999, + 999999999, Integer.MAX_VALUE + }; + + /** + * Computes the numbers of characters in the base-10 string representation of a given integer, including the '-' + * prefix for a negative integer. That is, this method computes the length of the String returned by + * {@link Integer#toString(int)} without requiring a String object to be created. + * + * @param i an integer + * @return the length of the string that would be returned by calling {@link Integer#toString(int)} with {@code i} + * as the argument + */ + public static int sizeOfBase10String(int x) { + if (x == Integer.MIN_VALUE) { + return "-2147483648".length(); + } + final int posX = x < 0 ? -x : x; + for (int i = 0;; i++) { + if (posX <= sizeBase10Table[i]) { + if (x < 0) { + return i + 2; + } + return i + 1; + } + } + } + + /** + * @see Longs#toUnitsString(long, boolean) + */ + public static String toUnitsString(long number, boolean onlyPowerOfTwo) { + return Longs.toUnitsString(number, onlyPowerOfTwo); + } + + /** + * Computes the minimum value in an array of integers. + * + * @param ints the array of integers from which the minimum is computed. This array must have at least one element. + * @return the minimum value in {@code ints} + * @throws ArrayIndexOutOfBoundsException if {@code ints.length == 0} + */ + public static int min(int[] ints) { + int min = ints[0]; + for (int n : ints) { + if (n < min) { + min = n; + } + } + return min; + } + + /** + * Computes the maximum value in an array of integers. + * + * @param ints the array of integers from which the maximum is computed. This array must have at least one element. + * @return the maximum value in {@code ints} + * @throws ArrayIndexOutOfBoundsException if {@code ints.length == 0} + */ + public static int max(int[] ints) { + int max = ints[0]; + for (int n : ints) { + if (n > max) { + max = n; + } + } + return max; + } + +} diff --git a/JavaInJava/src/com/sun/max/lang/Longs.java b/JavaInJava/src/com/sun/max/lang/Longs.java new file mode 100644 index 0000000..26533fe --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Longs.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +/** + * Additional methods that one might want in java.lang.Long. + * + * @author Bernd Mathiske + */ +public final class Longs { + + private Longs() { + } + + public static final int SIZE = 8; + public static final int WIDTH = 64; + + public static final long INT_MASK = 0xffffffffL; + + public static int compare(long greater, long lesser) { + if (greater > lesser) { + return 1; + } + if (greater == lesser) { + return 0; + } + return -1; + } + + public static int numberOfEffectiveSignedBits(long signed) { + if (signed >= 0) { + return 65 - Long.numberOfLeadingZeros(signed); + } + return 65 - Long.numberOfLeadingZeros(~signed); + } + + public static int numberOfEffectiveUnsignedBits(long unsigned) { + return 64 - Long.numberOfLeadingZeros(unsigned); + } + + public static byte getByte(long value, int index) { + return (byte) ((value >> (index * 8)) & 0xffL); + } + + public static String toPaddedHexString(long n, char pad) { + final String s = Long.toHexString(n); + return Strings.times(pad, 16 - s.length()) + s; + } + + /** + * Determines if a given number is zero or a power of two. + */ + public static boolean isPowerOfTwoOrZero(long n) { + return Long.lowestOneBit(n) == n; + } + + public static final long K = 1024; + public static final long M = K * K; + public static final long G = M * K; + public static final long T = G * K; + public static final long P = T * K; + + /** + * Converts a positive number to a string using unit suffixes to reduce the + * number of digits to three or less using base 2 for sizes. + * + * @param number the number to convert to a string + * @param onlyPowerOfTwo if {@code true}, then a unit suffix is only used if {@code number} is an exact power of 2 + */ + public static String toUnitsString(long number, boolean onlyPowerOfTwo) { + if (number < 0) { + throw new IllegalArgumentException(String.valueOf(number)); + } + if (onlyPowerOfTwo && !isPowerOfTwoOrZero(number)) { + return String.valueOf(number); + } + if (number >= P) { + return number / P + "P"; + } + if (number >= T) { + return number / T + "T"; + } + if (number >= G) { + return number / G + "G"; + } + if (number >= M) { + return number / M + "M"; + } + if (number >= K) { + return number / K + "K"; + } + return Long.toString(number); + } + + /** + * Parse a size specification nX, where X := {K, M, G, T, P, k, m, g, t, p}. + * + * @param value a string containing a long number that can be parsed by {@link Long#parseLong(String)} followed by + * an optional scaling character + * @return the scaled value + * @throws NumberFormatException if {@code value} does not contain a parsable {@code long} or has an invalid scale + * suffix + */ + public static long parseScaledValue(String value) throws NumberFormatException { + char lastChar = value.charAt(value.length() - 1); + if (!Character.isDigit(lastChar)) { + long result = Long.parseLong(value.substring(0, value.length() - 1)); + switch (lastChar) { + case 'K': + case 'k': { + return result * Longs.K; + } + case 'M': + case 'm': { + return result * Longs.M; + } + case 'G': + case 'g': { + return result * Longs.G; + } + case 'T': + case 't': { + return result * Longs.T; + } + case 'P': + case 'p': { + return result * Longs.P; + } + default: { + throw new NumberFormatException("Number with unknown scale suffix: " + value); + } + } + } + return Long.parseLong(value); + } +} diff --git a/JavaInJava/src/com/sun/max/lang/MutableInnerClassGlobal.java b/JavaInJava/src/com/sun/max/lang/MutableInnerClassGlobal.java new file mode 100644 index 0000000..1ebc933 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/MutableInnerClassGlobal.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +/** + * Globals to inner classes must be final, so we need to box them somehow + * if we want them to have a mutable global. + * + * @author Bernd Mathiske + */ +public class MutableInnerClassGlobal { + + private T value; + + public T value() { + return value; + } + + public MutableInnerClassGlobal() { + } + + public MutableInnerClassGlobal(T value) { + this.value = value; + } + + public void setValue(T value) { + this.value = value; + } + +} diff --git a/JavaInJava/src/com/sun/max/lang/Package.java b/JavaInJava/src/com/sun/max/lang/Package.java new file mode 100644 index 0000000..bc31413 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import com.sun.max.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/lang/Procedure.java b/JavaInJava/src/com/sun/max/lang/Procedure.java new file mode 100644 index 0000000..e2696ca --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Procedure.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +/** + * @author Bernd Mathiske + */ +public interface Procedure { + + void run(T argument); + +} diff --git a/JavaInJava/src/com/sun/max/lang/Shorts.java b/JavaInJava/src/com/sun/max/lang/Shorts.java new file mode 100644 index 0000000..1a335fa --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Shorts.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import com.sun.max.util.*; + +/** + * @author Bernd Mathiske + */ +public final class Shorts { + + private Shorts() { + } + + public static final int SIZE = 2; + public static final int WIDTH = 16; + public static final int MASK = 0xffff; + + public static final Range VALUE_RANGE = new Range(Short.MIN_VALUE, Short.MAX_VALUE); +} diff --git a/JavaInJava/src/com/sun/max/lang/StaticFieldLiteral.java b/JavaInJava/src/com/sun/max/lang/StaticFieldLiteral.java new file mode 100644 index 0000000..76e26a4 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/StaticFieldLiteral.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.lang.reflect.*; + +import com.sun.max.program.*; + +public interface StaticFieldLiteral { + + String literal(); + + void setLiteral(String literal); + + Class literalClass(); + + void setLiteralClass(Class literalClass); + + public static final class Static { + + private Static() { + } + + public static void initialize(Class staticFieldLiteralClass) { + for (Field field : staticFieldLiteralClass.getDeclaredFields()) { + if ((field.getModifiers() & Modifier.STATIC) != 0 && StaticFieldLiteral.class.isAssignableFrom(field.getType())) { + field.setAccessible(true); + try { + final StaticFieldLiteral staticFieldLiteral = (StaticFieldLiteral) field.get(staticFieldLiteralClass); + staticFieldLiteral.setLiteral(field.getName()); + staticFieldLiteral.setLiteralClass(staticFieldLiteralClass); + } catch (IllegalAccessException illegalAccessException) { + ProgramError.unexpected("could not name literal of field: " + field); + } + } + } + } + } + +} diff --git a/JavaInJava/src/com/sun/max/lang/StaticFieldName.java b/JavaInJava/src/com/sun/max/lang/StaticFieldName.java new file mode 100644 index 0000000..d0cb9d4 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/StaticFieldName.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.lang.reflect.*; +import java.util.*; + +import com.sun.max.program.*; + +public interface StaticFieldName { + + String name(); + + void setName(String name); + + public interface StringFunction { + String function(String string); + } + + public interface Procedure { + void procedure(StaticFieldName staticFieldName); + } + + public static final class Static { + + private Static() { + } + + public static List initialize(Class staticNameFieldClass, StringFunction stringFunction, Procedure procedure) { + final List sequence = new LinkedList(); + for (Field field : staticNameFieldClass.getDeclaredFields()) { + if ((field.getModifiers() & Modifier.STATIC) != 0 && StaticFieldName.class.isAssignableFrom(field.getType())) { + field.setAccessible(true); + try { + final StaticFieldName value = (StaticFieldName) field.get(null); + if (value.name() == null) { + String name = field.getName(); + if (stringFunction != null) { + name = stringFunction.function(name); + } + value.setName(name); + } + if (procedure != null) { + procedure.procedure(value); + } + sequence.add(value); + } catch (IllegalAccessException illegalAccessException) { + ProgramError.unexpected("could not name value of field: " + field); + } + } + } + return sequence; + } + + public static List initialize(Class staticNameFieldClass, StringFunction stringFunction) { + return initialize(staticNameFieldClass, stringFunction, null); + } + + public static List initialize(Class staticNameFieldClass, Procedure procedure) { + return initialize(staticNameFieldClass, null, procedure); + } + + public static List initialize(Class staticNameFieldClass) { + return initialize(staticNameFieldClass, null, null); + } + } + +} diff --git a/JavaInJava/src/com/sun/max/lang/Strings.java b/JavaInJava/src/com/sun/max/lang/Strings.java new file mode 100644 index 0000000..37a585c --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/Strings.java @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.io.*; +import java.util.*; + +/** + * Additional String-related operations. + * + * @author Bernd Mathiske + */ +public final class Strings { + + private Strings() { + } + + /** + * @param stream + * the input stream to be read in its entirety and then closed + * @return the contents of the input stream as a String, with line breaks + * @throws IOException + * as usual + */ + public static String fromInputStream(InputStream stream) throws IOException { + final BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + final StringBuffer result = new StringBuffer(); + final String lineSeparator = System.getProperty("line.separator"); + while (true) { + final String line = reader.readLine(); + if (line == null) { + stream.close(); + return result.toString(); + } + result.append(line); + result.append(lineSeparator); + } + } + + public static String firstCharToLowerCase(String s) { + if (s == null || s.length() == 0) { + return s; + } + return s.substring(0, 1).toLowerCase() + s.substring(1); + } + + public static String firstCharToUpperCase(String s) { + if (s == null || s.length() == 0) { + return s; + } + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + + public static String times(char ch, int nTimes) { + if (nTimes <= 0) { + return ""; + } + final char[] chars = new char[nTimes]; + for (int i = 0; i < nTimes; i++) { + chars[i] = ch; + } + return new String(chars); + } + + private static final char[] SPACES; + static { + SPACES = new char[200]; + java.util.Arrays.fill(SPACES, ' '); + } + + public static String spaces(int nSpaces) { + if (nSpaces <= 0) { + return ""; + } + if (nSpaces <= SPACES.length) { + return new String(SPACES, 0, nSpaces); + } + return times(' ', nSpaces); + } + + /** + * @return The String {@code s} padded out to {@code length}, if needed, by appending space characters + */ + public static String padLengthWithSpaces(String s, int length) { + if (s.length() >= length) { + return s; + } + return s + spaces(length - s.length()); + } + + /** + * @return The string {@code s} padded out to {@code length}, if needed, by prepending space characters + */ + public static String padLengthWithSpaces(int length, String s) { + if (s.length() >= length) { + return s; + } + return spaces(length - s.length()) + s; + } + + private static final char[] ZEROES; + static { + ZEROES = new char[200]; + java.util.Arrays.fill(ZEROES, '0'); + } + + public static String zeroes(int nZeroes) { + if (nZeroes <= 0) { + return ""; + } + if (nZeroes <= ZEROES.length) { + return new String(ZEROES, 0, nZeroes); + } + return times(' ', nZeroes); + } + + /** + * @return The String {@code s} padded out to {@code length}, if needed, by appending zero characters + */ + public static String padLengthWithZeroes(String s, int length) { + if (s.length() >= length) { + return s; + } + return s + zeroes(length - s.length()); + } + + /** + * @return The string {@code s} padded out to {@code length}, if needed, by prepending zero characters + */ + public static String padLengthWithZeroes(int length, String s) { + if (s.length() >= length) { + return s; + } + return zeroes(length - s.length()) + s; + } + + /** + * Finds the index of the first non-escaped instance of {@code c} in {@code s} starting at {@code fromIndex}. + * The search takes into account that the escape char (i.e. {@code '\'}) may itself be escaped. + * + * @return -1 if the char could not be found + */ + public static int indexOfNonEscapedChar(char c, String s, int fromIndex) { + int index = s.indexOf(c, fromIndex); + while (index != -1) { + if (index > 0 && (s.charAt(index - 1) != '\\') || (index > 1 && s.charAt(index - 2) == '\\')) { + return index; + } + index = s.indexOf(c, index + 1); + } + return -1; + } + + /** + * Parses a command line into a string array appropriate for calling {@link Runtime#exec(String[])}. + * The given command line is tokenized around {@link Character#isWhitespace(char) whitespaces} + * except for sequences of characters enclosed in non-escaped double quotes (after the double + * quotes are removed). + */ + public static String[] splitCommand(String command) { + final List parts = new ArrayList(); + + boolean escapedChar = false; + boolean insideQuotes = false; + + final char[] buffer = new char[command.length()]; + int pos = 0; + + for (int index = 0; index < command.length(); ++index) { + final char ch = command.charAt(index); + if (escapedChar) { + escapedChar = false; + } else { + if (ch == '\\') { + escapedChar = true; + } else { + if (insideQuotes) { + if (ch == '"') { + insideQuotes = false; + continue; + } + } else { + if (ch == '"') { + insideQuotes = true; + continue; + } else if (Character.isWhitespace(ch)) { + if (pos != 0) { + parts.add(new String(buffer, 0, pos)); + pos = 0; + } + continue; + + } + } + } + } + buffer[pos++] = ch; + } + + if (insideQuotes) { + throw new IllegalArgumentException("unclosed quotes"); + } + if (escapedChar) { + throw new IllegalArgumentException("command line cannot end with escape char '\\'"); + } + if (pos != 0) { + parts.add(new String(buffer, 0, pos)); + } + return parts.toArray(new String[parts.size()]); + } + + public static String truncate(String s, int maxLength) { + if (maxLength < 0) { + throw new IllegalArgumentException(); + } + if (s.length() <= maxLength) { + return s; + } + return s.substring(0, maxLength) + "..."; + } + + /** + * Capitalizes the first character in a given string. + * + * @param string the string to process + * @param lowercaseTail if true, the remaining characters in {@code string} are converted to lower case + */ + public static String capitalizeFirst(String string, boolean lowercaseTail) { + final String tail = string.substring(1); + return Character.toUpperCase(string.charAt(0)) + (lowercaseTail ? tail.toLowerCase() : tail); + } + + /** + * Chops the last {@code count} from a given string. + * + * @param s the string to chop + * @param count the number of characters to chop from the end of {@code s} + * @return the chopped string + * @throws IndexOutOfBoundsException if {@code count < 0} or {@code count > s.length()} + */ + public static String chopSuffix(String s, int count) { + return s.substring(0, s.length() - count); + } + + /** + * Chops the last {@code suffix.length()} from a given string. Calling this method is + * equivalent to {@link #chopSuffix(String, int) chop(s, suffix.length())}. + */ + public static String chopSuffix(String s, String suffix) { + return chopSuffix(s, suffix.length()); + } + + /** + * Prepends {@code n} space characters to every line in String {@code lines}, + * including a possibly non-empty line following the final newline. + * Returns {@code lines} if {@code spaces <= 0} + */ + public static String indent(String lines, int spaces) { + return indent(lines, spaces(spaces)); + } + + /** + * Prepends the String {@code indentation} to every line in String {@code lines}, + * including a possibly non-empty line following the final newline. + */ + public static String indent(String lines, String indentation) { + if (lines.length() == 0) { + return lines; + } + final String newLine = "\n"; + if (lines.endsWith(newLine)) { + return indentation + (lines.substring(0, lines.length() - 1)).replace(newLine, newLine + indentation) + newLine; + } + return indentation + lines.replace(newLine, newLine + indentation); + } + + public static String formatParagraphs(String s, int leftJust, int pindent, int width) { + final int len = s.length(); + int indent = pindent; + indent += leftJust; + int consumed = indent + leftJust; + final String indstr = space(indent); + final String ljstr = space(leftJust); + final StringBuffer buf = new StringBuffer(s.length() + 50); + buf.append(indstr); + int lastSp = -1; + for (int cntr = 0; cntr < len; cntr++) { + final char c = s.charAt(cntr); + if (c == '\n') { + buf.append('\n'); + consumed = indent; + buf.append(indstr); + continue; + } else if (Character.isWhitespace(c)) { + lastSp = buf.length(); + } + buf.append(c); + consumed++; + + if (consumed > width) { + if (lastSp >= 0) { + buf.setCharAt(lastSp, '\n'); + buf.insert(lastSp + 1, ljstr); + consumed = buf.length() - lastSp + leftJust - 1; + } + } + } + return buf.toString(); + } + + protected static final String[] spacers = { + "", // 0 + " ", // 1 + " ", // 2 + " ", // 3 + " ", // 4 + " ", // 5 + " ", // 6 + " ", // 7 + " ", // 8 + " ", // 9 + " ", // 10 + }; + + public static void appendFract(StringBuffer buf, double val, int digits) { + int cntr = 0; + for (int radix = 10; cntr < digits; radix = radix * 10, cntr++) { + if (cntr == 0) { + buf.append('.'); + } + final int digit = (int) (val * radix) % 10; + buf.append((char) (digit + '0')); + } + } + + public static String fixedDouble(double fval, int places) { + if (Double.isInfinite(fval)) { + return "(inf)"; + } + if (Double.isNaN(fval)) { + return "(NaN)"; + } + + final StringBuffer buf = new StringBuffer(places + 5); + // append the whole part + final long val = (long) fval; + buf.append(val); + // append the fractional part + final double fract = fval >= 0 ? fval - val : val - fval; + appendFract(buf, fract, places); + + return buf.toString(); + } + + public static String space(int len) { + if (len <= 0) { + return ""; + } + if (len < spacers.length) { + return spacers[len]; + } + return times(' ', len); + } + + public static void space(StringBuffer buf, int len) { + int i = 0; + while (i++ < len) { + buf.append(' '); + } + } + + public static String concat(String first, String second, String separator) { + if (!first.isEmpty()) { + return first + separator + second; + } + return second; + } + +} diff --git a/JavaInJava/src/com/sun/max/lang/WordWidth.java b/JavaInJava/src/com/sun/max/lang/WordWidth.java new file mode 100644 index 0000000..86c4c88 --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/WordWidth.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.lang; + +import java.util.*; + +/** + * A word width value describes how many bits there are in a machine word. + * + * @author Bernd Mathiske + */ +public enum WordWidth { + + BITS_8(8, byte.class, Byte.MIN_VALUE, Byte.MAX_VALUE, 3), + BITS_16(16, short.class, Short.MIN_VALUE, Short.MAX_VALUE, 4), + BITS_32(32, int.class, Integer.MIN_VALUE, Integer.MAX_VALUE, 5), + BITS_64(64, long.class, Long.MIN_VALUE, Long.MAX_VALUE, 6); + + public static final List VALUES = java.util.Arrays.asList(values()); + + /** + * Number of bits in a Word. + * This must be a positive power of two. + */ + public final int numberOfBits; + + /** + * Log2 of the number of bits. + */ + public final int log2numberOfBits; + + /** + * Log2 of the number of bytes. + */ + public final int log2numberOfBytes; + + /** + * Number of bytes in a Word. + * This must be a positive power of two. + */ + public final int numberOfBytes; + + public final Class canonicalPrimitiveType; + public final long min; + public final long max; + + private WordWidth(int numberOfBits, Class canonicalPrimitiveType, long min, long max, int log2numberOfBits) { + this.numberOfBits = numberOfBits; + this.numberOfBytes = numberOfBits / 8; + this.canonicalPrimitiveType = canonicalPrimitiveType; + this.min = min; + this.max = max; + this.log2numberOfBits = log2numberOfBits; + this.log2numberOfBytes = log2numberOfBits - 3; + } + + public boolean lessThan(WordWidth other) { + return numberOfBits < other.numberOfBits; + } + + public boolean lessEqual(WordWidth other) { + return numberOfBits <= other.numberOfBits; + } + + public boolean greaterThan(WordWidth other) { + return numberOfBits > other.numberOfBits; + } + + public boolean greaterEqual(WordWidth other) { + return numberOfBits >= other.numberOfBits; + } + + @Override + public String toString() { + return Integer.toString(numberOfBits); + } + + public static WordWidth fromInt(int wordWidth) { + if (wordWidth <= 8) { + return WordWidth.BITS_8; + } + if (wordWidth <= 16) { + return WordWidth.BITS_16; + } + if (wordWidth <= 32) { + return WordWidth.BITS_32; + } + return WordWidth.BITS_64; + } + + /** + * @return which word width is minimally required to represent all the non-one bits in the signed argument, and a sign bit + */ + public static WordWidth signedEffective(int signed) { + return fromInt(Ints.numberOfEffectiveSignedBits(signed)); + } + + /** + * @return which word width is minimally required to represent all the non-zero bits in the unsigned argument + */ + public static WordWidth unsignedEffective(int unsigned) { + return fromInt(Ints.numberOfEffectiveUnsignedBits(unsigned)); + } + + /** + * @return which word width is minimally required to represent all the non-one bits in the signed argument, and a sign bit + */ + public static WordWidth signedEffective(long signed) { + return fromInt(Longs.numberOfEffectiveSignedBits(signed)); + } + + /** + * @return which word width is minimally required to represent all the non-zero bits in the unsigned argument + */ + public static WordWidth unsignedEffective(long unsigned) { + return fromInt(Longs.numberOfEffectiveUnsignedBits(unsigned)); + } +} diff --git a/JavaInJava/src/com/sun/max/lang/package-info.java b/JavaInJava/src/com/sun/max/lang/package-info.java new file mode 100644 index 0000000..fc2ee2f --- /dev/null +++ b/JavaInJava/src/com/sun/max/lang/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * Supplementing java.lang. + * + * @author Bernd Mathiske + */ +package com.sun.max.lang; diff --git a/JavaInJava/src/com/sun/max/package-info.java b/JavaInJava/src/com/sun/max/package-info.java new file mode 100644 index 0000000..a1ac5be --- /dev/null +++ b/JavaInJava/src/com/sun/max/package-info.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * Project Maxine software + * + * The top level package contains classes that provide package info manipulation operations. + * + * @author Bernd Mathiske + */ +package com.sun.max; diff --git a/JavaInJava/src/com/sun/max/program/ClassSearch.java b/JavaInJava/src/com/sun/max/program/ClassSearch.java new file mode 100644 index 0000000..bfb2e9b --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/ClassSearch.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + +import com.sun.max.lang.*; + +/** + * Provides a facility for finding classes reachable on a given {@linkplain Classpath classpath}. + * + * @author Doug Simon + */ +public class ClassSearch extends ClasspathTraversal { + + private final HashSet classes; + + public ClassSearch() { + this(false); + } + + /** + * Creates a class search object. + * + * @param omitDuplicates if true, then each argument passed to {@link #visitClass(String)} is guaranteed to be unique. + */ + public ClassSearch(boolean omitDuplicates) { + if (omitDuplicates) { + classes = new HashSet(); + } else { + classes = null; + } + } + + /** + * Handles a class file encountered during the traversal. + * + * @param className + * the name of the class denoted by the class file + * @return true if the traversal should continue, false if it should terminate + */ + protected boolean visitClass(String className) { + return true; + } + + /** + * Handles a class file encountered during the traversal. Unless this object was initialized to omit duplicates, + * this method may be called more than once for the same class as class files are not guaranteed to be unique in a + * classpath. + * + * @param isArchiveEntry true if the class is in a .zip or .jar file, false if it is a file in a directory + * @param className the name of the class denoted by the class file + * @return true if the traversal should continue, false if it should terminate + */ + protected boolean visitClass(boolean isArchiveEntry, String className) { + if (classes != null) { + if (classes.contains(className)) { + return true; + } + classes.add(className); + } + return visitClass(className); + } + + protected boolean visit(boolean isArchiveEntry, String dottifiedResource) { + if (dottifiedResource.endsWith(".class")) { + final String className = Strings.chopSuffix(dottifiedResource, ".class"); + return visitClass(isArchiveEntry, className); + } + return true; + } + + @Override + protected boolean visitArchiveEntry(ZipFile archive, ZipEntry resource) { + return visit(true, resource.getName().replace('/', '.')); + } + + @Override + protected boolean visitFile(File parent, String resource) { + return visit(false, resource.replace(File.separatorChar, '.')); + } +} diff --git a/JavaInJava/src/com/sun/max/program/Classpath.java b/JavaInJava/src/com/sun/max/program/Classpath.java new file mode 100755 index 0000000..c909a93 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/Classpath.java @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + +import com.sun.max.io.*; + +/** + * @author Bernd Mathiske + * @author Doug Simon + */ +public class Classpath { + + private static final List EMPTY_LIST = Collections.emptyList(); + + public static final Classpath EMPTY = new Classpath(EMPTY_LIST); + + private final List entries; + + private final Map classpathFileMap = new HashMap(); + + /** + * An entry in a classpath is a file system path that denotes an existing {@linkplain Directory directory}, + * an existing {@linkplain Archive zip/jar} file or a {@linkplain PlainFile neither}. + */ + public abstract static class Entry { + + /** + * Gets the string representing the underlying path of this entry. + */ + public final String path() { + return file().getPath(); + } + + /** + * Gets the File object representing the underlying path of this entry. + */ + public abstract File file(); + + /** + * Gets the contents of a file denoted by a given path that is relative to this classpath entry. If the denoted + * file does not exist under this classpath entry then {@code null} is returned. Any IO exception that occurs + * when reading is silently ignored. + * + * @param path a file path relative to this classpath entry. This values uses the '/' character as the path + * separator regardless of the {@linkplain File#separatorChar default} for the underlying platform. + */ + abstract ClasspathFile readFile(String path); + + public boolean isDirectory() { + return false; + } + + public boolean isArchive() { + return false; + } + + public boolean isPlainFile() { + return false; + } + + @Override + public String toString() { + return path(); + } + + public ZipFile zipFile() { + return null; + } + } + + /** + * Represents a classpath entry that is neither an existing directory nor an existing zip/jar archive file. + */ + static final class PlainFile extends Entry { + + private final File file; + + public PlainFile(File file) { + this.file = file; + } + + @Override + ClasspathFile readFile(String path) { + return null; + } + + @Override + public File file() { + return file; + } + + @Override + public boolean isPlainFile() { + return true; + } + } + + /** + * Represents a classpath entry that is a path to an existing directory. + */ + static final class Directory extends Entry { + private final File directory; + + public Directory(File directory) { + this.directory = directory; + } + + @Override + ClasspathFile readFile(String path) { + final File file = new File(directory, File.separatorChar == '/' ? path : path.replace('/', File.separatorChar)); + if (file.exists()) { + try { + return new ClasspathFile(Files.toBytes(file), this); + } catch (IOException ioException) { + ProgramWarning.message("Error reading from " + file + ": " + ioException); + return null; + } + } + return null; + } + + @Override + public File file() { + return directory; + } + + @Override + public boolean isDirectory() { + return true; + } + } + + /** + * Represents a classpath entry that is a path to an existing zip/jar archive file. + */ + static final class Archive extends Entry { + + private final File file; + private ZipFile zipFile; + + public Archive(File file) { + this.file = file; + } + + @Override + public ZipFile zipFile() { + if (zipFile == null && file != null) { + try { + zipFile = new ZipFile(file); + } catch (IOException e) { + ProgramWarning.message("Error opening ZIP file: " + file.getPath()); + e.printStackTrace(); + } + } + return zipFile; + } + + @Override + ClasspathFile readFile(String path) { + final ZipFile zf = zipFile(); + if (zf == null) { + return null; + } + try { + final ZipEntry zipEntry = zf.getEntry(path); + if (zipEntry != null) { + return new ClasspathFile(readZipEntry(zf, zipEntry), this); + } + } catch (IOException ioException) { + //ProgramWarning.message("could not read ZIP file: " + file); + } + return null; + } + + @Override + public File file() { + return file; + } + + @Override + public boolean isArchive() { + return true; + } + } + + /** + * Gets the ordered entries from which this classpath is composed. + * + * @return a sequence of {@code Entry} objects + */ + public List entries() { + return entries; + } + + /** + * Creates a classpath {@link Entry} from a given file system path. + * + * @param path a file system path denoting a classpath entry + */ + public static Entry createEntry(String path) { + final File pathFile = new File(path); + if (pathFile.isDirectory()) { + return new Directory(pathFile); + } else if (path.endsWith(".zip") || path.endsWith(".jar")) { + if (pathFile.exists() && pathFile.isFile()) { + return new Archive(pathFile); + } + } + //ProgramWarning.message("Class path entry is neither a directory nor a JAR file: " + path); + return new PlainFile(pathFile); + } + + /** + * Creates a new classpath from an array of classpath entries. + * + * @param paths an array of classpath entries + */ + public Classpath(String[] paths) { + final Entry[] entryArray = new Entry[paths.length]; + for (int i = 0; i < paths.length; ++i) { + final String path = paths[i]; + entryArray[i] = createEntry(path); + } + this.entries = Arrays.asList(entryArray); + } + + /** + * Creates a new classpath from a sequence of classpath entries. + * + * @param paths a sequence of classpath entries + */ + public Classpath(List entries) { + this.entries = entries; + } + + /** + * Creates a new classpath by parsing a string of classpath entries separated by the system dependent + * {@linkplain File#pathSeparator path separator}. + * + * @param paths a string of classpath entries separated by ':' or ';' + */ + public Classpath(String paths) { + this(paths.split(File.pathSeparator)); + } + + /** + * Gets the classpath derived from the value of the {@code "java.ext.dirs"} system property. + * + * @see "http://java.sun.com/javase/6/docs/technotes/guides/extensions/extensions.html" + */ + private static String extensionClasspath() { + final String extDirs = System.getProperty("java.ext.dirs"); + if (extDirs != null) { + final StringBuilder buf = new StringBuilder(); + for (String extDirPath : extDirs.split(File.pathSeparator)) { + final File extDir = new File(extDirPath); + if (extDir.isDirectory()) { + for (File file : extDir.listFiles()) { + if (file.isDirectory() || + (file.isFile() && (file.getName().endsWith(".jar") || file.getName().endsWith(".zip")))) { + if (buf.length() != 0) { + buf.append(File.pathSeparatorChar); + } + buf.append(file.getAbsolutePath()); + } + } + } else { + // Ignore non-directory + } + } + if (buf.length() != 0) { + buf.append(File.pathSeparatorChar); + return buf.toString(); + } + } + return ""; + } + + /** + * Gets a classpath corresponding to the class search order used by the application class loader. + */ + public static Classpath fromSystem() { + final String value = System.getProperty("sun.boot.class.path") + File.pathSeparator + extensionClasspath() + System.getProperty("java.class.path"); + return new Classpath(value.split(File.pathSeparator)); + } + + /** + * Gets a classpath corresponding to the class search order used by the boot class loader. + */ + public static Classpath bootClassPath() { + final String value = System.getProperty("sun.boot.class.path"); + if (value == null) { + return EMPTY; + } + return new Classpath(value.split(File.pathSeparator)); + } + + /** + * Gets a new classpath obtained by prepending a given classpath to this class classpath. + * + * @param classpath the classpath to prepend to this classpath + * @return the result of prepending {@code classpath} to this classpath + */ + public Classpath prepend(Classpath classpath) { + ArrayList entries = new ArrayList(this.entries.size() + classpath.entries.size()); + entries.addAll(classpath.entries); + entries.addAll(this.entries); + return new Classpath(entries); + } + + /** + * Gets a new classpath obtained by prepending a given classpath to this class classpath. + * + * @param classpath the classpath to prepend to this classpath + * @return the result of prepending {@code classpath} to this classpath + */ + public Classpath prepend(String path) { + ArrayList entries = new ArrayList(this.entries.size()); + entries.add(createEntry(path)); + entries.addAll(this.entries); + return new Classpath(entries); + } + + /** + * Searches for a class file denoted by a given class name on this classpath and returns its contents in a byte array if + * found. Any IO exception that occurs when reading is silently ignored. + * + * @param className a fully qualified class name (e.g. "java.lang.Class") + * @return the contents of the file available on the classpath whose name is computed as + * {@code className.replace('.', '/')}. If no such file is available on this class path or if + * reading the file produces an IO exception, then null is returned. + */ + public ClasspathFile readClassFile(String className) { + return readFile(className, ".class"); + } + + /** + * Searches for a file denoted by a given class name on this classpath and returns its contents in a byte array if + * found. Any IO exception that occurs when reading is silently ignored. + * + * @param className a fully qualified class name (e.g. "java.lang.Class") + * @param extension a file extension + * @return the contents of the file available on the classpath whose name is computed as + * {@code className.replace('.', '/') + extension}. If no such file is available on this class path or if + * reading the file produces an IO exception, then null is returned. + */ + public ClasspathFile readFile(String className, String extension) { + final String path = className.replace('.', '/') + extension; + for (Entry entry : entries()) { + ClasspathFile classpathFile = null; + classpathFile = entry.readFile(path); + if (classpathFile != null) { + recordPackage(className, classpathFile); + return classpathFile; + } + } + return null; + } + + private void recordPackage(String className, ClasspathFile classpathFile) { + final int ix = className.lastIndexOf('.'); + final String packageName = ix < 0 ? "/" : className.substring(0, ix + 1).replace('.', '/'); + if (!classpathFileMap.containsKey(packageName)) { + classpathFileMap.put(packageName, classpathFile); + } + } + + /** + * Searches for an existing file corresponding to an directory entry in this classpath composed with a given path + * suffix. + * + * @param suffix a file path relative to a directory entry of this classpath + * @return a file corresponding to the {@linkplain File#File(File, String) composition} of the first directory entry + * of this classpath with {@code suffix} that denotes an existing file or null if so such file exists + */ + public File findFile(String suffix) { + for (Entry entry : entries()) { + if (entry instanceof Directory) { + final File file = new File(((Directory) entry).directory, suffix); + if (file.exists()) { + return file; + } + } + } + return null; + } + + public static byte[] readZipEntry(ZipFile zipFile, ZipEntry zipEntry) throws IOException { + final byte[] bytes = new byte[(int) zipEntry.getSize()]; + final InputStream zipStream = new BufferedInputStream(zipFile.getInputStream(zipEntry), bytes.length); + try { + int offset = 0; + while (offset < bytes.length) { + final int n = zipStream.read(bytes, offset, bytes.length - offset); + if (n <= 0) { + //ProgramWarning.message("truncated ZIP file: " + zipFile); + } + offset += n; + } + } finally { + zipStream.close(); + } + return bytes; + } + + @Override + public String toString() { + if (entries == null || entries.isEmpty()) { + return ""; + } + String s = entries.toString().replace(", ", File.pathSeparator); + return s.substring(1, s.length() - 1); + } + + public ClasspathFile classpathFileForPackage(String name) { + return classpathFileMap.get(name); + } + + /** + * Converts this object to a String array with one array element for each classpath entry. + * + * @return the newly created String array with one element per classpath entry + */ + public String[] toStringArray() { + final String[] result = new String[entries().size()]; + int z = 0; + for (Classpath.Entry e : entries()) { + result[z] = e.path(); + z++; + } + return result; + } +} diff --git a/JavaInJava/src/com/sun/max/program/ClasspathFile.java b/JavaInJava/src/com/sun/max/program/ClasspathFile.java new file mode 100644 index 0000000..495e740 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/ClasspathFile.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +import com.sun.max.program.Classpath.*; + +/** + * Encapulates the contents of a file loaded from an {@linkplain Entry entry} on a {@linkplain Classpath classpath}. + * + * @author Doug Simon + */ +public final class ClasspathFile { + + /** + * The bytes of the file represented by this object. + */ + public final byte[] contents; + + /** + * The classpath entry from which the file represented by this object was read. + */ + public final Entry classpathEntry; + + /** + * Creates an object encapsulating the bytes of a file read via a classpath entry. + * + * @param contents the bytes of the file that was read + * @param classpathEntry the entry from which the file was read + */ + public ClasspathFile(byte[] contents, Entry classpathEntry) { + this.classpathEntry = classpathEntry; + this.contents = contents; + } +} diff --git a/JavaInJava/src/com/sun/max/program/ClasspathTraversal.java b/JavaInJava/src/com/sun/max/program/ClasspathTraversal.java new file mode 100644 index 0000000..071e671 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/ClasspathTraversal.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + +import com.sun.max.io.*; +import com.sun.max.program.Classpath.*; + +/** + * Provides a facility for processing all the resources reachable on a given {@linkplain Classpath classpath}. + * + * @author Doug Simon + */ +public class ClasspathTraversal { + + /** + * Handles a standard file resource encountered during the traversal. + * + * @param parent the classpath directory entry under which the resource is located + * @param resource the path of the resource relative to {@code parent}. The + * {@linkplain File#separatorChar platform specific} character is used as the path separator in this + * value. + * @return true if the traversal should continue, false if it should terminate + */ + protected boolean visitFile(File parent, String resource) { + return true; + } + + /** + * Handles an archive entry resource encountered during the traversal. + * + * @param archive the classpath .zip or .jar entry in which the resource is located + * @param resource the archive entry holding the resource + * @return true if the traversal should continue, false if it should terminate + */ + protected boolean visitArchiveEntry(ZipFile archive, ZipEntry resource) { + return true; + } + + /** + * Traverses all the resources reachable on a given classpath. + * + * @param classpath the classpath to search + */ + public void run(final Classpath classpath) { + run(classpath, null); + } + + /** + * Traverses all the resources reachable on a given classpath. + * + * @param classpath the classpath to search + * @param resourcePrefixFilter if non-null, then only resources whose name begins with this value are traversed. The + * '/' character must be used in this value as the path separator regardless of the + * {@linkplain File#separatorChar default} for the underlying platform. + */ + public void run(final Classpath classpath, String resourcePrefixFilter) { + for (final Entry entry : classpath.entries()) { + if (entry.isDirectory()) { + final String prefix = entry.path() + File.separator; + final File startFile; + if (resourcePrefixFilter == null) { + startFile = entry.file(); + } else { + if (File.separatorChar != '/') { + startFile = new File(entry.file(), resourcePrefixFilter.replace('/', File.separatorChar)); + } else { + startFile = new File(entry.file(), resourcePrefixFilter); + } + } + + final FileTraversal fileTraversal = new FileTraversal() { + @Override + protected void visitFile(File file) { + final String path = file.getPath(); + assert path.startsWith(prefix); + final String resource = path.substring(prefix.length()); + if (!ClasspathTraversal.this.visitFile(entry.file(), resource)) { + stop(); + } + } + }; + fileTraversal.run(startFile); + if (fileTraversal.wasStopped()) { + return; + } + } else if (entry.isArchive()) { + final ZipFile zipFile = entry.zipFile(); + if (zipFile != null) { + for (final Enumeration e = zipFile.entries(); e.hasMoreElements();) { + final ZipEntry zipEntry = e.nextElement(); + if (resourcePrefixFilter == null || zipEntry.getName().startsWith(resourcePrefixFilter)) { + if (!visitArchiveEntry(zipFile, zipEntry)) { + return; + } + } + } + } + } + } + } +} diff --git a/JavaInJava/src/com/sun/max/program/Package.java b/JavaInJava/src/com/sun/max/program/Package.java new file mode 100755 index 0000000..fa2a430 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +import com.sun.max.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/program/ProgramError.java b/JavaInJava/src/com/sun/max/program/ProgramError.java new file mode 100755 index 0000000..e21f653 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/ProgramError.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +/** + * A collection of static methods for reporting errors indicating some fatal condition. + * In the target VM, these errors can be made to perform a hard exit of the VM by + * redirecting them via a {@linkplain #setHandler(Handler) registered} error handler. + * + * @author Bernd Mathiske + * @author Paul Caprioli + * @author Doug Simon + * @author Michael Van De Vanter + */ + +public final class ProgramError extends Error { + + /** + * Implemented by a client that can {@linkplain ProgramError#setHandler(Handler) register} + * itself to handle program errors instead of having them result in a {@link ProgramError} + * instance raised. + */ + public static interface Handler { + + /** + * Handles a given error condition. This method should never return normally. + * + * @param message a message describing the error condition. This value may be {@code null} + * @param throwable an exception given more detail on the cause of the error condition. This value may be {@code null} + */ + void handle(String message, Throwable throwable); + } + + /** + * Registers a handler to which error reporting is redirected. Any previously registered handler + * is overwritten and discarded. + * + * @param h if non-null, this object's {@link Handler#handle(String, Throwable)} method is messaged instead of + * raising a ProgramError. + */ + public static void setHandler(Handler h) { + handler = h; + } + + private ProgramError(String message, Throwable cause) { + super(message, cause); + } + + /** + * Checks a given condition and if it's {@code false}, the appropriate error handling action is taken. + * The message reported to this action is {@code "Program Error"}. + * + * @param condition a condition to test + */ + public static void check(boolean condition) { + if (!condition) { + unexpected(null, null); + } + } + + /** + * Checks a given condition and if it's {@code false}, the appropriate error handling action is taken. + * + * @param condition a condition to test + * @param message a message describing the error condition being tested + */ + public static void check(boolean condition, String message) { + if (!condition) { + unexpected(message, null); + } + } + + /** + * Checks a given condition and if it's {@code false}, the appropriate error handling action is taken. + * + * @param condition a condition to test + * @param message a message describing the error condition being tested + * @param object an object whose string description is to be appended to the message + */ + public static void check(boolean condition, String message, Object object) { + if (!condition) { + unexpected(message + object.toString(), null); + } + } + + /** + * Reports the occurrence of some error condition triggering the appropriate error handling action + * to be taken. By default, this action is to raise a {@link ProgramError} exception. However, + * if an alternative error handler has been {@linkplain #setHandler(Handler) registered}, its + * {@link Handler#handle(String, Throwable)} method is called instead. + * + * This method never returns normally. + * + * @param message a message describing the error condition. This value may be {@code null}. + * @param throwable an exception given more detail on the cause of the error condition. This value may be {@code null}. + */ + public static ProgramError unexpected(String message, Throwable throwable) { + if (handler != null) { + handler.handle(message, throwable); + } + if (message == null) { + throw new ProgramError("Unexpected Program Error:", throwable); + } + throw new ProgramError("Unexpected Program Error: " + message, throwable); + } + + /** + * Reports the occurrence of some error condition. + * + * This method never returns normally. + * + * @param message a message describing the error condition. This value may be {@code null}. + * @see #unexpected(String, Throwable) + */ + public static ProgramError unexpected(String message) { + throw unexpected(message, null); + } + + /** + * Reports the occurrence of some error condition. + * + * This method never returns normally. + * + * @param throwable an exception given more detail on the cause of the error condition. This value may be {@code null} + * @see #unexpected(String, Throwable) + */ + public static ProgramError unexpected(Throwable throwable) { + throw unexpected(null, throwable); + } + + /** + * Reports the occurrence of some error condition. + * + * This method never returns normally. + * + * @param throwable an exception given more detail on the cause of the error condition. This value may be {@code null} + * @see #unexpected(String, Throwable) + */ + public static ProgramError unexpected() { + throw unexpected((String) null); + } + + /** + * Reports that a {@code switch} statement encountered a {@code case} value it was not expecting. + * + * This method never returns normally. + * + * @see #unexpected(String, Throwable) + */ + public static ProgramError unknownCase() { + throw unexpected("unknown switch case"); + } + + /** + * Reports that a {@code switch} statement encountered a {@code case} value it was not expecting. + * + * This method never returns normally. + * + * @param caseValue the unexpected {@code case} value as a string + * @see #unexpected(String, Throwable) + */ + public static ProgramError unknownCase(String caseValue) { + throw unexpected("unknown switch case: " + caseValue); + } + + // Checkstyle: stop + private static Handler handler = null; +} diff --git a/JavaInJava/src/com/sun/max/program/ProgramWarning.java b/JavaInJava/src/com/sun/max/program/ProgramWarning.java new file mode 100755 index 0000000..5a7a3bf --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/ProgramWarning.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +/** + * A collection of static methods for reporting a warning when an unexpected, non-fatal condition is encountered. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public final class ProgramWarning { + + /** + * Implemented by a client that can {@linkplain ProgramWarning#setHandler(Handler) register} + * itself to handle program warnings instead of having them printed to {@link System#err}. + */ + public static interface Handler { + + /** + * Handles display a given warning message. + * + * @param message a warning message + */ + void handle(String message); + } + + /** + * Registers a handler to which warnings are redirected. Any previously registered handler + * is overwritten and discarded. + * + * @param h if non-null, this object's {@link Handler#handle(String)} method is messaged instead of + * printing the warning to {@link System#err} a ProgramError. + */ + public static void setHandler(Handler h) { + handler = h; + } + + private static Handler handler; + + private ProgramWarning() { + } + + /** + * Prints a given warning message. + * + * @param warning the warning message to print + */ + public static void message(String warning) { + if (handler != null) { + handler.handle(warning); + } else { + System.err.println("WARNING: " + warning); + } + } + + /** + * Checks a given condition and if it's {@code false}, the appropriate warning message is printed. + * + * @param condition a condition to test + * @param message the warning message to be printed if {@code condition == false} + */ + public static void check(boolean condition, String warning) { + if (!condition) { + message(warning); + } + } +} diff --git a/JavaInJava/src/com/sun/max/program/Trace.java b/JavaInJava/src/com/sun/max/program/Trace.java new file mode 100755 index 0000000..90200bc --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/Trace.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program; + +import java.io.*; + +import com.sun.max.annotate.*; +import com.sun.max.io.*; +import com.sun.max.program.option.*; + +/** + * Tracing output for debugging purposes. No performance impact when disabled. Some performance impact when active, even + * without output. Possibly significant performance impact when producing a lot of output. + * + * @author Bernd Mathiske + */ +public final class Trace { + + private Trace() { + // do nothing. + } + + private static PrintStream stream; + + public static PrintStream stream() { + return stream; + } + + public static void setStream(PrintStream stream) { + Trace.stream = stream; + } + + private static final boolean showThread; + + static { + showThread = System.getProperty("max.trace.showThread") != null; + final String traceFileName = System.getProperty("max.trace.file"); + stream = System.out; + if (traceFileName != null) { + final File traceFile = new File(traceFileName); + try { + final OutputStream fileStream = new BufferedOutputStream(new FileOutputStream(traceFile)); + if (System.getProperty("max.trace.noconsole") != null) { + stream = new PrintStream(fileStream); + } else { + stream = new PrintStream(new MultiOutputStream(fileStream, System.out)); + } + } catch (IOException ioException) { + System.err.println("Could not open file for trace output: " + traceFile.getAbsolutePath()); + } + } + } + + /** + * Static master switch. Set by source code editing only (for now). + * + * Set '_enabled' to 'true' to enable tracing output, according to your other trace-related settings. + * + * Set '_enabled' to 'false' to prevent any tracing. All tracing routines will thus become dead code. The optimizing + * compiler should then be able to eliminate the runtime overhead. + */ + private static final boolean ENABLED = true; + + public static void addTo(OptionSet options) { + options.addOption(new Option("trace", 0, OptionTypes.INT_TYPE, "Sets tracing level.") { + @Override + public void setValue(Integer value) { + super.setValue(value); + level = value; + } + }); + } + + /** + * Dynamically sets tracing level, causing trace commands at this or lower levels to produce output. + */ + public static void on(int newLevel) { + assert newLevel >= 0; + level = newLevel; + } + + /** + * Dynamically turns tracing on for all levels. + */ + public static void on() { + on(Integer.MAX_VALUE); + } + + @RESET + private static long count; + + /** + * The threshold of trace calls before traces are actually sent to the trace stream. + * + * This field can be updated by the inspector. + */ + @RESET + @INSPECTED + private static long threshold; + + /** + * The current trace level. + * + * This field can be updated by the inspector. + */ + @RESET + @INSPECTED + private static int level; + + /** + * Dynamically sets the current tracing level to the greater of the current level or the specified new level. + */ + public static void atLeast(int l) { + if (l > level) { + level = l; + } + } + + /** + * Dynamically turns tracing off by setting current level to zero. + */ + public static void off() { + level = 0; + } + + /** + * @return current tracing level, which must equal or exceed the level specified by trace commands for output to be produced. + */ + public static int level() { + return level; + } + + /** + * Does the current tracing level equal or exceed the specified level. + */ + public static boolean hasLevel(int requiredLevel) { + count++; + return level >= requiredLevel && count >= threshold; + } + + private static final int MAX_INDENTATION = 10; + + @RESET + private static int indentation; + + private static void printInt(int n) { + if (n < 10) { + stream.write(((char) n) + '0'); + } else { + final int m = n / 10; + printInt(m); + printInt(n - (m * 10)); + } + } + + /** + * This should not cause allocation/GC. + */ + private static void printPrefix(int requiredLevel) { + if (showThread) { + stream.print(Thread.currentThread().getName() + " "); + for (int i = 0; i < indentation; i++) { + stream.print(" "); + } + } + + /** + * Prints a newline on trace output if tracing is globally enabled and current tracing level is at least the level required. + */ + public static void line(int requiredLevel) { + if (ENABLED) { + if (hasLevel(requiredLevel)) { + stream.println(); + stream.flush(); + } + } + } + + /** + * Prints a line of trace output if tracing is globally enabled and if current tracing level is at least the level required. + */ + public static void line(int requiredLevel, Object message) { + if (ENABLED) { + if (hasLevel(requiredLevel)) { + printPrefix(requiredLevel); + stream.println(message); + stream.flush(); + } + } + } + + /** + * Prints a "BEGIN" line of trace output if tracing is globally enabled and if current tracing level is at least the level required; increases indentation. + */ + public static void begin(int requiredLevel, Object message) { + if (ENABLED) { + if (hasLevel(requiredLevel)) { + printPrefix(requiredLevel); + stream.print("BEGIN: "); + stream.println(message); + stream.flush(); + indentation++; + } + } + } + + /** + * Prints an "END" line of trace output if tracing is globally enabled and if current tracing level is at least the level required; decreases indentation. + */ + public static void end(int requiredLevel, Object message) { + end(requiredLevel, message, 0); + } + + /** + * Prints an "END" line of trace output if tracing is globally enabled and if current tracing level is at least the level required; decreases indentation; + * appends a timing message, expressed in milliseconds, if a non-zero starting time is supplied. + * @param requiredLevel + * @param message + * @param startTimeMillis a starting time, output from {@link System#currentTimeMillis()}; no timing message appears if zero. + */ + public static void end(int requiredLevel, Object message, long startTimeMillis) { + if (ENABLED) { + if (hasLevel(requiredLevel)) { + final long endTimeMillis = System.currentTimeMillis(); + indentation--; + // It's quite possible for indentation to go negative in a multithreaded environment + //assert _indentation >= 0; + printPrefix(requiredLevel); + stream.print("END: "); + if (startTimeMillis > 0) { + stream.print(message); + stream.print(" ("); + stream.print(endTimeMillis - startTimeMillis); + stream.println("ms)"); + } else { + stream.println(message); + stream.flush(); + } + } + } + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/FieldOption.java b/JavaInJava/src/com/sun/max/program/option/FieldOption.java new file mode 100644 index 0000000..3401538 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/FieldOption.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option; + +import com.sun.max.*; +import com.sun.max.program.ProgramError; + +import java.lang.reflect.Field; + +/** + * This class implements a command line option that stores its value in a field + * via reflection. + * + * @author Ben L. Titzer + */ +public class FieldOption extends Option { + + protected final Object object; + protected final Field field; + protected T nullValue; + + public FieldOption(String name, Object object, Field field, T defaultValue, Type type, String help) { + super(name, defaultValue, type, help); + this.object = object; + this.field = field; + this.nullValue = defaultValue; + } + + /** + * Gets the value of this option. This implementation stores the field's value in a reflected field + * and access requires a reflective access. + * @return the value of this option + */ + @Override + public T getValue() { + try { + return Utils.cast(field.get(object)); + } catch (IllegalAccessException e) { + throw ProgramError.unexpected(e); + } + } + + /** + * Sets the value of this option. This implementation stores the field's value in a reflected field + * and thus setting the value requires a reflective access. + * @param value the value to set the new value to + */ + @Override + public void setValue(T value) { + try { + if (value == null) { + field.set(object, nullValue); + } else { + field.set(object, value); + } + } catch (Exception e) { + throw ProgramError.unexpected("Error updating the value of " + field, e); + } + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/MaxPackageOptionType.java b/JavaInJava/src/com/sun/max/program/option/MaxPackageOptionType.java new file mode 100644 index 0000000..78ec5a3 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/MaxPackageOptionType.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option; + +import com.sun.max.*; + +/** + * The {@code MaxPackageOptionType} class. + * Created Nov 20, 2007 + * + * @author Ben L. Titzer + */ +public class MaxPackageOptionType extends Option.Type { + public final MaxPackage superPackage; + public final Class classType; + + public MaxPackageOptionType(MaxPackage superPackage, Class classType) { + super(MaxPackage.class, "vm-package"); + this.superPackage = superPackage; + this.classType = classType; + } + @Override + public MaxPackage parseValue(String string) { + final String fullName = superPackage.name() + "." + string; + if (string != null && string.length() > 0) { + MaxPackage result = MaxPackage.fromName(fullName); + if (result == null) { + result = MaxPackage.fromName(string); + } + if (result == null) { + throw new Option.Error("MaxPackage not found: " + string + " (or " + fullName + ")"); + } + return result; + } + return null; + } + + @Override + public String getValueFormat() { + return ""; + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/Option.java b/JavaInJava/src/com/sun/max/program/option/Option.java new file mode 100644 index 0000000..8cf4beb --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/Option.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option; + +import com.sun.max.*; + +/** + * The {@code Option} class represents a command-line or other configuration + * option with a particular name, type, and description. + * + * @author Ben L. Titzer + */ +public class Option implements Cloneable { + + /** + * The {@code Option.Type} class represents a type for an option. This class + * implements method for parsing and unparsing values from strings. + */ + public abstract static class Type { + protected final String typeName; + public final Class type; + + protected Type(Class type, String typeName) { + this.typeName = typeName; + this.type = type; + } + + public String getTypeName() { + return typeName; + } + + public String unparseValue(T value) { + return String.valueOf(value); + } + + public abstract T parseValue(String string) throws Option.Error; + + public abstract String getValueFormat(); + + public Option cast(Option option) { + return Utils.cast(option); + } + } + + public static class Error extends java.lang.Error { + + public Error(String message) { + super(message); + } + } + + protected final String name; + protected T defaultValue; + protected final Type type; + protected final String help; + protected T value; + + /** + * The constructor for the {@code Option} class creates constructs a new + * option with the specified parameters. + * + * @param name the name of the option as a string + * @param defaultValue the default value of the option + * @param type the type of the option, which is used for parsing and unparsing values + * @param help a help description which is usually used to generate a formatted + * help output + */ + public Option(String name, T defaultValue, Type type, String help) { + this.defaultValue = defaultValue; + this.name = name; + this.type = type; + this.help = help; + value = null; + } + + /** + * The {@code getName()} method returns the name of this option as a string. + * + * @return the name of this option + */ + public String getName() { + return name; + } + + /** + * Sets the default value for this option, + * which is the value that the option retains if no assignment is made. + * + * @param val the default value of the option + */ + public void setDefaultValue(T val) { + defaultValue = val; + } + + /** + * The {@code getDefaultValue()} method returns the default value for this option, + * which is the value that the option retains if no assignment is made. + * + * @return the default value of the option + */ + public T getDefaultValue() { + return defaultValue; + } + + /** + * The {@code getValue()} method retrieves the current value of this option. + * + * @return the current value of this option + */ + public T getValue() { + return !assigned ? defaultValue : value; + } + + private boolean assigned; + + /** + * The {@code setValue()) method sets the value of this option. + * + * @param value the new value to this option + */ + public void setValue(T value) { + assigned = true; + this.value = value; + } + + /** + * The {@code setValue()} method sets the value of this option, given a string value. + * The type of this option is used to determine how to parse the string into a value + * of the appropriate type. Thus this method may potentially throw runtime exceptions + * if parsing fails. + * + * @param string the new value of this option as a string + */ + public void setString(String string) { + setValue(type.parseValue(string)); + } + + /** + * The {@code getType()} method returns the type of this option. + * @return the type of this option. + */ + public Type getType() { + return type; + } + + /** + * The {@code getString()} method retrieves the value of this option as a string. + * The type of this option is used to determine how to unparse the value into a string. + * + * @return the value of this option as a string + */ + public String getString() { + return type.unparseValue(getValue()); + } + + public String getHelp() { + return help; + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/OptionSet.java b/JavaInJava/src/com/sun/max/program/option/OptionSet.java new file mode 100644 index 0000000..1a763b7 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/OptionSet.java @@ -0,0 +1,746 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import com.sun.max.*; +import com.sun.max.lang.*; +import com.sun.max.program.*; +import com.sun.max.program.option.gui.*; + +/** + * The {@code OptionSet} class parses and collects options from the command line and + * configuration files. + * + * @author Ben L. Titzer + */ +public class OptionSet { + /** + * The {@code Syntax} enum allows different options to be parsed differently, + * depending on their usage. + */ + public enum Syntax { + REQUIRES_EQUALS { + @Override + public String getUsage(Option option) { + return "-" + option.getName() + "=" + option.getType().getValueFormat(); + } + }, + EQUALS_OR_BLANK { + @Override + public String getUsage(Option option) { + return "-" + option.getName() + "[=" + option.getType().getValueFormat() + "]"; + } + }, + REQUIRES_BLANK { + @Override + public String getUsage(Option option) { + return "-" + option.getName(); + } + }, + CONSUMES_NEXT { + @Override + public String getUsage(Option option) { + return "-" + option.getName() + " " + option.getType().getValueFormat(); + } + }; + + public abstract String getUsage(Option option); + } + + protected final Map optionMap; + protected final Map optionSyntax; + protected final Map optionValues; + protected final boolean allowUnrecognizedOptions; + + protected static final String[] NO_ARGUMENTS = {}; + + protected String[] arguments = NO_ARGUMENTS; + + /** + * Creates an option set that does not allow unrecognized options to be present when + * {@linkplain #parseArguments(String[]) parsing command line arguments} or + * {@linkplain #loadOptions(OptionSet) loading options from another option set}. + */ + public OptionSet() { + this(false); + } + + /** + * Creates an option set. + * + * @param allowUnrecognizedOptions + * specifies if this option set allows unrecognized options to be present when + * {@linkplain #parseArguments(String[]) parsing command line arguments} or + * {@linkplain #loadOptions(OptionSet) loading options from another option set}. + */ + public OptionSet(boolean allowUnrecognizedOptions) { + optionValues = new HashMap(); + // Using a LinkedHashMap to preserve insertion order when iterating over values + optionMap = new LinkedHashMap(); + optionSyntax = new HashMap(); + this.allowUnrecognizedOptions = allowUnrecognizedOptions; + } + + /** + * Converts this option set into a list of command line arguments, to be used, for example, to pass to an external + * tool. For each option in this set that has been explicitly set this method will prepend an appropriate option + * string of appropriate syntactic form (e.g. "-name=value") to the array of arguments passed. + * + * @return a new array of program arguments that includes these options + */ + public String[] asArguments() { + String[] newArgs = Arrays.copyOf(arguments, arguments.length + optionValues.size()); + int i = 0; + for (String name : optionValues.keySet()) { + final String value = optionValues.get(name); + final Syntax syntax = optionSyntax.get(name); + if (syntax == Syntax.REQUIRES_BLANK) { + newArgs[i++] = "-" + name; + } else if (syntax == Syntax.CONSUMES_NEXT) { + newArgs = Arrays.copyOf(newArgs, newArgs.length + 1); + newArgs[i++] = "-" + name; + newArgs[i++] = value; + } else { + newArgs[i++] = "-" + name + "=" + value; + } + } + return newArgs; + } + + /** + * Gets an option set derived from this option set that contains all the unrecognized options that have been loaded + * or parsed into this option set. The returned option set also includes a copy of the + * {@linkplain #getArguments() non-option arguments} from this option set. + * @return a new option set encapsulating all the arguments and options + */ + public OptionSet getArgumentsAndUnrecognizedOptions() { + final OptionSet argumentsAndUnrecognizedOptions = new OptionSet(true); + for (Map.Entry entry : optionValues.entrySet()) { + if (!optionMap.containsKey(entry.getKey())) { + argumentsAndUnrecognizedOptions.optionValues.put(entry.getKey(), entry.getValue()); + } + } + argumentsAndUnrecognizedOptions.arguments = arguments; + return argumentsAndUnrecognizedOptions; + } + + /** + * Handles an Option.Error raised while loading or parsing values into this option set. + *

+ * This default implementation is to print a usage message and the call {@link System#exit(int)}. + * @param error the error that occurred + * @param optionName the name of the option being parsed + */ + protected void handleErrorDuringParseOrLoad(Option.Error error, String optionName) { + System.out.println("Error parsing option -" + optionName + ": " + error.getMessage()); + printHelp(System.out, 78); + System.exit(1); + } + + /** + * Parses a list of command line arguments, processing the leading options (i.e. arguments that start with '-') + * and returning the "leftover" arguments to the caller. The longest tail of {@code arguments} that starts with a non-option argument can be retrieved after parsing with {@link #getArguments()}. + * + * @param args + * the arguments + * @return this option set + */ + public OptionSet parseArguments(String[] args) { + // parse the options + int i = 0; + for (; i < args.length; i++) { + final String argument = args[i]; + if (argument.charAt(0) == '-') { + // is the beginning of a valid option. + final int index = argument.indexOf('='); + final String optionName = getOptionName(argument, index); + String value = getOptionValue(argument, index); + final Syntax syntax = optionSyntax.get(optionName); + // check the syntax of this option + try { + checkSyntax(optionName, syntax, value); + if (syntax == Syntax.CONSUMES_NEXT) { + value = args[++i]; + } + setValue(optionName, value); + } catch (Option.Error error) { + handleErrorDuringParseOrLoad(error, optionName); + } + } else { + // is not an option, therefore the start of arguments + break; + } + } + + final int left = args.length - i; + arguments = new String[left]; + System.arraycopy(args, i, arguments, 0, left); + + if (System.getProperty("useProgramOptionDialog") != null) { + OptionsDialog.show(null, this); + } + return this; + } + + /** + * The {@code getArguments()} method gets the leftover command line options + * from the last call to {@code parseArguments}. + * + * @return the leftover command line options + */ + public String[] getArguments() { + if (arguments.length == 0) { + return arguments; + } + return Arrays.copyOf(arguments, arguments.length); + } + + /** + * Determines if this option set allows parsing or loading of unrecognized options. + * @return {@code true} if this option set allows unrecognized options + */ + public boolean allowsUnrecognizedOptions() { + return allowUnrecognizedOptions; + } + + /** + * The {@code loadSystemProperties()} method loads the value of the valid + * options from the systems properties with the specified prefix. + * + * @param prefix the prefix of each system property, used to disambiguate + * these options from other system properties. + * @return this option set + */ + public OptionSet loadSystemProperties(String prefix) { + final Properties systemProperties = System.getProperties(); + final Properties properties = new Properties(); + for (String key : systemProperties.stringPropertyNames()) { + if (key.startsWith(prefix)) { + properties.setProperty(key.substring(prefix.length()), systemProperties.getProperty(key)); + } + } + return loadProperties(properties, true); + } + + /** + * The {@code storeSystemProperties()} method stores these option values + * into the system properties. + * + * @param prefix the prefix to append to all option names when inserting them + * into the systems properties + */ + public void storeSystemProperties(String prefix) { + for (Map.Entry entry : optionValues.entrySet()) { + System.setProperty(prefix + entry.getKey(), entry.getValue()); + } + } + + /** + * Loads the specified properties into this set of options. + * + * @param p + * the properties set to load into this set of options + * @param loadall + * true if this method should load all properties in the property set into this option set; false if this + * method should only load properties for options already in this option set + * @return this option set + */ + public OptionSet loadProperties(Properties p, boolean loadall) { + if (loadall) { + // if loadall is specified, load all properties in the set + for (Object object : p.keySet()) { + final String name = (String) object; + final String val = p.getProperty(name); + try { + setValue(name, val); + } catch (Option.Error error) { + handleErrorDuringParseOrLoad(error, name); + } + } + } else { + // if loadall is not specified, only load options that are in this option set. + for (Object o : p.keySet()) { + final String name = (String) o; + if (optionMap.containsKey(name)) { + final String val = p.getProperty(name); + try { + setValue(name, val); + } catch (Option.Error error) { + handleErrorDuringParseOrLoad(error, name); + } + } + } + } + if (System.getProperty("useProgramOptionDialog") != null) { + OptionsDialog.show(null, this); + } + return this; + } + + /** + * The {@code loadFile()} method parses properties from a file and loads them into this set of options. + * + * @param fname + * the filename from while to load the properties + * @param loadall + * true if this method should load all properties in the property set into this option set; false if this + * method should only load properties for options already in this option set + * @return this option set + * @throws java.io.IOException + * if there is a problem opening or reading the file + * @throws Option.Error + * if there is a problem parsing an option + */ + public OptionSet loadFile(String fname, boolean loadall) throws IOException, Option.Error { + final Properties defs = new Properties(); + final FileInputStream stream = new FileInputStream(new File(fname)); + defs.load(stream); + stream.close(); + return loadProperties(defs, loadall); + } + + /** + * Loads a set of options and {@linkplain #getArguments() arguments} from another option set. + * + * @param options the option set from which to load the option values + * @return this option set + */ + public OptionSet loadOptions(OptionSet options) { + for (Map.Entry entry : options.optionValues.entrySet()) { + try { + setValue(entry.getKey(), entry.getValue()); + } catch (Option.Error error) { + handleErrorDuringParseOrLoad(error, entry.getKey()); + } + } + arguments = options.arguments; + + if (System.getProperty("useProgramOptionDialog") != null) { + OptionsDialog.show(null, this); + } + return this; + } + + protected void checkSyntax(String optname, Syntax syntax, String value) { + if (syntax == Syntax.REQUIRES_BLANK && value != null) { + throw new Option.Error("syntax error: \"-" + optname + "\" required"); + } + if (syntax == Syntax.REQUIRES_EQUALS && value == null) { + throw new Option.Error("syntax error: \"-" + optname + "=value\" required"); + } + if (syntax == Syntax.CONSUMES_NEXT && value != null) { + throw new Option.Error("syntax error: \"-" + optname + " value\" required"); + } + } + + protected String getOptionName(String argument, int equalIndex) { + if (equalIndex < 0) { // naked option + return argument.substring(1, argument.length()); + } + return argument.substring(1, equalIndex); + } + + protected String getOptionValue(String argument, int equalIndex) { + if (equalIndex < 0) { // naked option + return null; + } + return argument.substring(equalIndex + 1); + } + + /** + * Adds the options of an {@link OptionSet} to this set. + * @param optionSet the set of options to add + */ + public void addOptions(OptionSet optionSet) { + for (Option option : optionSet.getOptions()) { + final Syntax syntax = optionSet.optionSyntax.get(option.getName()); + addOption(option, syntax); + } + } + + /** + * The {@code addOption()} method adds an option with the {@link Syntax#REQUIRES_EQUALS} syntax to this option set. + * + * @param option the new option to add to this set + * @return the option passed as the argument, after it has been added to this option set + */ + public Option addOption(Option option) { + return addOption(option, Syntax.REQUIRES_EQUALS); + } + + /** + * The {@code addOption()} method adds an option to this option set. + * + * @param option the new option to add to this set + * @param syntax the syntax of the option, which specifies how to parse the option + * from command line parameters + * @return the option passed as the argument, after it has been added to this option set + */ + public Option addOption(Option option, Syntax syntax) { + final String name = option.getName(); + final Option existingOption = optionMap.put(name, option); + if (existingOption != null) { + throw ProgramError.unexpected("Cannot register more than one option under the same name: " + option.getName()); + } + optionSyntax.put(name, syntax); + return option; + } + + /** + * The {@code setSyntax()} method sets the syntax of a particular option. + * + * @param option the option for which to change the syntax + * @param syntax the new syntax for the instruction + */ + public void setSyntax(Option option, Syntax syntax) { + optionSyntax.put(option.getName(), syntax); + } + + /** + * The {@code setValue()} method sets the value of the specified option in + * this option set. If there is no option by the specified name, the name/value + * pair will simply be remembered. + * + * @param name the name of the option + * @param value the new value of the option as a string + * @throws Option.Error if {@code name} denotes an unrecognized option and this + */ + public void setValue(String name, String value) { + final String v = value == null ? "" : value; + final Option opt = optionMap.get(name); + if (opt != null) { + opt.setString(v); + } else { + if (!allowUnrecognizedOptions) { + throw new Option.Error("unrecognized option -" + name); + } + } + optionValues.put(name, v); + } + + public void setValuesAgain() { + for (String name : optionValues.keySet()) { + final Option opt = optionMap.get(name); + opt.setString(optionValues.get(name)); + } + } + + public String getStringValue(String name) { + return optionValues.get(name); + } + + /** + * The {@code hasOptionSpecified()} method checks whether an option with the specified + * name has been assigned to. An option as been "assigned to" if its value has been set + * by either parsing arguments (the {@code parseArguments() method} or loading properties + * from a file or the system properties. + * + * @param name the name of the option to query + * @return true if an option with the specified name has been set; false otherwise + */ + public boolean hasOptionSpecified(String name) { + return optionValues.containsKey(name); + } + + /** + * Retrieves the options from this option + * set, in the order in which they were added. + * @return an iterable collection of {@code Option} instances, sorted according to insertion order + */ + public Iterable> getOptions() { + return Utils.cast(optionMap.values()); + } + + /** + * The {@code getSortedOptions()} method retrieves the options from this option + * set, sorting all options by their names. + * @return an iterable collection of {@code Option} instances, sorted according to the name of each option + */ + public Iterable> getSortedOptions() { + final List> list = new LinkedList>(); + final TreeSet tree = new TreeSet(); + for (String string : optionMap.keySet()) { + tree.add(string); + } + for (String string : tree) { + list.add(optionMap.get(string)); + } + return list; + } + + /** + * Prints the help message header. + * + * @param stream the output stream to which to write the help text + */ + protected void printHelpHeader(PrintStream stream) { + } + + /** + * The {@code printHelp()} method prints a textual listing of these options and their syntax + * to the specified output stream. + * @param stream the output stream to which to write the help text + * @param width the length of the line to truncate + */ + public void printHelp(PrintStream stream, int width) { + printHelpHeader(stream); + for (Option option : getSortedOptions()) { + if (option.type == OptionTypes.BLANK_BOOLEAN_TYPE && option instanceof FieldOption) { + FieldOption fopt = (FieldOption) option; + try { + if (!fopt.nullValue.equals(fopt.field.getBoolean(null))) { + // Don't show message for "-XX:+" option if the default is represented by the + // "-XX:-" option instead (and vice versa). + continue; + } + } catch (Exception e) { + } + } + + + final Option opt = Utils.cast(option); + stream.print(" " + getUsage(opt)); + final Object defaultValue = opt.getDefaultValue(); + if (defaultValue != null) { + stream.println(" (default: " + opt.getType().unparseValue(defaultValue) + ")"); + } else { + stream.println(); + } + final String help = opt.getHelp(); + if (help.length() > 0) { + stream.print(Strings.formatParagraphs(help, 8, 0, width)); + stream.println(); + } + } + } + + /** + * This method gets a usage string for a particular option that describes + * the range of valid string values that it accepts. + * @param option the option for which to get usage + * @return a string describing the usage syntax for the specified option + */ + public String getUsage(Option option) { + return optionSyntax.get(option.getName()).getUsage(option); + } + + /** + * This method adds all public static fields with appropriate types to the + * option set with the specified prefix. + * @param javaClass the java class containing the fields + * @param prefix the prefix to add to the options + * @param helpMap map from option names to the help message for the option (may be {@code null}) + */ + public void addFieldOptions(Class javaClass, String prefix, Map helpMap) { + for (final Field field : javaClass.getDeclaredFields()) { + int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) { + field.setAccessible(true); + final OptionSettings settings = field.getAnnotation(OptionSettings.class); + String help; + String name; + if (settings != null) { + help = settings.help(); + name = settings.name().isEmpty() ? field.getName().replace('_', '-') : settings.name(); + } else { + name = field.getName().replace('_', '-'); + help = helpMap != null ? helpMap.get(name) : ""; + if (help == null) { + help = ""; + } + } + addFieldOption(prefix, name, null, field, help); + } + } + } + + /** + * Adds a new option whose value is stored in the specified reflection field. + * @param prefix the name of the option + * @param name the name of the option + * @param object the object containing the field (if the field is not static) + * @param field the field to store the value + * @param help the help text for the option @return a new option that will mod?ify the field when parsed + * @return the option created + */ + @SuppressWarnings("unchecked") + public Option addFieldOption(String prefix, String name, Object object, Field field, String help) { + final Class fieldType = field.getType(); + final Object defaultValue; + final String optionName = prefix + ":" + name; + try { + defaultValue = field.get(null); + } catch (IllegalAccessException e) { + return null; + } + if (fieldType == boolean.class) { + if (prefix.length() > 0) { + // setup a "-prefix+name" option + String plusName = prefix + ":+" + name; + FieldOption plusOption = new FieldOption(plusName, object, field, (Boolean) defaultValue, OptionTypes.BLANK_BOOLEAN_TYPE, help); + plusOption.nullValue = true; + addOption(plusOption, Syntax.REQUIRES_BLANK); + + // setup a "-prefix-name" option + String minusName = prefix + ":-" + name; + FieldOption minusOption = new FieldOption(minusName, object, field, (Boolean) defaultValue, OptionTypes.BLANK_BOOLEAN_TYPE, help); + minusOption.nullValue = false; + return addOption(minusOption, Syntax.REQUIRES_BLANK); + } + return addOption(new FieldOption(optionName, object, field, (Boolean) defaultValue, OptionTypes.BOOLEAN_TYPE, help)); + + } else if (fieldType == int.class) { + return addOption(new FieldOption(optionName, object, field, (Integer) defaultValue, OptionTypes.INT_TYPE, help)); + } else if (fieldType == float.class) { + return addOption(new FieldOption(optionName, object, field, (Float) defaultValue, OptionTypes.FLOAT_TYPE, help)); + } else if (fieldType == long.class) { + return addOption(new FieldOption(optionName, object, field, (Long) defaultValue, OptionTypes.LONG_TYPE, help)); + } else if (fieldType == double.class) { + return addOption(new FieldOption(optionName, object, field, (Double) defaultValue, OptionTypes.DOUBLE_TYPE, help)); + } else if (fieldType == String.class) { + return addOption(new FieldOption(optionName, object, field, (String) defaultValue, OptionTypes.STRING_TYPE, help)); + } else if (fieldType == File.class) { + return addOption(new FieldOption(optionName, object, field, (File) defaultValue, OptionTypes.FILE_TYPE, help)); + } else if (fieldType.isEnum()) { + final Class enumClass = Utils.cast(fieldType); + return addOption(makeEnumFieldOption(optionName, object, field, defaultValue, enumClass, help)); + } + return null; + } + + private > FieldOption makeEnumFieldOption(String name, Object object, Field field, Object defaultValue, Class enumClass, String help) { + final OptionTypes.EnumType optionType = new OptionTypes.EnumType(enumClass); + final T defaultV = Utils.cast(defaultValue); + return new FieldOption(name, object, field, defaultV, optionType, help); + } + + public Option newStringOption(String name, String defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.STRING_TYPE, help)); + } + + public Option newIntegerOption(String name, Integer defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.INT_TYPE, help)); + } + + public Option newLongOption(String name, Long defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.LONG_TYPE, help)); + } + + public Option newFloatOption(String name, Float defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.FLOAT_TYPE, help)); + } + + public Option newDoubleOption(String name, Double defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.DOUBLE_TYPE, help)); + } + + public Option> newStringListOption(String name, String defaultValue, String help) { + return addOption(new Option>(name, defaultValue == null ? null : OptionTypes.COMMA_SEPARATED_STRING_LIST_TYPE.parseValue(defaultValue), OptionTypes.COMMA_SEPARATED_STRING_LIST_TYPE, help)); + } + + public Option> newStringListOption(String name, String[] defaultValue, String help) { + List list = null; + if (defaultValue != null) { + list = new ArrayList(defaultValue.length); + list.addAll(Arrays.asList(defaultValue)); + } + return addOption(new Option>(name, list, OptionTypes.COMMA_SEPARATED_STRING_LIST_TYPE, help)); + } + + public Option> newStringListOption(String name, String defaultValue, char separator, String help) { + final OptionTypes.StringListType type = new OptionTypes.StringListType(separator); + return addOption(new Option>(name, defaultValue == null ? null : type.parseValue(defaultValue), type, help)); + } + + public Option> newListOption(String name, String defaultValue, Option.Type elementOptionType, char separator, String help) { + final OptionTypes.ListType type = new OptionTypes.ListType(separator, elementOptionType); + return addOption(new Option>(name, defaultValue == null ? null : type.parseValue(defaultValue), type, help)); + } + + public Option newFileOption(String name, String defaultValue, String help) { + return newFileOption(name, OptionTypes.FILE_TYPE.parseValue(defaultValue), help); + } + + public Option newFileOption(String name, File defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.FILE_TYPE, help)); + } + + public Option newURLOption(String name, URL defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.URL_TYPE, help)); + } + + public Option newInstanceOption(String name, Class klass, T defaultValue, String help) { + return addOption(new Option(name, defaultValue, OptionTypes.createInstanceOptionType(klass), help)); + } + + public Option> newListInstanceOption(String name, String defaultValue, Class klass, char separator, String help) { + final OptionTypes.ListType type = OptionTypes.createInstanceListOptionType(klass, separator); + return addOption(new Option>(name, (defaultValue == null) ? null : type.parseValue(defaultValue), type, help)); + } + + public Option newBooleanOption(String name, Boolean defaultValue, String help) { + if (defaultValue != null && !defaultValue) { + return addOption(new Option(name, defaultValue, OptionTypes.BOOLEAN_TYPE, help), Syntax.EQUALS_OR_BLANK); + } + return addOption(new Option(name, defaultValue, OptionTypes.BOOLEAN_TYPE, help)); + } + + public Option newOption(String name, String defaultValue, Option.Type type, String help) { + return newOption(name, type.parseValue(defaultValue), type, Syntax.REQUIRES_EQUALS, help); + } + + public Option newOption(String name, T defaultValue, Option.Type type, Syntax syntax, String help) { + return addOption(new Option(name, defaultValue, type, help), syntax); + } + + public > Option newEnumOption(String name, E defaultValue, Class enumClass, String help) { + return addOption(new Option(name, defaultValue, new OptionTypes.EnumType(enumClass), help)); + } + + public > Option> newEnumListOption(String name, Iterable defaultValue, Class enumClass, String help) { + final List list; + if (defaultValue == null) { + list = null; + } else if (defaultValue instanceof List) { + list = Utils.cast(defaultValue); + } else if (defaultValue instanceof Collection) { + final Collection collection = Utils.cast(defaultValue); + list = new ArrayList(collection); + } else { + list = new ArrayList(); + for (E value : defaultValue) { + list.add(value); + } + } + final Option> option = new Option>(name, list, new OptionTypes.EnumListType(enumClass, ','), help); + return addOption(option); + } + + public Option newConfigOption(String name, File defaultFile, String help) { + return addOption(new Option(name, defaultFile, new OptionTypes.ConfigFile(this), help)); + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/OptionSettings.java b/JavaInJava/src/com/sun/max/program/option/OptionSettings.java new file mode 100644 index 0000000..82f449c --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/OptionSettings.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * An annotation that can be applied to a static field to set its name as option and its help text. + * + * @author Ben L. Titzer + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface OptionSettings { + + /** + * The name of this option, if different from the name of the field. + * @return the name of this option + */ + String name() default ""; + + /** + * The help text of this option. + * @return the help text + */ + String help() default ""; +} diff --git a/JavaInJava/src/com/sun/max/program/option/OptionTypes.java b/JavaInJava/src/com/sun/max/program/option/OptionTypes.java new file mode 100644 index 0000000..d539af8 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/OptionTypes.java @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option; + +import java.io.*; +import java.net.*; +import java.text.*; +import java.util.*; + +import com.sun.max.*; +import com.sun.max.program.*; +import com.sun.max.program.option.Option.Error; + +public class OptionTypes { + + protected static class LongType extends Option.Type { + + protected LongType() { + super(Long.class, "long"); + } + + @Override + public Long parseValue(String string) { + if (string.length() == 0) { + return 0L; + } + try { + return Long.valueOf(string); + } catch (NumberFormatException e) { + throw new Option.Error("invalid long value: " + string); + } + } + + @Override + public String getValueFormat() { + return ""; + } + } + + protected static class ScaledLongType extends LongType { + + protected ScaledLongType() { + super(); + } + @Override + public Long parseValue(String string) { + final char last = string.charAt(string.length() - 1); + String s = string; + int multiplier = 1; + if (last == 'k' || last == 'K') { + multiplier = 1024; + s = s.substring(0, s.length() - 1); + } else if (last == 'm' || last == 'M') { + multiplier = 1024 * 1024; + s = s.substring(0, s.length() - 1); + } else if (last == 'g' || last == 'G') { + multiplier = 1024 * 1024 * 1024; + s = s.substring(0, s.length() - 1); + } + final long value = super.parseValue(s); + if (value > Long.MAX_VALUE / multiplier || value < Long.MIN_VALUE / multiplier) { + throw new Option.Error("invalid long value: " + s); + } + return value * multiplier; + } + } + + public static class ConfigFile extends Option.Type { + protected final OptionSet optionSet; + + public ConfigFile(OptionSet set) { + super(File.class, "file"); + optionSet = set; + } + @Override + public File parseValue(String string) { + if (string != null) { + final File f = new File(string); + if (!f.exists()) { + throw new Option.Error("configuration file does not exist: " + string); + } + try { + optionSet.loadFile(string, true); + } catch (IOException e) { + throw new Option.Error("error loading config from " + string + ": " + e.getMessage()); + } + } + return null; + } + + @Override + public String getValueFormat() { + return ""; + } + } + + public static class ListType extends Option.Type> { + protected final char separator; + public final Option.Type elementOptionType; + + private static Class> listClass(Class valueClass) { + final Class>> type = null; + return Utils.cast(type, List.class); + } + + public ListType(char separator, Option.Type elementOptionType) { + super(listClass(elementOptionType.type), "list"); + this.separator = separator; + this.elementOptionType = elementOptionType; + } + + @Override + public String unparseValue(List value) { + final StringBuilder buffer = new StringBuilder(); + boolean previous = false; + for (Object object : value) { + if (previous) { + buffer.append(separator); + } + previous = true; + buffer.append(object.toString()); + } + return buffer.toString(); + } + + @Override + public List parseValue(String val) { + final List list = new LinkedList(); + if (val.isEmpty()) { + return list; + } + + final CharacterIterator i = new StringCharacterIterator(val); + StringBuilder buffer = new StringBuilder(32); + while (i.current() != CharacterIterator.DONE) { + if (i.current() == separator) { + list.add(elementOptionType.parseValue(buffer.toString().trim())); + buffer = new StringBuilder(32); + } else { + buffer.append(i.current()); + } + i.next(); + } + list.add(elementOptionType.parseValue(buffer.toString().trim())); + return list; + } + + @Override + public String getValueFormat() { + return "[{" + separator + "}*]"; + } + } + + public static class EnumType> extends Option.Type { + public final T[] values; + + public EnumType(Class enumClass) { + super(enumClass, enumClass.getName()); + values = enumClass.getEnumConstants(); + } + + @Override + public T parseValue(String string) { + if (string == null) { + return null; + } + for (T value : values) { + if (value.name().equalsIgnoreCase(string)) { + return value; + } + } + throw new Option.Error("invalid " + typeName); + } + + @Override + public String getValueFormat() { + return Utils.toString(values, "|"); + } + } + + public static final Option.Type LONG_TYPE = new LongType(); + public static final Option.Type SCALED_LONG_TYPE = new ScaledLongType(); + + public static final Option.Type STRING_TYPE = new Option.Type(String.class, "string") { + @Override + public String parseValue(String string) { + return string; + } + + @Override + public String getValueFormat() { + return ""; + } + }; + + /** + * @author Thomas Wuerthinger + * + * @return An option type that takes a class name as its value. It reflectively creates an instance + * of the specified class. If the class is not found, it tries to prefix the class name with "com.sum.max.". + */ + public static final Option.Type createInstanceOptionType(final Class klass) { + return new Option.Type(klass, "instance") { + + @Override + public String getValueFormat() { + return ""; + } + + @Override + public T parseValue(String string) throws Error { + try { + try { + return Utils.cast(klass, Class.forName(string).newInstance()); + } catch (ClassNotFoundException e) { + return Utils.cast(klass, Class.forName("com.sun.max." + string).newInstance()); + } + } catch (InstantiationException e) { + ProgramError.unexpected("Could not instantiate class " + string, e); + } catch (IllegalAccessException e) { + ProgramError.unexpected("Could not access class " + string, e); + } catch (ClassNotFoundException e) { + ProgramError.unexpected("Could not find class " + string, e); + } + return null; + } + }; + } + + /** + * @author Thomas Wuerthinger + * + * @return An option type that takes a list of class names as its value. Then it reflectively creates instances + * of these classes and returns them as a list. + */ + public static final ListType createInstanceListOptionType(final Class klass, char separator) { + return new ListType(separator, createInstanceOptionType(klass)); + } + + public static final Option.Type DOUBLE_TYPE = new Option.Type(Double.class, "double") { + @Override + public Double parseValue(String string) { + if (string.length() == 0) { + return 0.0d; + } + try { + return Double.valueOf(string); + } catch (NumberFormatException e) { + throw new Option.Error("invalid double value: " + string); + } + } + + @Override + public String getValueFormat() { + return ""; + } + }; + public static final Option.Type FLOAT_TYPE = new Option.Type(Float.class, "float") { + @Override + public Float parseValue(String string) { + if (string.length() == 0) { + return 0.0f; + } + try { + return Float.valueOf(string); + } catch (NumberFormatException e) { + throw new Option.Error("invalid float value: " + string); + } + } + + @Override + public String getValueFormat() { + return ""; + } + }; + public static final Option.Type INT_TYPE = new Option.Type(Integer.class, "int") { + @Override + public Integer parseValue(String string) { + if (string.length() == 0) { + return 0; + } + try { + return Integer.valueOf(string); + } catch (NumberFormatException e) { + throw new Option.Error("invalid int value: " + string); + } + } + + @Override + public String getValueFormat() { + return ""; + } + }; + public static final Option.Type BOOLEAN_TYPE = new Option.Type(Boolean.class, "boolean") { + @Override + public Boolean parseValue(String string) { + if (string.isEmpty() || string.equalsIgnoreCase("true") || string.equalsIgnoreCase("t") || string.equalsIgnoreCase("y")) { + return Boolean.TRUE; + } else if (string.equalsIgnoreCase("false") || string.equalsIgnoreCase("f") || string.equalsIgnoreCase("n")) { + return Boolean.FALSE; + } + throw new Option.Error("invalid boolean value: " + string); + } + + @Override + public String getValueFormat() { + return "true|false, t|f, y|n"; + } + }; + public static final Option.Type BLANK_BOOLEAN_TYPE = new Option.Type(Boolean.class, "boolean") { + @Override + public Boolean parseValue(String string) { + // blank boolean always returns null + return null; + } + + @Override + public String getValueFormat() { + return "true|false, t|f, y|n"; + } + }; + public static final Option.Type FILE_TYPE = new Option.Type(File.class, "file") { + @Override + public File parseValue(String string) { + if (string == null || string.length() == 0) { + return null; + } + return new File(string); + } + + @Override + public String getValueFormat() { + return ""; + } + }; + public static final Option.Type URL_TYPE = new Option.Type(URL.class, "URL") { + @Override + public URL parseValue(String string) { + if (string == null || string.length() == 0) { + return null; + } + try { + return new URL(string); + } catch (MalformedURLException e) { + throw new Option.Error("invalid URL: " + string); + } + } + + @Override + public String getValueFormat() { + return ""; + } + }; + + public static class StringListType extends ListType { + public StringListType(char separator) { + super(separator, STRING_TYPE); + } + } + + public static class EnumListType> extends ListType { + public EnumListType(Class enumClass, char separator) { + super(separator, new EnumType(enumClass)); + } + } + + public static final StringListType COMMA_SEPARATED_STRING_LIST_TYPE = new StringListType(','); + +} diff --git a/JavaInJava/src/com/sun/max/program/option/Package.java b/JavaInJava/src/com/sun/max/program/option/Package.java new file mode 100755 index 0000000..b83e8fc --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option; + +import com.sun.max.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/gui/OptionsDialog.java b/JavaInJava/src/com/sun/max/program/option/gui/OptionsDialog.java new file mode 100644 index 0000000..8145fe9 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/gui/OptionsDialog.java @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option.gui; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.Arrays; +import java.util.List; + +import javax.swing.*; + +import com.sun.max.*; +import com.sun.max.gui.*; +import com.sun.max.program.*; +import com.sun.max.program.option.*; + +/** + * A dialog used to present the {@linkplain Option options} defined by a {@link OptionSet}. + * + * @author Doug Simon + * @author Ben L. Titzer + */ +public class OptionsDialog extends JDialog { + + public static final int TEXT_FIELD_COLUMNS = 40; + + protected abstract static class GUIOption implements ItemListener { + protected final Option option; + protected final JCheckBox guard; + protected final JLabel label; + protected JComponent input; + + protected GUIOption(Option opt) { + this.option = opt; + guard = new JCheckBox(); + label = new JLabel(option.getName()); + guard.addItemListener(this); + } + + public JCheckBox getGuard() { + return guard; + } + + public JLabel getLabel() { + return label; + } + + public JComponent getInputComponent() { + return input; + } + + public void itemStateChanged(ItemEvent e) { + setInputAndLabelEnabled(guard.isSelected()); + } + + protected void setEnabledOfContainedComponents(Container container, boolean enabled) { + for (Component component : container.getComponents()) { + component.setEnabled(enabled); + if (component instanceof Container) { + setEnabledOfContainedComponents((Container) component, enabled); + } + } + } + + protected void setInputAndLabelEnabled(boolean enabled) { + input.setEnabled(enabled); + setEnabledOfContainedComponents(input, enabled); + label.setEnabled(enabled); + } + + public abstract T getValue() throws Option.Error; + + public abstract void setValue(T value); + + public void commitOption() { + if (guard.isSelected()) { + option.setValue(getValue()); + } + } + + public String unparse() { + return option.getType().unparseValue(getValue()); + } + + public void parse(String str) { + guard.setEnabled(true); + setValue(option.getType().parseValue(str)); + } + } + + protected static class IntegerGUIOption extends GUIOption { + private final JTextField textField; + + protected IntegerGUIOption(Option option) { + super(option); + textField = new JTextField(); + input = textField; + textField.setColumns(TEXT_FIELD_COLUMNS); + setValue(option.getValue()); + } + + @Override + public void setValue(Integer i) { + textField.setText(String.valueOf(i)); + guard.setSelected(i != null); + setInputAndLabelEnabled(i != null); + } + + @Override + public Integer getValue() { + if (guard.isSelected()) { + return option.getType().parseValue(textField.getText()); + } + return null; + } + } + + protected static class BooleanGUIOption extends GUIOption { + private final JLabel helpText; + protected BooleanGUIOption(Option option) { + super(option); + helpText = new JLabel("" + option.getHelp() + ""); + input = helpText; + setValue(option.getValue()); + } + + @Override + public void commitOption() { + if (guard.isSelected()) { + option.setValue(true); + } else { + option.setValue(false); + } + } + + @Override + public void setValue(Boolean b) { + guard.setSelected(b); + helpText.setEnabled(b); + setInputAndLabelEnabled(b); + } + + @Override + public Boolean getValue() { + return guard.isSelected(); + } + } + + protected static class StringGUIOption extends GUIOption { + private final JTextField textField; + + protected StringGUIOption(Option option) { + super(option); + textField = new JTextField(TEXT_FIELD_COLUMNS); + input = textField; + setValue(option.getValue()); + } + + @Override + public void setValue(String i) { + textField.setText(String.valueOf(i)); + guard.setSelected(i != null); + setInputAndLabelEnabled(i != null); + } + + @Override + public String getValue() { + if (guard.isSelected()) { + return textField.getText(); + } + return null; + } + } + + protected static class ListGUIOption extends GUIOption> { + private final JTextField textField; + private final JList list; + + protected ListGUIOption(Option> option) { + super(option); + if (option.getType() instanceof OptionTypes.EnumListType) { + textField = null; + final OptionTypes.EnumListType elt = (OptionTypes.EnumListType) option.getType(); + final OptionTypes.EnumType et = (OptionTypes.EnumType) elt.elementOptionType; + list = new JList(et.values); + list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + list.setVisibleRowCount(Math.min(10, et.values.length)); + list.setLayoutOrientation(JList.VERTICAL); + final JScrollPane scrollPane = new JScrollPane(list); + input = scrollPane; + } else { + list = null; + textField = new JTextField(TEXT_FIELD_COLUMNS); + input = textField; + } + setValue(option.getValue()); + } + + @Override + public void setValue(List objects) { + if (objects != null) { + if (textField == null) { + this.list.clearSelection(); + final int[] selectedIndices = new int[objects.size()]; + int i = 0; + for (Object value : objects) { + final Enum enumValue = (Enum) value; + selectedIndices[i++] = enumValue.ordinal(); + } + this.list.setSelectedIndices(selectedIndices); + } else { + textField.setText(String.valueOf(option.getType().unparseValue(objects))); + } + } + guard.setSelected(objects != null); + setInputAndLabelEnabled(objects != null); + } + + @Override + public List getValue() { + if (guard.isSelected()) { + if (textField == null) { + final List result = new LinkedList(); + for (Object value : this.list.getSelectedValues()) { + result.add(value); + } + return result; + } + return option.getType().parseValue(textField.getText()); + } + return null; + } + } + + protected static class URLGUIOption extends GUIOption { + private final JTextField textField; + + protected URLGUIOption(Option option) { + super(option); + textField = new JTextField(TEXT_FIELD_COLUMNS); + input = textField; + setValue(option.getValue()); + } + + @Override + public void setValue(URL i) { + textField.setText(String.valueOf(i)); + guard.setSelected(i != null); + setInputAndLabelEnabled(i != null); + } + + @Override + public URL getValue() { + if (guard.isSelected()) { + try { + return new URL(textField.getText()); + } catch (MalformedURLException e) { + return null; + } + } + return null; + } + } + + protected static class EnumGUIOption extends GUIOption { + private final JComboBox comboBox; + + protected EnumGUIOption(Option option) { + super(option); + final OptionTypes.EnumType et = (OptionTypes.EnumType) option.getType(); + comboBox = new JComboBox(et.values); + input = comboBox; + setValue(option.getValue()); + } + + @Override + public void setValue(Object value) { + comboBox.setSelectedItem(value); + guard.setSelected(true); + } + + @Override + public Object getValue() { + return comboBox.getSelectedItem(); + } + } + + protected static class FileGUIOption extends GUIOption { + private final JTextField textField; + private final JButton fileChooserButton; + private JFileChooser fileChooser; + + protected FileGUIOption(Option option) { + super(option); + textField = new JTextField(TEXT_FIELD_COLUMNS); + final JPanel inputPanel = new JPanel(); + input = inputPanel; + fileChooserButton = new JButton(new AbstractAction("Select") { + public void actionPerformed(ActionEvent e) { + if (fileChooser == null) { + fileChooser = new JFileChooser(new File(".")); + fileChooser.setCurrentDirectory(new File(System.getProperty("user.home"))); + fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + } + + final File file = new File(textField.getText()); + if (file.exists()) { + final File parent = file.getParentFile(); + if (parent != null && parent.isDirectory()) { + fileChooser.setCurrentDirectory(parent); + } + fileChooser.ensureFileIsVisible(file); + fileChooser.setSelectedFile(file); + } + if (fileChooser.showDialog(fileChooserButton, "Select") == JFileChooser.APPROVE_OPTION) { + textField.setText(fileChooser.getSelectedFile().getAbsolutePath()); + } + } + }); + inputPanel.add(textField); + inputPanel.add(fileChooserButton); + setValue(option.getValue()); + } + + @Override + public void setValue(File i) { + if (i != null) { + if (fileChooser != null) { + fileChooser.setSelectedFile(i); + } + textField.setText(i.getAbsolutePath()); + } + guard.setSelected(i != null); + setInputAndLabelEnabled(i != null); + } + + @Override + public File getValue() { + return new File(textField.getText()); + } + + } + + protected static class PackageGUIOption extends GUIOption { + private final JComboBox values; + + protected PackageGUIOption(Option option) { + super(option); + + final MaxPackageOptionType type = (MaxPackageOptionType) option.getType(); + + final List maxPackages = new LinkedList(); + for (MaxPackage maxPackage : type.superPackage.getTransitiveSubPackages(Classpath.fromSystem())) { + final Class schemeClass = Utils.cast(type.classType); + if (maxPackage.schemeTypeToImplementation(schemeClass) != null) { + maxPackages.add(maxPackage); + } + } + + final MaxPackage[] pkgs = maxPackages.toArray(new MaxPackage[maxPackages.size()]); + Arrays.sort(pkgs, new Comparator() { + public int compare(MaxPackage o1, MaxPackage o2) { + return o1.name().compareTo(o2.name()); + } + }); + + this.values = new JComboBox(pkgs); + input = this.values; + + // The combo box must be editable as the prepopulated items are just those packages found from the super package + this.values.setEditable(true); + + setValue(option.getValue()); + } + + @Override + public MaxPackage getValue() { + return option.getType().parseValue(values.getSelectedItem().toString()); + } + + @Override + public void setValue(MaxPackage p) { + if (p != null) { + values.setSelectedItem(p); + guard.setSelected(true); + } else { + values.setSelectedIndex(-1); + guard.setSelected(false); + } + } + } + + private static GUIOption createGUIOption(Option option) { + final Option.Type type = option.getType(); + if (type == OptionTypes.BOOLEAN_TYPE) { + final Option opt = OptionTypes.BOOLEAN_TYPE.cast(option); + return new BooleanGUIOption(opt); + } + if (type == OptionTypes.INT_TYPE) { + final Option opt = OptionTypes.INT_TYPE.cast(option); + return new IntegerGUIOption(opt); + } + if (type == OptionTypes.STRING_TYPE) { + final Option opt = OptionTypes.STRING_TYPE.cast(option); + return new StringGUIOption(opt); + } + if (type == OptionTypes.URL_TYPE) { + final Option opt = OptionTypes.URL_TYPE.cast(option); + return new URLGUIOption(opt); + } + if (type == OptionTypes.FILE_TYPE) { + final Option opt = OptionTypes.FILE_TYPE.cast(option); + return new FileGUIOption(opt); + } + if (type instanceof OptionTypes.EnumType) { + final Option opt = Utils.cast(option); + return new EnumGUIOption(opt); + } + if (type instanceof OptionTypes.ListType) { + final Option> opt = Utils.cast(option); + return new ListGUIOption(opt); + } + if (type instanceof MaxPackageOptionType) { + final Option opt = Utils.cast(option); + return new PackageGUIOption(opt); + } + return null; + } + + private boolean cancelled; + + public OptionsDialog(JFrame owner, final OptionSet optionSet) { + super(owner, "Options Dialog", true); + + final LinkedList> guiOptions = new LinkedList>(); + + final Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + + // Configure panel of options + final JPanel optionsPanel = new JPanel(); + optionsPanel.setLayout(new SpringLayout()); + optionsPanel.setBorder(BorderFactory.createTitledBorder("")); + + for (final Option programOption : optionSet.getOptions()) { + final GUIOption guiOption = createGUIOption(programOption); + if (guiOption != null) { + guiOptions.add(guiOption); + + final JCheckBox enabled = guiOption.getGuard(); + final JLabel label = guiOption.getLabel(); + + label.setToolTipText(programOption.getHelp()); + + optionsPanel.add(enabled); + optionsPanel.add(label); + optionsPanel.add(guiOption.getInputComponent()); + } + } + + SpringUtilities.makeCompactGrid(optionsPanel, guiOptions.size(), 3, 0, 0, 5, 5); + contentPane.add(optionsPanel, BorderLayout.CENTER); + + // Configure buttons + final JButton ok = new JButton(new AbstractAction("OK") { + public void actionPerformed(ActionEvent e) { + for (GUIOption guiOption : guiOptions) { + try { + guiOption.commitOption(); + } catch (Option.Error e1) { + showErrorDialog(guiOption, e1); + return; + } + } + OptionsDialog.this.setVisible(false); + } + }); + + final JButton cancel = new JButton(new AbstractAction("Use Defaults") { + public void actionPerformed(ActionEvent e) { + OptionsDialog.this.setVisible(false); + OptionsDialog.this.cancelled = true; + } + }); + + final JButton exit = new JButton(new AbstractAction("Cancel") { + public void actionPerformed(ActionEvent e) { + System.exit(1); + } + }); + + ok.setToolTipText("Apply options as configured in this dialog and ignore the command line arguments."); + cancel.setToolTipText("Ignore options as configured in this dialog and use the command line arguments instead."); + exit.setToolTipText("Stop running the program [calls System.exit()]."); + + final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonPanel.add(ok); + buttonPanel.add(cancel); + buttonPanel.add(exit); + + contentPane.add(buttonPanel, BorderLayout.SOUTH); + pack(); + + // Places dialog in the middle of the screen if 'owner == null' + setLocationRelativeTo(owner); + } + + private class ErrorDialog extends JDialog { + ErrorDialog(JDialog owner, GUIOption guiOption, Option.Error error) { + super(owner, "Option Error", true); + final JPanel errorPanel = new JPanel(); + errorPanel.setLayout(new SpringLayout()); + errorPanel.setBorder(BorderFactory.createTitledBorder("")); + + final Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + + // Configure buttons + final JButton ok = new JButton(new AbstractAction("OK") { + public void actionPerformed(ActionEvent e) { + errorPanel.setVisible(false); + } + }); + final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonPanel.add(ok); + + final JLabel textPane = new JLabel(); + textPane.setText("Invalid value for " + guiOption.option.getType().getTypeName() + " option \"-" + guiOption.option.getName() + "\""); + contentPane.add(textPane); + + contentPane.add(buttonPanel, BorderLayout.SOUTH); + pack(); + + // Places dialog in the middle of the screen if 'owner == null' + setLocationRelativeTo(owner); + } + } + + public void showErrorDialog(GUIOption guiOption, Option.Error error) { + final String typeName = guiOption.option.getType().getTypeName(); + JOptionPane.showMessageDialog(this, "Error in option \"-" + guiOption.option.getName() + "\" of type " + typeName + "\n" + error.getMessage()); +// new ErrorDialog(this, guiOption, error).setVisible(true); + } + + /** + * Creates a dialog for displaying a GUI for a given option set. + * + * @return true if the user wants to use the options as configured by the dialog, false if the caller of this method + * should defer to parsing an argument array instead + */ + public static boolean show(JFrame owner, OptionSet optionSet) { + final OptionsDialog programOptionDialog = new OptionsDialog(owner, optionSet); + programOptionDialog.setVisible(true); + programOptionDialog.dispose(); + return !programOptionDialog.cancelled; + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/gui/Package.java b/JavaInJava/src/com/sun/max/program/option/gui/Package.java new file mode 100755 index 0000000..f7de9b7 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/gui/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.program.option.gui; + +import com.sun.max.*; + +/** + * This package is not included in the bootstrap as it would drag in most of Swing. + * + * @author Doug Simon + */ +public class Package extends MaxPackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/program/option/gui/package-info.java b/JavaInJava/src/com/sun/max/program/option/gui/package-info.java new file mode 100644 index 0000000..58c57bb --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/gui/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * GUI for getting command line options. + * + * @author Doug Simon + */ +package com.sun.max.program.option.gui; diff --git a/JavaInJava/src/com/sun/max/program/option/package-info.java b/JavaInJava/src/com/sun/max/program/option/package-info.java new file mode 100644 index 0000000..4e6a8a3 --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/option/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * Command line option parsing and side effect management. + * + * @author Bernd Mathiske + */ +package com.sun.max.program.option; diff --git a/JavaInJava/src/com/sun/max/program/package-info.java b/JavaInJava/src/com/sun/max/program/package-info.java new file mode 100644 index 0000000..9c70bad --- /dev/null +++ b/JavaInJava/src/com/sun/max/program/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * Utilities for any kind of Java program. + * + * @author Bernd Mathiske + */ +package com.sun.max.program; diff --git a/JavaInJava/src/com/sun/max/tele/interpreter/ExecutionFrame.java b/JavaInJava/src/com/sun/max/tele/interpreter/ExecutionFrame.java new file mode 100644 index 0000000..2765012 --- /dev/null +++ b/JavaInJava/src/com/sun/max/tele/interpreter/ExecutionFrame.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.tele.interpreter; + +import java.util.*; + +import com.sun.max.vm.actor.holder.*; +import com.sun.max.vm.actor.member.*; +import com.sun.max.vm.classfile.*; +import com.sun.max.vm.classfile.constant.*; +import com.sun.max.vm.value.*; + +/** + * Instances of this class represent individual execution frame entries on a given ExecutionThread's execution stack. + * + * @author Athul Acharya + */ +class ExecutionFrame { + + private final ClassMethodActor method; + private int currentOpcodePosition; + private int currentBytePosition; + private final Value[] locals; + private final Stack operands; + private final ExecutionFrame callersFrame; + private final byte[] code; + private final int depth; + + public ExecutionFrame(ExecutionFrame callersFrame, ClassMethodActor method) { + this.method = method; + this.locals = new Value[method.codeAttribute().maxLocals]; + this.operands = new Stack(); + this.callersFrame = callersFrame; + this.code = method.codeAttribute().code(); + this.depth = callersFrame == null ? 1 : callersFrame.depth + 1; + } + + /** + * Computes the number of frames on the call stack up to and including this frame. + */ + public int depth() { + return depth; + } + + public ExecutionFrame callersFrame() { + return callersFrame; + } + + public void setLocal(int index, Value value) { + locals[index] = value; + } + + public int readOpcode() { + currentOpcodePosition = currentBytePosition; + return readByte() & 0xff; + } + + public byte readByte() { + try { + return code[currentBytePosition++]; + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + throw new VerifyError("Ran off end of code"); + } + } + + public short readShort() { + final int high = readByte(); + final int low = readByte() & 0xff; + return (short) ((high << 8) | low); + } + + public int readInt() { + final int b3 = readByte() << 24; + final int b2 = (readByte() & 0xff) << 16; + final int b1 = (readByte() & 0xff) << 8; + final int b0 = readByte() & 0xff; + return b3 | b2 | b1 | b0; + } + + public void skipBytes(int n) { + currentBytePosition += n; + } + + public void alignInstructionPosition() { + final int remainder = currentBytePosition % 4; + if (remainder != 0) { + currentBytePosition += 4 - remainder; + } + } + + public void jump(int offset) { + currentBytePosition = currentOpcodePosition + offset; + } + + public int currentOpcodePosition() { + return currentOpcodePosition; + } + + public int currentBytePosition() { + return currentBytePosition; + } + + public void setBytecodePosition(int bcp) { + currentBytePosition = bcp; + } + + public byte[] code() { + return code; + } + + public Value getLocal(int index) { + return locals[index]; + } + + public Stack stack() { + return operands; + } + + public ConstantPool constantPool() { + return method.codeAttribute().constantPool; + } + + public ClassMethodActor method() { + return method; + } + + @Override + public String toString() { + return method.format("%H.%n(%p) @ " + currentBytePosition); + } + + /** + * Handles an exception at the current execution point in this frame by updating the {@linkplain #setBytecodePosition(int) + * instruction pointer} to the matching exception handler in this frame. If no matching exception handler is found + * for the current execution point and the given exception type, then the instruction pointer in this frame is left + * unmodified. + *

+ * The current execution point is derived from the value of {@link ExecutionFrame#currentBytePosition()} which is now at the first + * byte passed the instruction currently being executed. That is, an instruction is completely decoded before any + * exceptions are thrown while executing it. + * + * @param throwableClassActor the type of the exception being thrown + * @return {@code true} if an exception handler was found, {@code false} otherwise + */ + public boolean handleException(ClassActor throwableClassActor) { + final int bcp = currentOpcodePosition; + final ExceptionHandlerEntry[] handlers = method().codeAttribute().exceptionHandlerTable(); + for (ExceptionHandlerEntry handler : handlers) { + if (bcp >= handler.startPosition() && bcp < handler.endPosition()) { + if (handler.catchTypeIndex() == 0) { + currentBytePosition = handler.handlerPosition(); + return true; + } + final ClassActor catchType = constantPool().classAt(handler.catchTypeIndex()).resolve(constantPool(), handler.catchTypeIndex()); + if (catchType.isAssignableFrom(throwableClassActor)) { + currentBytePosition = handler.handlerPosition(); + return true; + } + } + } + return false; + } +} diff --git a/JavaInJava/src/com/sun/max/tele/interpreter/ExecutionThread.java b/JavaInJava/src/com/sun/max/tele/interpreter/ExecutionThread.java new file mode 100644 index 0000000..41a9ce1 --- /dev/null +++ b/JavaInJava/src/com/sun/max/tele/interpreter/ExecutionThread.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.tele.interpreter; + +import java.io.*; + +import com.sun.max.vm.actor.holder.*; +import com.sun.max.vm.actor.member.*; + +/** + * Instances of this class contain the execution state of a single thread in the system. + * NOTE: currently there _is_ only one thread. Please ignore the man behind the curtain. + * + * @author Athul Acharya + */ +class ExecutionThread { + + /** + * The maximum frame depth for a thread. + */ + public static final int STACK_SIZE = 1000; + + private ExecutionFrame frame; + //private int _prio; + //private ThreadType _threadType; + + public ExecutionThread(int prio, ThreadType threadType) { + //_prio = prio; + //_threadType = threadType; + frame = null; + } + + public ExecutionFrame pushFrame(ClassMethodActor method) { + this.frame = new ExecutionFrame(frame, method); + if (frame.depth() > STACK_SIZE) { + throw new StackOverflowError(); + } + return frame; + } + + public ExecutionFrame popFrame() { + frame = frame.callersFrame(); + return frame; + } + + public ExecutionFrame frame() { + return frame; + } + + public static enum ThreadType { + NORMAL_THREAD, + VM_THREAD, + } + + /** + * Handles an exception at the current execution point in this thread by updating the call stack and instruction + * pointer to a matching exception handler in this thread's current call stack. If no matching exception handler is + * found for the current execution point and the given exception type, then the call stack and instruction pointer + * in this thread are left unmodified. + * + * @param throwableClassActor + * @return {@code true} if an exception handler was found, {@code false} otherwise + */ + public boolean handleException(ClassActor throwableClassActor) { + ExecutionFrame frame = this.frame; + while (frame != null) { + if (frame.handleException(throwableClassActor)) { + this.frame = frame; + return true; + } + + frame = frame.callersFrame(); + } + return false; + } + + public void printStackTrace(PrintStream printStream, TeleInterpreterException executionException) { + ExecutionFrame frame = this.frame; + printStream.println(executionException.getMessage()); + while (frame != null) { + printStream.println("\tat " + frame.method().toStackTraceElement(frame.currentOpcodePosition())); + frame = frame.callersFrame(); + } + if (executionException.getCause() != null) { + printStream.print("Caused by: "); + executionException.getCause().printStackTrace(printStream); + } + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(getClass().getSimpleName()); + ExecutionFrame frame = this.frame; + while (frame != null) { + sb.append(String.format("%n%s [bci:%d]", frame.method().toStackTraceElement(frame.currentOpcodePosition()))); + frame = frame.callersFrame(); + } + return sb.toString(); + } +} diff --git a/JavaInJava/src/com/sun/max/tele/interpreter/Machine.java b/JavaInJava/src/com/sun/max/tele/interpreter/Machine.java new file mode 100644 index 0000000..3151e37 --- /dev/null +++ b/JavaInJava/src/com/sun/max/tele/interpreter/Machine.java @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.tele.interpreter; + +import java.lang.reflect.*; +import java.util.*; + +import com.sun.max.lang.*; +import com.sun.max.program.*; +import com.sun.max.tele.*; +import com.sun.max.tele.object.*; +import com.sun.max.tele.reference.*; +import com.sun.max.tele.value.*; +import com.sun.max.unsafe.*; +import com.sun.max.vm.actor.holder.*; +import com.sun.max.vm.actor.member.*; +import com.sun.max.vm.bytecode.graft.*; +import com.sun.max.vm.classfile.constant.*; +import com.sun.max.vm.layout.*; +import com.sun.max.vm.reference.*; +import com.sun.max.vm.type.*; +import com.sun.max.vm.value.*; + +/** + * The Interpreter's interface to the VM. Encapsulates all the state of the VM. + * Can run without VM for testing. + * + * @author Athul Acharya + */ +public final class Machine extends AbstractTeleVMHolder{ + + private ExecutionThread currentThread; + + Machine(TeleVM vm) { + super(vm); + final ExecutionThread mainThread = newThread(java.lang.Thread.NORM_PRIORITY, ExecutionThread.ThreadType.NORMAL_THREAD); + //JavaThreads.initialize(mainThread); + activate(mainThread); + } + + public ReferenceValue toReferenceValue(Reference reference) { + if (vm() == null) { + return ObjectReferenceValue.from(reference.toJava()); + } else { + return vm().createReferenceValue(reference); + } + } + + public ExecutionFrame pushFrame(ClassMethodActor method) { + return currentThread.pushFrame(method); + } + + public ExecutionFrame popFrame() { + return currentThread.popFrame(); + } + + public void activate(ExecutionThread thread) { + //active_threads.insertElementAt(this_thread, 0); + currentThread = thread; + } + + public ExecutionThread newThread(int prio, ExecutionThread.ThreadType threadType) { + return new ExecutionThread(prio, threadType); + } + + public MethodActor currentMethod() { + return currentThread.frame().method(); + } + + public ExecutionThread currentThread() { + return currentThread; + } + + public void jump(int offset) { + currentThread.frame().jump(offset); + } + + public int readOpcode() { + return currentThread.frame().readOpcode(); + } + + public void setLocal(int index, Value value) { + currentThread.frame().setLocal(index, value); + } + + public Value getLocal(int index) { + return currentThread.frame().getLocal(index); + } + + public void push(Value value) { + currentThread.frame().stack().push(value); + } + + public Value pop() { + return currentThread.frame().stack().pop(); + } + + public Value peek() { + return currentThread.frame().stack().peek(); + } + + public Value peek(int n) { + final Stack operands = currentThread.frame().stack(); + return operands.elementAt(operands.size() - n); + } + + public byte readByte() { + return currentThread.frame().readByte(); + } + + public short readShort() { + return currentThread.frame().readShort(); + } + + public int readInt() { + return currentThread.frame().readInt(); + } + + public void skipBytes(int n) { + currentThread.frame().skipBytes(n); + } + + public void alignInstructionPosition() { + currentThread.frame().alignInstructionPosition(); + } + + public Value widenIfNecessary(Value value) { + if (value.kind().stackKind == Kind.INT) { + return IntValue.from(value.toInt()); + } + + return value; + } + + public Value resolveConstantReference(int cpIndex) { + Value constant = currentThread.frame().constantPool().valueAt(cpIndex); + + if (constant instanceof ObjectReferenceValue) { + constant = toReferenceValue(Reference.fromJava(constant.unboxObject())); + } + + return widenIfNecessary(constant); + } + + /** + * Converts a given reference to an object to a {@link Throwable} instance. + * + * @param vm the tele VM to be used if {@code throwableReference} is a reference in a VM's address space + * @param throwableReference the reference to be converted to a {@code Throwable instance} + * @return a {@code Throwable instance} converted from {@code throwableReference} + */ + private static Throwable toThrowable(TeleVM vm, ReferenceValue throwableReference) { + if (throwableReference instanceof TeleReferenceValue) { + try { + return (Throwable) vm.heap().makeTeleObject(throwableReference.asReference()).deepCopy(); + } catch (Exception e1) { + throw ProgramError.unexpected("Could not make a local copy of a remote Throwable", e1); + } + } else { + return (Throwable) throwableReference.asBoxedJavaValue(); + } + } + + public TeleInterpreterException raiseException(ReferenceValue throwableReference) throws TeleInterpreterException { + throw new TeleInterpreterException(toThrowable(vm(), throwableReference), this); + } + + public TeleInterpreterException raiseException(Throwable throwable) throws TeleInterpreterException { + throw new TeleInterpreterException(throwable, this); + } + + /** + * Looks for an exception handler in the current execution scope that handles a given exception. If one is found, + * the execution context is adjusted appropriately so that execution will resume at the discovered handler. + * If no handler is found, the execution context is not modified. + * + * @param throwableReference the reference value representing the exception to be handled + * @return {@code true} if an appropriate exception handler was found, {@code false} otherwise + */ + public boolean handleException(ReferenceValue throwableReference) { + if (currentThread.handleException(throwableReference.getClassActor())) { + push(throwableReference); + return true; + } + return false; + } + + public int depth() { + return currentThread.frame().stack().size(); + } + + public Value getStatic(int cpIndex) { + final ConstantPool constantPool = currentThread.frame().constantPool(); + final FieldRefConstant fieldRef = constantPool.fieldAt(cpIndex); + if (vm() != null) { + final FieldActor fieldActor = fieldRef.resolve(constantPool, cpIndex); + final TeleClassActor teleClassActor = vm().findTeleClassActor(fieldActor.holder().typeDescriptor); + final TeleStaticTuple teleStaticTuple = teleClassActor.getTeleStaticTuple(); + final Reference staticTupleReference = teleStaticTuple.reference(); + + switch (fieldActor.kind.asEnum) { + case BOOLEAN: + case BYTE: + case CHAR: + case SHORT: + case INT: { + final int intValue = fieldActor.kind.readValue(staticTupleReference, fieldActor.offset()).toInt(); + return IntValue.from(intValue); + } + case FLOAT: { + return FloatValue.from(staticTupleReference.readFloat(fieldActor.offset())); + } + case LONG: { + return LongValue.from(staticTupleReference.readLong(fieldActor.offset())); + } + case DOUBLE: { + return DoubleValue.from(staticTupleReference.readDouble(fieldActor.offset())); + } + case WORD: { + return new WordValue(staticTupleReference.readWord(fieldActor.offset())); + } + case REFERENCE: { + return vm().createReferenceValue(vm().wordToReference(staticTupleReference.readWord(fieldActor.offset()))); + } + } + } else { + final FieldActor fieldActor = fieldRef.resolve(constantPool, cpIndex); + return widenIfNecessary(fieldActor.readValue(Reference.fromJava(fieldActor.holder().staticTuple()))); + } + + return null; + } + + public void putStatic(int cpIndex, Value value) { + if (vm() != null) { + ProgramError.unexpected("Cannot run putstatic remotely!"); + } else { + final ConstantPool cp = currentThread.frame().constantPool(); + final FieldActor fieldActor = cp.fieldAt(cpIndex).resolve(cp, cpIndex); + fieldActor.writeValue(fieldActor.holder().staticTuple(), fieldActor.kind.convert(value)); + } + } + + public Value getField(Reference instance, int cpIndex) throws TeleInterpreterException { + if (instance.isZero()) { + raiseException(new NullPointerException()); + } + final ConstantPool constantPool = currentThread.frame().constantPool(); + final FieldRefConstant fieldRef = constantPool.fieldAt(cpIndex); + final FieldActor fieldActor = fieldRef.resolve(constantPool, cpIndex); + final Kind kind = fieldActor.kind; + + if (kind.isExtendedPrimitiveValue()) { + return widenIfNecessary(fieldActor.readValue(instance)); + } else { + assert kind.isReference; + if (instance instanceof TeleReference && !((TeleReference) instance).isLocal()) { + return vm().createReferenceValue(vm().wordToReference(instance.readWord(fieldActor.offset()))); + } else { + return fieldActor.readValue(instance); + } + } + } + + public void putField(Object instance, int cpIndex, Value value) { + if (instance instanceof TeleReference && !((TeleReference) instance).isLocal()) { + ProgramError.unexpected("Cannot run putfield remotely!"); + } else { + final ConstantPool cp = currentThread.frame().constantPool(); + final FieldActor fieldActor = cp.fieldAt(cpIndex).resolve(cp, cpIndex); + + if (value instanceof TeleReferenceValue) { + fieldActor.writeValue(instance, TeleReferenceValue.from(vm(), makeLocalReference((TeleReference) value.asReference()))); + } else { + final Value val = fieldActor.kind.convert(value); + fieldActor.writeValue(instance, val); + } + } + } + + public MethodActor resolveMethod(int cpIndex) { + final ConstantPool cp = currentThread.frame().constantPool(); + final MethodRefConstant methodRef = cp.methodAt(cpIndex); + return methodRef.resolve(cp, cpIndex); + } + + private Object readRemoteArray(TeleReference remoteArray, int length, TypeDescriptor type) { + Object localArray = null; + // TODO: this could probably ask the kind to perform the operation + if (type == JavaTypeDescriptor.BOOLEAN) { + final boolean[] array = new boolean[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getBoolean(remoteArray, i); + } + + localArray = array; + } else if (type == JavaTypeDescriptor.BYTE) { + final byte[] array = new byte[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getByte(remoteArray, i); + } + + localArray = array; + } else if (type == JavaTypeDescriptor.CHAR) { + final char[] array = new char[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getChar(remoteArray, i); + } + + localArray = array; + } else if (type == JavaTypeDescriptor.DOUBLE) { + final double[] array = new double[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getDouble(remoteArray, i); + } + + localArray = array; + } else if (type == JavaTypeDescriptor.FLOAT) { + final float[] array = new float[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getFloat(remoteArray, i); + } + + localArray = array; + } else if (type == JavaTypeDescriptor.INT) { + final int[] array = new int[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getInt(remoteArray, i); + } + + localArray = array; + } else if (type == JavaTypeDescriptor.LONG) { + final long[] array = new long[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getLong(remoteArray, i); + } + + localArray = array; + } else if (type == JavaTypeDescriptor.SHORT) { + final short[] array = new short[length]; + + for (int i = 0; i < length; i++) { + array[i] = Layout.getShort(remoteArray, i); + } + + localArray = array; + } else { + ProgramError.unexpected("readRemoteArray called without a primitive array type"); + } + + return localArray; + } + + Reference makeLocalReference(TeleReference remoteReference) { + if (remoteReference.isLocal()) { + return remoteReference; + } + + final ClassActor remoteReferenceClassActor = vm().makeClassActorForTypeOf(remoteReference); + + if (remoteReferenceClassActor.typeDescriptor.equals(JavaTypeDescriptor.STRING)) { + return Reference.fromJava(vm().getString(remoteReference)); + } else if (remoteReferenceClassActor.isArrayClass() && remoteReferenceClassActor.componentClassActor().isPrimitiveClassActor()) { + final int arrayLength = Layout.readArrayLength(remoteReference); + return Reference.fromJava(readRemoteArray(remoteReference, arrayLength, remoteReferenceClassActor.componentClassActor().typeDescriptor)); + } else { + //should put some tracing error message here + return remoteReference; + } + } + + private void invertOperands(Stack argumentStack, Value[] arguments) { + for (int i = 0; i < arguments.length; i++) { + arguments[i] = argumentStack.pop(); + + if (arguments[i] instanceof TeleReferenceValue) { + final TeleReferenceValue inspectorReferenceArgument = (TeleReferenceValue) arguments[i]; + final TeleReference reference = (TeleReference) inspectorReferenceArgument.asReference(); + if (!reference.isLocal()) { + arguments[i] = TeleReferenceValue.from(vm(), makeLocalReference(reference)); + } + } + } + } + + private final ClassMethodActor safepointAndLoadExceptionObject = (ClassMethodActor) MethodActor.fromJava(Classes.findDeclaredMethod(ExceptionDispatcher.class, "safepointAndLoadExceptionObject")); + + public void invokeMethod(ClassMethodActor method) throws TeleInterpreterException { + final ExecutionFrame oldFrame = currentThread.frame(); + final Stack argumentStack = new Stack(); + final Stack oldOperands = oldFrame.stack(); + int numberOfParameters = method.descriptor().numberOfParameters(); + int i; + + if (!method.isStatic()) { + numberOfParameters++; + } + + //inverting the operands + for (i = 0; i < numberOfParameters; i++) { + argumentStack.push(oldOperands.pop()); + } + + if (method == safepointAndLoadExceptionObject) { + push(widenIfNecessary(ReferenceValue.from(ExceptionDispatcher.hostedSafepointAndLoadExceptionObject()))); + } else if (method.isNative()) { + final Value[] arguments = new Value[numberOfParameters]; + invertOperands(argumentStack, arguments); + try { + push(widenIfNecessary(method.invoke(arguments))); + } catch (InvocationTargetException e) { + throw new TeleInterpreterException(e.getCause(), this); + } catch (IllegalAccessException e) { + throw new TeleInterpreterException(e, this); + } + } else if (method.codeAttribute() == null || Word.class.isAssignableFrom(method.holder().toJava())) { + final Value[] arguments = new Value[numberOfParameters]; + invertOperands(argumentStack, arguments); + + try { + Value result = method.invoke(arguments); + if (result.kind().isReference) { + result = toReferenceValue(Reference.fromJava(result.asObject())); + } + push(widenIfNecessary(result)); + } catch (InvocationTargetException e) { + throw new TeleInterpreterException(e.getCause(), this); + } catch (IllegalAccessException e) { + throw new TeleInterpreterException(e, this); + } + } else { + final ExecutionFrame newFrame = currentThread.pushFrame(method); + i = 0; + while (i < numberOfParameters) { + final Value argument = argumentStack.pop(); + newFrame.setLocal(i, argument); + + if (argument instanceof DoubleValue || argument instanceof LongValue) { + i++; + numberOfParameters++; + } + i++; + } + } + } + + public ClassActor resolveClassReference(int constantPoolIndex) { + final ConstantPool constantPool = currentThread.frame().constantPool(); + return constantPool.classAt(constantPoolIndex).resolve(constantPool, constantPoolIndex); + } +} diff --git a/JavaInJava/src/com/sun/max/tele/interpreter/Package.java b/JavaInJava/src/com/sun/max/tele/interpreter/Package.java new file mode 100644 index 0000000..36126b4 --- /dev/null +++ b/JavaInJava/src/com/sun/max/tele/interpreter/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.tele.interpreter; + +import com.sun.max.*; + +/** + * @author Athul Acharya + */ +public class Package extends MaxPackage { + + public Package() { + super(); + } + +} diff --git a/JavaInJava/src/com/sun/max/tele/interpreter/TeleInterpreter.java b/JavaInJava/src/com/sun/max/tele/interpreter/TeleInterpreter.java index 3c8b362..c888b77 100644 --- a/JavaInJava/src/com/sun/max/tele/interpreter/TeleInterpreter.java +++ b/JavaInJava/src/com/sun/max/tele/interpreter/TeleInterpreter.java @@ -53,23 +53,17 @@ * @author Athul Acharya * @author Doug Simon */ -public final class TeleInterpreter extends IrInterpreter { +public final class TeleInterpreter { private final TeleVM teleVM; private Machine machine; private Value returnValue; - private int instructionsExecuted; public TeleInterpreter(TeleVM teleVM) { this.teleVM = teleVM; } - @Override - public Value execute(IrMethod method, Value... arguments) throws InvocationTargetException { - return run(method.classMethodActor(), arguments); - } - /** * Creates an interpreter instance and uses it to execute a given method with the given arguments. * Note that arguments must be dynamic types seen by the JavaPrototyper as legitimate VM classes. @@ -84,116 +78,6 @@ public static Value execute(TeleVM teleVM, ClassMethodActor classMethodActor, Va return new TeleInterpreter(teleVM).run(classMethodActor, args); } - /** - * Creates an interpreter instance and uses it to execute a given method with the given arguments. - * - * @param teleVM the remote VM - * @param declaringClassName the name of the class that declares the method to be executed - * @param name the name of the method to be executed - * @param signature the signature of the method to be executed - * @param args the arguments to passed to the method for execution - * @return the result of the execution - * @throws TeleInterpreterException if an uncaught exception occurs during execution of the method - * @throws NoSuchMethodError if the specified method cannot be found - */ - public static Value execute(TeleVM teleVM, String declaringClassName, String name, SignatureDescriptor signature, Value... args) throws TeleInterpreterException { - ClassActor classActor; - ClassMethodActor classMethodActor; - - classActor = HostedBootClassLoader.HOSTED_BOOT_CLASS_LOADER.mustMakeClassActor(JavaTypeDescriptor.getDescriptorForJavaString(declaringClassName)); - classMethodActor = classActor.findClassMethodActor(SymbolTable.makeSymbol(name), signature); - - if (classMethodActor == null) { - throw new NoSuchMethodError(declaringClassName + "." + name + signature); - } - - return execute(teleVM, classMethodActor, args); - } - - /** - * Creates an interpreter instance and uses it to execute a given method with the given arguments. - * - * @param teleVM the remote VM - * @param declaringClass the class that declares the method to be executed - * @param name the name of the method to be executed - * @param signature the signature of the method to be executed - * @param args the arguments to passed to the method for execution - * @return the result of the execution - * @throws TeleInterpreterException if an uncaught exception occurs during execution of the method - */ - public static Value execute(TeleVM teleVM, Class declaringClass, String name, SignatureDescriptor signature, Value... args) throws TeleInterpreterException { - ClassActor classActor; - ClassMethodActor classMethodActor; - - classActor = HostedBootClassLoader.HOSTED_BOOT_CLASS_LOADER.mustMakeClassActor(JavaTypeDescriptor.forJavaClass(declaringClass)); - classMethodActor = classActor.findClassMethodActor(SymbolTable.makeSymbol(name), signature); - - if (classMethodActor == null) { - throw new NoSuchMethodError(declaringClass.getName() + "." + name + signature); - } - - return execute(teleVM, classMethodActor, args); - } - - /** - * A lazy constructed cache of mappings from opcode positions to disassembled bytecode instructions. - */ - private Map> bytecodeTraces; - - /** - * The last frame traced in {@link #traceExecution()}. - */ - private ExecutionFrame lastTracedFrame; - - /** - * Traces the current execution point. - */ - private void traceExecution() { - if (Trace.hasLevel(2)) { - PrintStream stream = Trace.stream(); - ExecutionFrame frame = machine.currentThread().frame(); - - int depth = frame.depth(); - if (lastTracedFrame == null) { - stream.println("Interpreter: " + Strings.spaces(depth * 2) + "ENTERING: " + frame.method().format("%H.%n(%p)")); - } else if (lastTracedFrame != frame) { - int lastFrameDepth = lastTracedFrame.depth(); - if (lastFrameDepth < depth) { - stream.println("Interpreter: " + Strings.spaces(depth * 2) + "ENTERING: " + frame.method().format("%H.%n(%p)")); - } else { - stream.println("Interpreter: " + Strings.spaces(lastFrameDepth * 2) + "EXITING: " + lastTracedFrame.method().format("%H.%n(%p)")); - } - } - if (Trace.hasLevel(3)) { - if (bytecodeTraces == null) { - bytecodeTraces = new HashMap>(); - } - Map bcpToTrace = bytecodeTraces.get(machine.currentMethod()); - if (bcpToTrace == null) { - bcpToTrace = new HashMap(); - bytecodeTraces.put(machine.currentMethod(), bcpToTrace); - ConstantPool constantPool = frame.constantPool(); - BytecodeBlock bytecodeBlock = new BytecodeBlock(frame.code()); - String[] instructions = BytecodePrinter.toString(constantPool, bytecodeBlock, "", "\0", 0).split("\0"); - for (String instruction : instructions) { - int colonIndex = instruction.indexOf(':'); - assert colonIndex != -1 : "instruction trace does not start with expected ':': " + instruction; - try { - int bcp = Integer.parseInt(instruction.substring(0, colonIndex)); - bcpToTrace.put(bcp, instruction); - } catch (NumberFormatException numberFormatException) { - ProgramWarning.message("instruction trace does not start with expected ':': " + instruction); - } - } - } - - stream.println("Interpreter: " + Strings.spaces(depth * 2) + bcpToTrace.get(frame.currentOpcodePosition())); - } - lastTracedFrame = frame; - stream.flush(); - } - } - private Value run(ClassMethodActor classMethodActor, Value... arguments) throws TeleInterpreterException { machine = new Machine(teleVM); @@ -208,13 +92,10 @@ private Value run(ClassMethodActor classMethodActor, Value... arguments) throws int opcode; MethodStatus status; - instructionsExecuted = 0; while (true) { opcode = machine.readOpcode(); - traceExecution(); - try { boolean isWide = false; @@ -240,8 +121,6 @@ private Value run(ClassMethodActor classMethodActor, Value... arguments) throws if (!handled) { throw new TeleInterpreterException(throwable, machine); } - } finally { - instructionsExecuted++; } } diff --git a/JavaInJava/src/com/sun/max/tele/interpreter/TeleInterpreterException.java b/JavaInJava/src/com/sun/max/tele/interpreter/TeleInterpreterException.java new file mode 100644 index 0000000..7900ad7 --- /dev/null +++ b/JavaInJava/src/com/sun/max/tele/interpreter/TeleInterpreterException.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.tele.interpreter; + +import java.lang.reflect.*; + +import com.sun.max.vm.value.*; + +/** + * An exception thrown while executing the {@linkplain TeleInterpreter interpreter}. + * + * Instances of this exception type are constructed in the context of the interpreter's {@linkplain Machine machine} + * state which is used to construct a stack trace of the interpreter's call stack at the time of the exception. + * + * @author Doug Simon + */ +public class TeleInterpreterException extends InvocationTargetException { + + private final ReferenceValue throwableReference; + + public TeleInterpreterException(Throwable throwable, Machine machine) { + super(throwable, throwable.getMessage()); + throwableReference = ReferenceValue.from(throwable); + initStackTrace(machine); + } + + public ReferenceValue throwableReference() { + return throwableReference; + } + + public Class throwableType() { + return throwableReference.getClassActor().toJava(); + } + + private void initStackTrace(Machine machine) { + ExecutionFrame frame = machine.currentThread().frame(); + if (frame == null) { + setStackTrace(new StackTraceElement[0]); + } else { + int i = 0; + final int depth = frame.depth(); + final StackTraceElement[] stackTrace = new StackTraceElement[depth]; + while (frame != null) { + stackTrace[i++] = frame.method().toStackTraceElement(frame.currentOpcodePosition()); + frame = frame.callersFrame(); + } + setStackTrace(stackTrace); + } + } + + /** + * Returns the value of calling {@link #toString()} on the {@link #getCause() wrapped} exception. + */ + @Override + public String toString() { + return getCause().toString(); + } +} diff --git a/JavaInJava/src/com/sun/max/tele/interpreter/package-info.java b/JavaInJava/src/com/sun/max/tele/interpreter/package-info.java new file mode 100644 index 0000000..451145b --- /dev/null +++ b/JavaInJava/src/com/sun/max/tele/interpreter/package-info.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * An interpreter for running queries on remote objects in the tele VM. + * + * Derived from the JavaInJava interpreter by Antero Taivalsaari. + * See Sun Labs tech report TR-98-64: + * http://research.sun.com/techrep/1998/abstract-64.html + * + * @author Athul Acharya + */ +package com.sun.max.tele.interpreter; diff --git a/JavaInJava/src/com/sun/max/util/ArrayValueHistory.java b/JavaInJava/src/com/sun/max/util/ArrayValueHistory.java new file mode 100644 index 0000000..f448899 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/ArrayValueHistory.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.util.*; + +import com.sun.max.program.*; + +/** + * An array-based recording of the history of a value, with + * time expressed as the number of generations back from the current generation (0). + * + * @author Michael Van De Vanter + */ +public class ArrayValueHistory { + + private final ArrayDeque generations; + private final int limit; + private int age = -1; + + public ArrayValueHistory(int limit) { + this.generations = new ArrayDeque(); + this.limit = limit; + } + + public ArrayValueHistory() { + this (Integer.MAX_VALUE); + } + + /** + * Adds a new value, which becomes the current generation. + * The generation of all previously recorded values increases by 1. + */ + public void add(E newValue) { + if (generations.size() > 0) { + if (newValue.equals(generations.getFirst())) { + if (age >= 0) { + age++; + } + } else { + age = 0; + } + } + generations.addFirst(newValue); + if (generations.size() > limit) { + generations.removeLast(); + } + } + + /** + * @return the "current" value (at generation 0). + * Error if no values have been recorded. + */ + public E get() { + if (generations.size() > 0) { + return generations.getFirst(); + } + ProgramError.unexpected("empty history"); + return null; + } + + /** + * @return The value at a specified generation. + * Error if generation does not exist. + */ + public E get(int generation) { + final Iterator iterator = generations.iterator(); + int index = 0; + while (iterator.hasNext()) { + if (index == generation) { + return iterator.next(); + } + index++; + } + ProgramError.unexpected("exceeded history"); + return null; + } + + /** + * @return the age, in generations, of the current value, since recording began. + * 0 if different from immediate predecessor; -1 if no different value ever recorded + * Comparison uses {@linkplain Object#equals(Object) equals}. + */ + public int getAge() { + return age; + } + + /** + * @return the maximum number of generations that can be recorded. + */ + public int getLimit() { + return limit; + } + + /** + * @return the number of generations recorded; initially 0. + */ + public int getSize() { + return generations.size(); + } + + /** + * @return iteration of the values recorded in the history, starting with the current + * generation and proceeding backward in time. + */ + public Iterator values() { + return generations.iterator(); + } + +} diff --git a/JavaInJava/src/com/sun/max/util/Deferrable.java b/JavaInJava/src/com/sun/max/util/Deferrable.java new file mode 100755 index 0000000..68b63e6 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Deferrable.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.util.*; + +/** + * Deferred Runnables. + * + * Creating a Deferrable either causes immediate execution of its 'run()' method + * or queues it for deferred execution later on when 'runAll()' is called. + * + * @author Bernd Mathiske + */ +public abstract class Deferrable implements Runnable { + + public Deferrable(Queue queue) { + queue.handle(this); + } + + @Override + public String toString() { + return super.toString(); + } + + public static final class Queue { + + private List deferrables; + + private Queue() { + } + + synchronized void handle(Deferrable deferrable) { + if (deferrables != null) { + deferrables.add(deferrable); + } else { + deferrable.run(); + } + } + + public synchronized void deferAll() { + deferrables = new LinkedList(); + } + + public synchronized void runAll() { + while (deferrables != null) { + final List oldDeferrables = this.deferrables; + this.deferrables = new LinkedList(); + for (Deferrable deferrable : oldDeferrables) { + deferrable.run(); + } + if (oldDeferrables.isEmpty()) { + this.deferrables = null; + } + } + } + } + + public static Queue createRunning() { + return new Queue(); + } + + public static Queue createDeferred() { + final Queue queue = new Queue(); + queue.deferAll(); + return queue; + } + + public abstract static class Block implements Runnable { + public Block(Queue queue) { + queue.deferAll(); + run(); + queue.runAll(); + } + } +} diff --git a/JavaInJava/src/com/sun/max/util/Enumerable.java b/JavaInJava/src/com/sun/max/util/Enumerable.java new file mode 100644 index 0000000..c67dce0 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Enumerable.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +/** + * Java enums are insufficient in that their ordinals have to be successive. + * An Enumerable has an additional arbitrary int "value", + * which may incur gaps between ordinal-successive Enumerables. + *

+ * An Enumerator can be called upon to provide the respective Enumerable matching a given value. + *

+ * See "Inheritance, Generics and Binary Methods in Java" + * for an explanation of how to interpret a recursive generic type. + *

+ * + * @see Enumerator + * + * @author Bernd Mathiske + */ +public interface Enumerable & Enumerable> extends Symbol { + + // We are merely declaring this method to lock in the same parameter type for the corresponding enumerator, + // not for any actual use + Enumerator enumerator(); + +} diff --git a/JavaInJava/src/com/sun/max/util/Enumerator.java b/JavaInJava/src/com/sun/max/util/Enumerator.java new file mode 100644 index 0000000..727b6da --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Enumerator.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.util.*; + +import com.sun.max.*; + +/** + * @see Enumerable + * + * @author Bernd Mathiske + */ +public class Enumerator & Enumerable> + implements Symbolizer { + + private final Class type; + private final E[] ordinalMap; + private final E[] valueMap; + private final int lowestValue; + + public Enumerator(Class type) { + this.type = type; + ordinalMap = type.getEnumConstants(); + + int lowValue = 0; + int highestValue = ordinalMap.length - 1; + boolean valuesAreSameAsOrdinals = true; + for (E e : ordinalMap) { + final int value = e.value(); + if (value != e.ordinal()) { + valuesAreSameAsOrdinals = false; + } + if (value < lowValue) { + lowValue = value; + } else if (value > highestValue) { + highestValue = value; + } + } + + if (valuesAreSameAsOrdinals) { + this.lowestValue = 0; + valueMap = ordinalMap; + } else { + final int valueMapLength = (highestValue - lowValue) + 1; + final Class arrayType = null; + this.lowestValue = lowValue; + valueMap = Utils.cast(arrayType, new Enum[valueMapLength]); + for (E e : ordinalMap) { + final int value = e.value(); + // The enumerable with the lowest ordinal is stored in the value map: + if (valueMap[value] == null) { + valueMap[value] = e; + } + } + } + } + + public Class type() { + return type; + } + + public int numberOfValues() { + return ordinalMap.length; + } + + /** + * Adds all the enumerable constants in this enumerator to a given set. + * + * @param set + * the set to which the enumerable constants are to be added + */ + public void addAll(Set set) { + for (E e : this) { + set.add(e); + } + } + + public int size() { + return ordinalMap.length; + } + + public Iterator iterator() { + return Arrays.asList(ordinalMap).iterator(); + } + + /** + * Gets the enumerable constant denoted by a given ordinal. Note that this differs from {@link #fromValue(int)} in + * that the latter retrieves an enumerable constant matching a given {@linkplain Enumerable#value() value}. An + * enumerable's value is not necessarily the same as its ordinal. + * + * @throws IndexOutOfBoundsException + * if {@code 0 < ordinal || ordinal >= length()} + */ + public E get(int ordinal) throws IndexOutOfBoundsException { + return ordinalMap[ordinal]; + } + + /** + * Gets the enumerable constant matching a given value. That is, this method gets an enumerable from this enumerator + * whose {@linkplain Enumerable#value() value} is equal to {@code value}. Note that the given value may not match + * any enumerable in this enumerator in which case null is returned. Additionally, there may be more than one + * enumerable with a matching value in which case the matching enumerable with the lowest + * {@linkplain Enum#ordinal() ordinal} is returned. + */ + public E fromValue(int value) { + final int index = value - lowestValue; + if (index >= 0 && index < valueMap.length) { + return valueMap[index]; + } + return null; + } +} diff --git a/JavaInJava/src/com/sun/max/util/ListSymbolizer.java b/JavaInJava/src/com/sun/max/util/ListSymbolizer.java new file mode 100644 index 0000000..7138dab --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/ListSymbolizer.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.util.*; + +import com.sun.max.program.*; + +/** + * @author Bernd Mathiske + */ +final class ListSymbolizer implements Symbolizer { + + private final Class symbolType; + private final List symbols; + + ListSymbolizer(Class symbolType, List symbols) { + if (symbolType.getName().startsWith("com.sun.max.asm") && Symbolizer.Static.hasPackageExternalAccessibleConstructors(symbolType)) { + // This test ensures that values passed for symbolic parameters of methods in the + // generated assemblers are guaranteed to be legal (assuming client code does not + // inject its own classes into the package where the symbol classes are defined). + ProgramError.unexpected("type of assembler symbol can have values constructed outside of defining package: " + symbolType); + } + this.symbolType = symbolType; + this.symbols = symbols; + ProgramError.check(!symbols.isEmpty()); + } + + public Class type() { + return symbolType; + } + + public int numberOfValues() { + return symbols.size(); + } + + public S fromValue(int value) { + for (S symbol : symbols) { + if (symbol.value() == value) { + return symbol; + } + } + return null; + } + + public Iterator iterator() { + return symbols.iterator(); + } +} diff --git a/JavaInJava/src/com/sun/max/util/Package.java b/JavaInJava/src/com/sun/max/util/Package.java new file mode 100755 index 0000000..b995ac1 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Package.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import com.sun.max.*; + +/** + * @see MaxPackage + * + * @author Bernd Mathiske + */ +public class Package extends BasePackage { + public Package() { + super(); + } +} diff --git a/JavaInJava/src/com/sun/max/util/Predicate.java b/JavaInJava/src/com/sun/max/util/Predicate.java new file mode 100755 index 0000000..60f42fa --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Predicate.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import com.sun.max.*; + +/** + * @author Bernd Mathiske + */ +public interface Predicate { + + boolean evaluate(T object); + + public static final class Static { + private Static() { + } + + private static Predicate alwaysTrue = new Predicate() { + public boolean evaluate(Object object) { + return true; + } + }; + + public static Predicate alwaysTrue(Class type) { + final Class> predicateType = null; + return Utils.cast(predicateType, alwaysTrue); + } + } + +} diff --git a/JavaInJava/src/com/sun/max/util/Range.java b/JavaInJava/src/com/sun/max/util/Range.java new file mode 100644 index 0000000..905cb15 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Range.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +/** + * A {@code Range} denotes all the integer values between a {@linkplain #start() start} (inclusive) and + * {@linkplain #end() end} (exclusive) value. + * + * @author Doug Simon + */ +public class Range { + private final int start; + private final int end; + + public Range(int start) { + this(start, start + 1); + } + + /** + * Creates an object representing values in the range {@code [start .. end)}. + * + * @param start + * the lowest value in the range + * @param end + * the value one greater than the highest value in the range + */ + public Range(int start, int end) { + assert end >= start; + this.start = start; + this.end = end; + assert length() >= 0; + } + + /** + * Gets the lowest value in this range. + * @return + */ + public int start() { + return start; + } + + /** + * Gets the number of values covered by this range. + */ + public long length() { + // This cast and the long return type prevents integer overflow + return ((long) end) - start; + } + + /** + * Gets the value one greater than the highest value in this range. + */ + public int end() { + return end; + } + + public boolean contains(long value) { + return value >= start && value < end; + } + + @Override + public String toString() { + return "[" + start() + '-' + (end() - 1) + ']'; + } +} diff --git a/JavaInJava/src/com/sun/max/util/Registry.java b/JavaInJava/src/com/sun/max/util/Registry.java new file mode 100644 index 0000000..2c9ee48 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Registry.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.util.*; + +import com.sun.max.program.*; + +/** + * The {@code Registry} class implements a type of configuration mechanism + * that allows a short string name (called an alias) to refer to a class name. + * The short name can be used to quickly look up an internally registered class and + * instantiate it (assuming the target class as a public constructor which takes + * no parameters). If the alias is not registered, the registry will try to use + * the alias as a fully-qualified Java class and load it using reflection. + * + * @author Ben L. Titzer + */ +public class Registry { + + protected final boolean loadClass; + protected final Class classClass; + protected final Map> classMap; + protected final Map objectMap; + protected final Map stringMap; + + public Registry(Class classType, boolean loadClass) { + this.loadClass = loadClass; + this.classClass = classType; + this.classMap = new HashMap>(); + this.objectMap = new HashMap(); + this.stringMap = new HashMap(); + } + + public void registerObject(String alias, C object) { + objectMap.put(alias, object); + } + + public void registerClass(String alias, Class classType) { + classMap.put(alias, classType); + } + + public void registerClass(String alias, String className) { + stringMap.put(alias, className); + } + + public C getInstance(String alias) { + return getInstance(alias, true); + } + + public C getInstance(String alias, boolean fatal) { + final C object = objectMap.get(alias); + if (object != null) { + return object; + } + Class classRef = classMap.get(alias); + String className = alias; + try { + if (classRef == null) { + className = stringMap.get(alias); + if (className != null) { + classRef = Class.forName(className).asSubclass(classClass); + } else if (loadClass) { + classRef = Class.forName(alias).asSubclass(classClass); + } else { + return genError(fatal, "cannot find alias", alias, className); + } + } + className = classRef.getName(); + return classRef.newInstance(); + } catch (ClassNotFoundException e) { + return genError(fatal, "cannot find class", alias, className); + } catch (InstantiationException e) { + return genError(fatal, "cannot instantiate class", alias, className); + } catch (IllegalAccessException e) { + return genError(fatal, "cannot instantiate class", alias, className); + } catch (ClassCastException e) { + return genError(fatal, "not a subclass of " + classClass.getName(), alias, className); + } + } + + public Iterable getAliases() { + final LinkedList lista = new LinkedList(); + lista.addAll(objectMap.keySet()); + lista.addAll(classMap.keySet()); + lista.addAll(stringMap.keySet()); + return lista; + } + + private C genError(boolean fatal, String message, String alias, String className) { + if (!fatal) { + return null; + } + String mstr = message + ": " + alias; + if (className != null) { + mstr = mstr + "(" + className + ")"; + } + throw ProgramError.unexpected(mstr); + } + + public static Registry newRegistry(Class cl) { + return new Registry(cl, true); + } +} diff --git a/JavaInJava/src/com/sun/max/util/RuntimeInfo.java b/JavaInJava/src/com/sun/max/util/RuntimeInfo.java new file mode 100644 index 0000000..abc2430 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/RuntimeInfo.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.io.*; +import java.util.regex.*; + +/** + * Class for run-time system information. + * + * @author Paul Caprioli + */ +public final class RuntimeInfo { + + /** + * Gets the suggested maximum number of processes to fork. + * @param requestedMemorySize the physical memory size (in bytes) that each process will consume. + * @return the suggested number of processes that should be started in parallel. + */ + public static int getSuggestedMaximumProcesses(long requestedMemorySize) { + final Runtime runtime = Runtime.getRuntime(); + final String os = System.getProperty("os.name"); + long freeMemory = 0L; + try { + if (os.equals("Linux")) { + final Process process = runtime.exec(new String[] {"/usr/bin/free", "-ob"}); + final BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); + in.readLine(); + final String line = in.readLine(); + final String[] fields = line.split("\\s+"); + freeMemory = Long.parseLong(fields[3]); + } else if (os.equals("SunOS")) { + Process process = runtime.exec(new String[] {"/bin/kstat", "-p", "-nsystem_pages", "-sfreemem"}); + BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line = in.readLine(); + String[] fields = line.split("\\s+"); + freeMemory = Long.parseLong(fields[1]); + process = runtime.exec(new String[] {"/bin/getconf", "PAGESIZE"}); + in = new BufferedReader(new InputStreamReader(process.getInputStream())); + line = in.readLine(); + freeMemory *= Long.parseLong(line); + } else if (os.equals("Mac OS X") || os.equals("Darwin")) { + final Process process = runtime.exec("/usr/bin/vm_stat"); + final BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); + final Matcher matcher = Pattern.compile("[^0-9]*([0-9]+)[^0-9]*").matcher(in.readLine()); + if (matcher.matches()) { + freeMemory = Long.parseLong(matcher.group(1)); + } + matcher.reset(in.readLine()); + if (matcher.matches()) { + freeMemory *= Long.parseLong(matcher.group(1)); + } + } else if (os.equals("GuestVM")) { + freeMemory = 0L; + } + } catch (Exception e) { + freeMemory = 0L; + } + final int processors = runtime.availableProcessors(); + if (freeMemory <= 0L || freeMemory >= requestedMemorySize * processors) { + return processors; + } + return Math.max(1, (int) (freeMemory / requestedMemorySize)); + } + + private RuntimeInfo() { + } +} diff --git a/JavaInJava/src/com/sun/max/util/SingleThread.java b/JavaInJava/src/com/sun/max/util/SingleThread.java new file mode 100644 index 0000000..8019896 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/SingleThread.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.util.concurrent.*; + +import com.sun.max.*; +import com.sun.max.lang.*; +import com.sun.max.program.*; + +/** + * Compute given functions in always one and the same single thread. + * + * This is for example necessary in Linux where one and + * the same thread needs to be reused to represent the whole process in certain contexts, + * e.g. when using the ptrace interface. + * + * @author Bernd Mathiske + * @author Doug Simon + */ +public class SingleThread extends Thread { + + private static Thread worker; + private static final ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() { + public Thread newThread(Runnable runnable) { + ProgramError.check(worker == null, "Single worker thread died unexpectedly"); + worker = new Thread(runnable); + worker.setName("SingleThread"); + return worker; + } + }); + + private static final boolean disabled = false; + + public static V execute(Function function) { + if (disabled || Thread.currentThread() == worker) { + try { + return function.call(); + } catch (Exception exception) { + ProgramError.unexpected(exception); + } + } + synchronized (executorService) { + final Future future = executorService.submit(function); + while (true) { + try { + return future.get(); + } catch (ExecutionException e) { + throw Utils.cast(RuntimeException.class, e.getCause()); + } catch (InterruptedException exception) { + // continue + } + } + } + } + + public static V executeWithException(Function function) throws Exception { + if (disabled || Thread.currentThread() == worker) { + return function.call(); + } + synchronized (executorService) { + final Future future = executorService.submit(function); + while (true) { + try { + return future.get(); + } catch (ExecutionException e) { + final Throwable cause = e.getCause(); + if (cause instanceof Exception) { + throw (Exception) cause; + } + ProgramError.unexpected(cause); + } catch (InterruptedException exception) { + // continue + } + } + } + } + + public static void execute(final Runnable runnable) { + if (disabled || Thread.currentThread() == worker) { + runnable.run(); + } + synchronized (executorService) { + final Future future = executorService.submit(runnable); + while (true) { + try { + future.get(); + return; + } catch (ExecutionException e) { + final Throwable cause = e.getCause(); + ProgramError.unexpected(cause); + + } catch (InterruptedException exception) { + // continue + } + } + } + } +} diff --git a/JavaInJava/src/com/sun/max/util/Symbol.java b/JavaInJava/src/com/sun/max/util/Symbol.java new file mode 100644 index 0000000..90254a0 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Symbol.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +/** + * A symbol is an immutable binding of a name to a value. + * + * @author Bernd Mathiske + * + * @see Symbolizer + */ +public interface Symbol { + + /** + * @return the name of the symbol + */ + String name(); + + /** + * @return the value of the symbol + */ + int value(); + +} diff --git a/JavaInJava/src/com/sun/max/util/Symbolizer.java b/JavaInJava/src/com/sun/max/util/Symbolizer.java new file mode 100644 index 0000000..c29eb3e --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Symbolizer.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.lang.reflect.*; +import java.util.*; +import java.util.Arrays; + +import com.sun.max.lang.*; + +/** + * A symbolizer is used to group a set of {@link Symbol symbols}. The members of the + * group can be iterated and the symbol corresponding to a given value can be + * retrieved from the group. + * + * This class is similar to the semantics of {@code enum}s in Java but adds + * the ability to have a set of predefined symbols whose primitive values are not + * necessarily contiguous and starting at 0. + * + * @author Bernd Mathiske + */ +public interface Symbolizer extends Iterable { + + /** + * @return the concrete type of the symbols in the group + */ + Class type(); + + /** + * Gets the symbol in the group whose primitive value equals {@code value}. + * + * @param value the search key + * @return the found symbol or {@code null} if no symbol is found for {@code value} + */ + S fromValue(int value); + + int numberOfValues(); + + public static final class Static { + + private Static() { + } + + public static boolean hasPackageExternalAccessibleConstructors(Class type) { + final int publicOrProtected = Modifier.PUBLIC | Modifier.PROTECTED; + for (Constructor constructor : type.getConstructors()) { + if ((constructor.getModifiers() & publicOrProtected) != 0) { + return true; + } + } + return false; + } + + /** + * Gets a map from name to symbol for all the symbols represented by a given symbolizer. + * + * @param the type of the symbol + * @param symbolizer a set of symbols + * @return a map from symbol name to symbol + */ + public static Map toSymbolMap(Symbolizer symbolizer) { + final Map map = new HashMap(symbolizer.numberOfValues()); + for (S symbol : symbolizer) { + map.put(symbol.name(), symbol); + } + return map; + } + + public static Symbolizer from(Class symbolType, S... symbols) { + return new ListSymbolizer(symbolType, Arrays.asList(symbols)); + } + + public static Symbolizer fromList(Class symbolType, Iterable< ? extends S> symbols, + final S... additionalSymbols) { + final List list = new ArrayList(Arrays.asList(additionalSymbols)); + for (S symbol : symbols) { + list.add(symbol); + } + return new ListSymbolizer(symbolType, list); + } + + public static Symbolizer append(Symbolizer symbolizer, S... symbols) { + return fromList(symbolizer.type(), symbolizer, symbols); + } + + public static Symbolizer append(Class symbolType, Symbolizer< ? extends S> symbolizer, + final S... symbols) { + return fromList(symbolType, symbolizer, symbols); + } + + public static Symbolizer initialize(Class staticNameFieldClass, Class symbolType) { + final List list = new ArrayList(); + final List staticFieldNames = StaticFieldName.Static.initialize(staticNameFieldClass); + for (StaticFieldName staticFieldName : staticFieldNames) { + if (symbolType.isInstance(staticFieldName)) { + list.add(symbolType.cast(staticFieldName)); + } + } + return new ListSymbolizer(symbolType, list); + } + + public static Symbolizer initialize(Class symbolType) { + return initialize(symbolType, symbolType); + } + + public static Symbolizer fromSymbolizer(Symbolizer symbolizer, Predicate predicate) { + if (predicate == null) { + return symbolizer; + } + final List result = new LinkedList(); + for (S element : symbolizer) { + if (predicate.evaluate(element)) { + result.add(element); + } + } + List filtered = result; + return fromList(symbolizer.type(), filtered); + } + + } +} diff --git a/JavaInJava/src/com/sun/max/util/Utf8.java b/JavaInJava/src/com/sun/max/util/Utf8.java new file mode 100755 index 0000000..392b0c4 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Utf8.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +import java.io.*; + +/** + * @author Bernd Mathiske + */ +public final class Utf8 { + + private Utf8() { + } + + /** + * @return the length in bytes of the UTF8 representation of the string + */ + public static int utf8Length(String string) { + int result = 0; + for (int i = 0; i < string.length(); i++) { + final int ch = string.charAt(i); + if ((ch >= 0x0001) && (ch <= 0x007F)) { + result++; + } else if (ch > 0x07FF) { + result += 3; + } else { + result += 2; + } + } + return result; + } + + public static byte[] stringToUtf8(String string) { + final byte[] result = new byte[utf8Length(string)]; + int index = 0; + for (int i = 0; i < string.length(); i++) { + final char ch = string.charAt(i); + if ((ch >= 0x0001) && (ch <= 0x007F)) { + result[index++] = (byte) ch; + } else if (ch > 0x07FF) { + result[index++] = (byte) (0xe0 | (byte) (ch >> 12)); + result[index++] = (byte) (0x80 | ((ch & 0xfc0) >> 6)); + result[index++] = (byte) (0x80 | (ch & 0x3f)); + } else { + result[index++] = (byte) (0xc0 | (byte) (ch >> 6)); + result[index++] = (byte) (0x80 | (ch & 0x3f)); + } + } + return result; + } + + /** + * Reads a UTF-8 encoded String from {@code in}. + * + * @param in a data input source + * @param zeroIsEncodedIn2Bytes if true, then 0 is decoded from two bytes as opposed to one + * @param length the numbers of bytes to be decoded + * @return the decoded string + */ + public static String readUtf8(DataInput in, boolean zeroIsEncodedIn2Bytes, int length) throws IOException, Utf8Exception { + if (length == 0) { + return ""; + } + final byte[] utf8Data = new byte[length]; + + boolean sevenBit = true; + for (int i = 0; i < length; i++) { + final byte ch = in.readByte(); + utf8Data[i] = ch; + if (ch < 0 || (zeroIsEncodedIn2Bytes && ch == 0)) { + sevenBit = false; + } + } + + if (sevenBit) { + final char[] charData = new char[length]; + for (int i = 0; i < length; i++) { + charData[i] = (char) (utf8Data[i] & 0xff); + } + return new String(charData); + } + + return utf8ToString(zeroIsEncodedIn2Bytes, utf8Data); + } + + /** + * Converts an array of UTF-8 data to a String. + * + * @param zeroIsEncodedIn2Bytes if true, then 0 is decoded from two bytes as opposed to one + * @param utf8Data the data + * @return the decoded string + */ + public static String utf8ToString(boolean zeroIsEncodedIn2Bytes, byte[] utf8Data) throws Utf8Exception { + final int length = utf8Data.length; + int count = 0; + final StringBuilder sb = new StringBuilder(length); + + while (count < length) { + final int c = utf8Data[count] & 0xff; + if (zeroIsEncodedIn2Bytes && c == 0) { + throw new Utf8Exception(); + } + switch (c >> 4) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: { + /* 0xxxxxxx*/ + count++; + sb.append((char) c); + break; + } + case 12: case 13: { + /* 110x xxxx 10xx xxxx*/ + count += 2; + if (count > length) { + throw new Utf8Exception(); + } + final int char2 = utf8Data[count - 1]; + if ((char2 & 0xC0) != 0x80) { + throw new Utf8Exception(); + } + sb.append((char) (((c & 0x1F) << 6) | (char2 & 0x3F))); + break; + } + case 14: { + /* 1110 xxxx 10xx xxxx 10xx xxxx */ + count += 3; + if (count > length) { + throw new Utf8Exception(); + } + final int char2 = utf8Data[count - 2]; + final int char3 = utf8Data[count - 1]; + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) { + throw new Utf8Exception(); + } + sb.append((char) (((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0))); + break; + } + default: { + /* 10xx xxxx, 1111 xxxx */ + throw new Utf8Exception(); + } + } + } + // The number of chars produced may be less than utflen + return new String(sb); + } + + private static byte[] readZeroTerminatedBytes(InputStream inputStream) throws IOException { + final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + while (true) { + final int ch = inputStream.read(); + if (ch < 0) { + throw new IOException(); + } + if (ch == 0) { + return buffer.toByteArray(); + } + buffer.write(ch); + } + } + + /** + * Reads a 0-terminated UTF8 encoded string from a given stream. + * + * @param inputStream the stream to read from + * @return the String constructed from the UTF8 encoded chars read from {@code inputStream}, omitting the terminating 0 + */ + public static String readString(InputStream inputStream) throws IOException, Utf8Exception { + final byte[] utf8Data = readZeroTerminatedBytes(inputStream); + return Utf8.utf8ToString(false, utf8Data); + } + + /** + * Writes a 0-terminated UTF8 encoded string to a given stream. + * + * @param inputStream the stream to read from + * @param string the String to be written + */ + public static void writeString(OutputStream outputStream, String string) throws IOException { + outputStream.write(stringToUtf8(string)); + outputStream.write((byte) 0); + } +} diff --git a/JavaInJava/src/com/sun/max/util/Utf8Exception.java b/JavaInJava/src/com/sun/max/util/Utf8Exception.java new file mode 100644 index 0000000..c292c0b --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/Utf8Exception.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +package com.sun.max.util; + +/** + * Signals that something went wrong regarding UTF8 encoding or decoding. + * + * @author Bernd Mathiske + */ +public class Utf8Exception extends Exception { + + Utf8Exception() { + super(); + } + + Utf8Exception(String message) { + super(message); + } + + Utf8Exception(String message, Throwable cause) { + super(message, cause); + } + + Utf8Exception(Throwable cause) { + super(cause); + } + +} diff --git a/JavaInJava/src/com/sun/max/util/package-info.java b/JavaInJava/src/com/sun/max/util/package-info.java new file mode 100644 index 0000000..cc8e2c6 --- /dev/null +++ b/JavaInJava/src/com/sun/max/util/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, these intellectual property + * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or + * more additional patents or pending patent applications in the U.S. and in other countries. + * + * U.S. Government Rights - Commercial software. Government users are subject to the Sun + * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its + * supplements. + * + * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or + * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks + * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the + * U.S. and other countries. + * + * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open + * Company, Ltd. + */ +/** + * This package contains anything that has not been properly categorized yet. + * + * @author Bernd Mathiske + */ +package com.sun.max.util;