Package st.redline.classloader

Source Code of st.redline.classloader.SmalltalkClassLoader$DelegateClassLoader

/* Redline Smalltalk, Copyright (c) James C. Ladd. All rights reserved. See LICENSE in the root of this distribution. */
package st.redline.classloader;

// ------------------------------------------------------------------
// This ClassLoader uses delegation to make resetting the ClassLoader
// easy, and to provide tracing when requested.

import st.redline.compiler.ast.Block;
import st.redline.lang.*;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;

public class SmalltalkClassLoader extends ClassLoader {

    public int BLOCK_NUMBER = 0;
    public ProtoObject METACLASS;
    public ProtoObject NIL;
    public ProtoObject TRUE;
    public ProtoObject FALSE;
    public final Map<String, Object> blocksToBeCompiled = new Hashtable<String, Object>();
    public final Map<String, ProtoObject> blocks = new Hashtable<String, ProtoObject>();
    public final Map<String, String> blockReturnTypes = new HashMap<String, String>();

    private final Stack<EigenClass> eigenClasses;
    private final Map<String, ProtoObject> symbols;
    private final DelegateClassLoader delegate;
    private final Bootstrapper bootstrapper;

    private boolean bootstrapping = true;
    private ProtoObject protoObject;

    public SmalltalkClassLoader(ClassBuilder classBuilder, Bootstrapper bootstrapper, boolean trace) {
        this.eigenClasses = new Stack<EigenClass>();
        this.symbols = new HashMap<String, ProtoObject>();
        this.bootstrapper = bootstrapper;
        delegate = trace ? tracingClassLoader(classBuilder) : simpleClassLoader(classBuilder);
    }

    public void bootstrap() throws Exception {
        Thread.currentThread().setContextClassLoader(this);
        bootstrapper.bootstrap(this);
    }

    public void stoppedBootstrapping() {
        bootstrapping = false;
        isBootstrapping();
    }

    public boolean isBootstrapping() {
        return bootstrapping;
    }

    public synchronized void currentEigenClass(EigenClass eigenClass) {
        eigenClasses.push(eigenClass);
    }

    public synchronized EigenClass currentEigenClass() {
        return eigenClasses.peek();
    }

    public synchronized void removeEigenClass() {
        eigenClasses.pop();
    }

    public synchronized String currentPackage() {
        return currentEigenClass().packageName();
    }

    public DelegateClassLoader simpleClassLoader(ClassBuilder classBuilder) {
        return new SimpleClassLoader(this, classBuilder);
    }

    public DelegateClassLoader tracingClassLoader(ClassBuilder classBuilder) {
        return new TracingClassLoader(this, classBuilder);
    }

    public Class loadClass(String name) throws ClassNotFoundException {
        return delegate.loadClass(name);
    }

    public Class defineClass(byte[] classBytes) {
        return defineClass(classBytes, null);
    }

    public Class defineClass(byte[] classBytes, String name) {
        return defineClass(name, classBytes, 0, classBytes.length);
    }

    public DelegateClassLoader delegate() {
        return delegate;
    }

    public void registerProtoObject(ProtoClass protoObject) {
        this.protoObject = protoObject;
        registerSmalltalkClass("ProtoObject", protoObject);
    }

    public void registerSmalltalkClass(String name, ProtoObject aClass) {
        delegate.registerSmalltalkClass(name, aClass);
    }

    public ProtoObject loadSmalltalkClass(String name, boolean resolve) throws ClassNotFoundException {
        return delegate.loadSmalltalkClass(name, resolve);
    }

    public ProtoObject loadSmalltalkClass(String name) throws ClassNotFoundException {
        return delegate.loadSmalltalkClass(name, true);
    }

    public boolean isInternedSymbol(String symbol) {
        return symbols.containsKey(symbol);
    }

    public ProtoObject internedSymbolAt(String symbol) {
        return symbols.get(symbol);
    }

    public void internSymbolAtPut(String symbol, ProtoObject symbolObject) {
        symbols.put(symbol, symbolObject);
    }

    public void registerBlockToBeCompiled(Block block, String fullBlockClassName) {
        if (blocksToBeCompiled.containsKey(fullBlockClassName))
            throw new IllegalStateException("Block to be compiled registered twice: " + fullBlockClassName);
        blocksToBeCompiled.put(fullBlockClassName, block);
    }

    public ProtoObject loadSmalltalkBlock(String name, PrimContext context) {
        if (blocks.containsKey(name))
            return createBlockInstance(blocks.get(name), context);
        Block block = (Block) blocksToBeCompiled.remove(name);
        if (block == null)
            throw new IllegalStateException("Block to be compiled '" + name + "' not found.");
        block.accept(block.analyser());
        try {
            ProtoObject newblock = (ProtoObject) defineClass(block.classBytes()).newInstance();
            blocks.put(name, newblock);
            return createBlockInstance(newblock, context);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected ProtoObject createBlockInstance(ProtoObject block, PrimContext context) {
        if (block.isMethodBlock())
            return block;
        try {
            Constructor constructor = block.getClass().getConstructor(PrimContext.class);
            return (ProtoBlock) constructor.newInstance(context);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Class loadBlockReturn(String blockReturnType) throws ClassNotFoundException {
        return super.loadClass(blockReturnType);
    }

    public boolean hasBlockReturnType(String fullyQualifiedClassName) {
        return blockReturnTypes.containsKey(fullyQualifiedClassName);
    }

    public void addBlockReturnType(String blockReturnTypeName) {
        blockReturnTypes.put(blockReturnTypeName, blockReturnTypeName);
    }

    // ----------------------------

    interface DelegateClassLoader {
        Class loadClass(String name) throws ClassNotFoundException;
        void registerSmalltalkClass(String name, ProtoObject aClass);
        ProtoObject loadSmalltalkClass(String name, boolean resolve) throws ClassNotFoundException;
    }

    // ----------------------------------
    // A simple non-tracing class loader.

    class SimpleClassLoader implements DelegateClassLoader {

        private final SmalltalkClassLoader owner;
        protected final ClassBuilder classBuilder;
        protected final Map<String, ProtoObject> classes;

        public SimpleClassLoader(SmalltalkClassLoader owner, ClassBuilder classBuilder) {
            this.owner = owner;
            this.classBuilder = classBuilder;
            this.classes = new HashMap<String, ProtoObject>();
        }

        public Class loadClass(String name) throws ClassNotFoundException {
            return findClass(name);
        }

        protected Class findClass(String name) throws ClassNotFoundException {
            byte[] classBytes = buildClass(name);
            if (classBytes != null)
                return defineClass(classBytes);
            /* check if system class */
            try { return findSystemClass(name); } catch (Exception e) {}
            return null;
        }

        protected Class defineClass(byte[] classBytes) {
            return owner.defineClass(classBytes);
        }

        protected byte[] buildClass(String name) {
            return classBuilder.build(name);
        }

        public void registerSmalltalkClass(String name, ProtoObject aClass) {
            if (classes.containsKey(name))
                System.err.println("WARNING: '" + name + "' registered twice.");
            classes.put(name, aClass);
        }

        public ProtoObject loadSmalltalkClass(String name, boolean resolve) throws ClassNotFoundException {
            ProtoObject aClass = classes.get(name);
            if (aClass != null)
                return aClass;
            if (resolve)
                // NOTE: We do not currently cache classes when found.
                try {
                    Class javaClass = findClass(name);
                    if (javaClass != null)
                        return (ProtoObject) javaClass.newInstance();
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new ClassNotFoundException(name + " " + e.getMessage());
                }
            return null;
        }
    }

    // -------------------------------------------------
    // A tracing class loader - turn on with command line option: -verbose:stclass

    class TracingClassLoader extends SimpleClassLoader {

        public TracingClassLoader(SmalltalkClassLoader owner, ClassBuilder classBuilder) {
            super(owner, classBuilder);
        }

        public Class loadClass(String name) throws ClassNotFoundException {
            System.out.println("[LoadClass " + name + "]");
            return findClass(name);
        }

        protected byte[] buildClass(String name) {
            StringBuilder path = new StringBuilder();
            byte[] bytes = classBuilder.build(name, path);
            if (path.length() > 0)
                System.out.println("[Loaded " + name + " from " + path + "]");
            return bytes;
        }

        public void registerSmalltalkClass(String name, ProtoObject aClass) {
            System.out.println("[Registering Smalltalk Class " + name + " as " + aClass + "]");
            super.registerSmalltalkClass(name, aClass);
        }

        public ProtoObject loadSmalltalkClass(String name, boolean resolve) throws ClassNotFoundException {
            System.out.println("[Smalltalk LoadClass " + name + "]");
            return super.loadSmalltalkClass(name, resolve);
        }
    }
}
TOP

Related Classes of st.redline.classloader.SmalltalkClassLoader$DelegateClassLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.