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 }