_Java Q&A_
by Cliff Berg

Listing One
/* Copyright Digital Focus. This code may be used for non-commercial purposes.
 * No guarantee or warrantee is given or implied.
 */

/** Our security manager. */
class GremlinWatcher extends SecurityManager
{
    private ThreadGroup seniorThreadGroup;
    private String gremlinDirectory;
    public GremlinWatcher(ThreadGroup seniorThreadGroup,
                                              String gremlinDirectory)
    {
        super();
        this.seniorThreadGroup = seniorThreadGroup;
        this.gremlinDirectory = gremlinDirectory;
    }
    public void checkCreateClassLoader() { }
    public void checkAccess(Thread t)
    {
        ThreadGroup g = t.getThreadGroup();
        checkAccess(g);
    }
    public void checkAccess(ThreadGroup g)
   {
        ThreadGroup tg = Thread.currentThread().getThreadGroup();
        if (! tg.parentOf(g)) throw new SecurityException();
    }
    public void checkExit(int status) { }
    public void checkExec(String cmd) { }
    public void checkLink(String lib) { }
    public void checkRead(java.io.FileDescriptor fd) { }
    public void checkRead(String file)
    {
        ThreadGroup tg = Thread.currentThread().getThreadGroup();
        if (tg != seniorThreadGroup)
        {
            // Perform checks; if checks fail, throw exception
            java.io.File f = new java.io.File(file);
            String path = f.getAbsolutePath();
            if (! path.regionMatches(true, 0, gremlinDirectory, 0, 
                                               gremlinDirectory.length()))
                throw new SecurityException("Cannot read file (" + path + ") 
                                              outside of Gremlin Directory");
            if (f.getName().regionMatches(true, f.getName().length() - 8,
                                               ".private", 0, 8))
                throw new SecurityException("Cannot read private file 
                                               (" + path + ")");
        }
        // return ok
        System.out.println("File " + file + " may be read");
    }
    public void checkRead(String file, Object context) { }
    public void checkWrite(java.io.FileDescriptor fd) { }
    public void checkWrite(String file)
    {
        ThreadGroup tg = Thread.currentThread().getThreadGroup();
        if (tg != seniorThreadGroup)
        {
            // Perform checks; if checks fail, throw exception
            java.io.File f = new java.io.File(file);
            String path = f.getAbsolutePath();
            if (! path.regionMatches(true, 0, gremlinDirectory, 0, 
                                               gremlinDirectory.length()))
                throw new SecurityException("Cannot write file (" + path + ") 
                                             outside of Gremlin Directory");
            if (f.getName().regionMatches(true, f.getName().length() - 8, 
                                               ".private", 0, 8))
                throw new SecurityException("Cannot write private file 
                                               (" + path + ")");
        }
        // return ok
        System.out.println("File " + file + " may be written");
    }
    public void checkDelete(String file) { }
    public void checkConnect(String host, int port) { }
    public void checkConnect(String host, int port, Object context) { }
    public void checkListen(int port) { }
    public void checkAccept(String host, int port) { }
    public void checkMulticast(java.net.InetAddress maddr) { }
    public void checkMulticast(java.net.InetAddress maddr, byte ttl) { }
    public void checkPropertiesAccess() { }
    public void checkPropertyAccess(String key) { }
    public void checkPropertyAccess(String key, String def) { }
    public boolean checkTopLevelWindow(Object window) { return true; }
    public void checkPrintJobAccess() { }
    public void checkSystemClipboardAccess() { }
    public void checkAwtEventQueueAccess() { }
    public void checkPackageAccess(String pkg) { }
    public void checkPackageDefinition(String pkg) { }
    public void checkSetFactory() { }
    public void checkMemberAccess(Class clazz, int which) { }
    public void checkSecurityAccess(String provider) { }
}
/** Our main class. */
public final class Demo
{
    private static ThreadGroup gremlins;
    private static boolean running = false;
    
    private Demo() {}   // Do not allow someone to instantiate
    
    /** Compiles a file called "Test.java" in the current directory, which 
     * contains a class called "Test", and dynamically loads that class and 
     * runs its run() method in a thread. Class Test must implement Runnable.
     * The only argument is the absolute path of the directory that Gremlins 
     * have unrestricted access to.
     */
    public static void main(String[] args)
    {
        if (running) return;
        running = true;
        SecurityManager sm = 
         new GremlinWatcher(Thread.currentThread().getThreadGroup(),args[0]);
        System.setSecurityManager(sm);
        gremlins = new ThreadGroup("Gremlins");
        sun.tools.javac.Main compiler = 
                  new sun.tools.javac.Main(System.out, "javac");
        GremlinLoader cl = new GremlinLoader();
        try
        {
            System.out.println("Compiling...");
            String[] file = { "Test.java" };
            if (! compiler.compile(file)) return;
            System.out.println("...compilation completed.");
            System.out.println("Loading class...");
            Class c = null;
            System.out.println("Calling loadClass()...");
            c = cl.loadClass("Test", true);
            System.out.println("...loadClass() completed.");
            System.out.println("...loaded.");
            System.out.println("Creating new instance...");
            Runnable test = (Runnable)c.newInstance();
            System.out.println("...new instance created.");
            // Create a new thread for test, in the gremlin's thread group.
            // Within that thread group, they can do whatever they want!
            Thread t = new Thread(gremlins, test);
            t.start();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
/** Class loader, for loading classes we generate dynamically at run time. */
class GremlinLoader extends ClassLoader
{
    public Class loadClass(String name, boolean resolve) 
                                                 throws ClassNotFoundException
    {
        System.out.println("Attempting to load class " + name);
        Class c;
        try
        {
            String fname = name + ".class";
            java.io.File file = new java.io.File(fname);
            if (! file.exists())
            {
                System.out.println("Loader could not find class " + name);
                c = findLoadedClass(name);      // comment out for JDK 1.02
                if (c == null) c = findSystemClass(name);   
                                                // comment out for JDK 1.02
                if (resolve) resolveClass(c);   // comment out for JDK 1.02
                return c;                       // comment out for JDK 1.02
                //return null;              // uncomment this for JDK 1.02
            }
            System.out.println("   (fname=" + fname + ")");
            java.io.FileInputStream f = new java.io.FileInputStream(fname);
            byte[] bytes = new byte[(int)file.length()];
            int n = f.read(bytes);
            System.out.println("  (read " + n + " bytes)");
            c = defineClass(bytes, 0, bytes.length);
            System.out.println("   (class defined)");
            if (resolve) resolveClass(c);
            System.out.println("   (class resolved)");
            return c;
        }
        catch (ClassNotFoundException cex)
        {
            c = findLoadedClass(name);
            if (resolve) resolveClass(c);
            return c;
        }
        catch (Exception ex)
        {
            System.out.println("Loader could not load " + name);
            ex.printStackTrace();
            return null;
       }
    }
}




