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    }