001 // Copyright 2005-08 Regents of the University of California. May be used
002 // under the terms of the revised BSD license. See LICENSING for details.
003 /**
004 * @author Adrian Mettler
005 */
006 package org.joe_e;
007 import org.joe_e.taming.Policy;
008
009 /**
010 * Joe-E core library functions. These provide fundamental features, similar
011 * to the methods in <code>java.lang.System</code>, such as the interface to the
012 * overlay type system.
013 */
014 public class JoeE {
015
016 private JoeE() {}
017
018 /**
019 * Tests whether the specified object belongs to the specified type in the
020 * overlay type system. The equivalent of the Java <code>instanceof</code>
021 * operator, for the overlay type system.
022 *
023 * @param obj the object to test
024 * @param type the type to test membership of
025 * @return true if the specified object belongs to the specified type
026 * in the overlay type system.
027 */
028 static public boolean instanceOf(Object obj, Class<?> type) {
029 return obj != null && isSubtypeOf(obj.getClass(), type);
030 }
031
032 /**
033 * Tests whether the first class is a subtype of the second in the overlay
034 * type system.
035 *
036 * @param c1 the potential subtype
037 * @param c2 the potential supertype
038 * @return true if the first argument is a subtype of the second in the
039 * overlay type system
040 */
041 /*
042 * It might be hard to believe at first that an algorithm this simple
043 * can take into account all transitive dependencies correctly,
044 * but here is the key fact that makes it work:
045 * if C honorarily implements marker interface I, and D is a
046 * subclass of C, then either (1) D is from the Java library,
047 * in which case the honorary implementation guarantees that D
048 * will also be marked as honorarily implementing I; or (2) D is
049 * user code, in which case the Joe-E verifier requires D to explicitly
050 * implement I (in the Java type system). In either case, this
051 * accounts for all transitive dependencies: in case (1), the call
052 * to honorarilyImplements() take care of transitive subtyping;
053 * in case (2), isAssignableFrom() takes care of it.
054 */
055 static public boolean isSubtypeOf(Class<?> c1, Class<?> c2) {
056 if (c2.isAssignableFrom(c1)) {
057 return true;
058 } else {
059 return Policy.hasHonorary(c1.getName(), c2.getName());
060 }
061 }
062
063 /**
064 * This field holds the ErrorHandler to be invoked when
065 * <code>abort()</code> is called.
066 * Trusted infrastructure (non-Joe-E) code may change the abort behavior
067 * by using unsafe reflection to modify the value of this field.
068 */
069 static private ErrorHandler handler = new SystemExit();
070
071 /**
072 * Aborts the current flow of control. This method invokes the currently
073 * registered error handler, which should preclude continued execution of
074 * Joe-E code.
075 * @param reason reason for the abort
076 * @return an error to throw
077 */
078 static public Error abort(final Error reason) {
079 while (true) {
080 try {
081 return handler.handle(reason);
082 } catch (final Throwable e) {
083 // Keep trying...
084 }
085 }
086 }
087
088 /**
089 * Is the object one-level deep immutable?
090 * @param x candidate object
091 * @return <code>true</code> if <code>x</code> is one-level deep immutable,
092 * <code>false</code> if it might not be
093 */
094 static public boolean
095 isFrozen(final Object x) {
096 return null == x ||
097 instanceOf(x, Selfless.class) ||
098 instanceOf(x, Immutable.class);
099 }
100 }