Package net.janino

Source Code of net.janino.EvaluatorBase

/*
* Janino - An embedded Java[TM] compiler
* Copyright (C) 2001-2004 Arno Unkrig
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information:
*   Arno Unkrig
*   Ferdinand-Miller-Platz 10
*   80335 Muenchen
*   Germany
*   http://www.janino.net
*   maintainer@janino.net
*/

package net.janino;

import java.io.*;

import net.janino.util.ClassFile;

/**
* Utilities for the various "...Evaluator" classes.
*/

public class EvaluatorBase {
    private final static boolean DEBUG = false;

    protected EvaluatorBase(
        ClassLoader optionalClassLoader // null == use current thread's context class loader
    ) {
        ClassLoader cl = (
            optionalClassLoader == null ?
            Thread.currentThread().getContextClassLoader() :
            optionalClassLoader
        );
        this.byteArrayClassLoader = (
            cl instanceof ByteArrayClassLoader ?
            (ByteArrayClassLoader) cl :
            new ByteArrayClassLoader(cl)
        );
        this.classLoaderIClassLoader = new ClassLoaderIClassLoader(cl);
    }

    /**
     * Parse as many import declarations as possible for the given
     * {@link Java.CompilationUnit}.
     * @param compilationUnit
     * @param scanner Source of tokens
     * @throws Scanner.ScanException
     * @throws Parser.ParseException
     * @throws IOException
     */
    protected void parseImportDeclarations(
        Java.CompilationUnit compilationUnit,
        Scanner              scanner
    ) throws Scanner.ScanException, Parser.ParseException, IOException {
        Parser parser = new Parser(scanner);
        while (scanner.peek().isKeyword("import")) parser.parseImportDeclaration(compilationUnit);
    }

    /**
     * To the given {@link Java.CompilationUnit}, add
     * <ul>
     *   <li>A class declaration with the given name, superclass and interfaces
     *   <li>A method declaration with the given return type, name, parameter
     *       names and values and thrown exceptions
     * </ul>
     * @param location
     * @param compilationUnit
     * @param className
     * @param optionalExtendedType (null == {@link Object})
     * @param implementedTypes
     * @return The created {@link Java.ClassDeclaration} object
     * @throws Parser.ParseException
     * @throws Scanner.ScanException
     * @throws IOException
     */
    protected Java.PackageMemberClassDeclaration addPackageMemberClassDeclaration(
        Scanner.Location     location,
        Java.CompilationUnit compilationUnit,
        String               className,
        Class                optionalExtendedType,
        Class[]              implementedTypes
    ) throws Parser.ParseException {
        Java.PackageMemberClassDeclaration tlcd = new Java.PackageMemberClassDeclaration(
            location,                                         // location
            compilationUnit,                                  // declaringCompilationUnit
            Mod.PUBLIC,                                       // modifiers
            className,                                        // name
            this.classToType(location, optionalExtendedType), // optionalExtendedType
            this.classesToTypes(location, implementedTypes)   // implementedTypes
        );
        compilationUnit.addPackageMemberTypeDeclaration(tlcd);
        return tlcd;
    }

    /**
     * To the given {@link Java.CompilationUnit}, add
     * <ul>
     *   <li>A package member class declaration with the given name, superclass and interfaces
     *   <li>A public method declaration with the given return type, name, parameter
     *       names and values and thrown exceptions
     *   <li>A block
     * </ul>
     * @param location
     * @param compilationUnit
     * @param className
     * @param optionalExtendedType (null == {@link Object})
     * @param implementedTypes
     * @param staticMethod Whether the method should be declared "static"
     * @param returnType Return type of the declared method
     * @param methodName
     * @param parameterNames
     * @param parameterTypes
     * @param thrownExceptions
     * @return The created {@link Java.Block} object
     * @throws Parser.ParseException
     * @throws Scanner.ScanException
     * @throws IOException
     */
    protected Java.Block addClassMethodBlockDeclaration(
        Scanner.Location     location,
        Java.CompilationUnit compilationUnit,
        String               className,
        Class                optionalExtendedType,
        Class[]              implementedTypes,
        boolean              staticMethod,
        Class                returnType,
        String               methodName,
        String[]             parameterNames,
        Class[]              parameterTypes,
        Class[]              thrownExceptions
    ) throws Parser.ParseException {
        if (parameterNames.length != parameterTypes.length) throw new RuntimeException("Lengths of \"parameterNames\" and \"parameterTypes\" do not match");

        // Add class declaration.
        Java.ClassDeclaration cd = this.addPackageMemberClassDeclaration(
            location,
            compilationUnit,
            className, optionalExtendedType, implementedTypes
        );

        // Add method declaration.
        Java.MethodDeclarator md = new Java.MethodDeclarator(
            location,                                        // location
            cd,                                              // declaringClassOrInterface
            (                                                // modifiers
                staticMethod ?
                (short) (Mod.PUBLIC | Mod.STATIC) :
                (short) Mod.PUBLIC
            ),
            this.classToType(location, returnType),         // type
            methodName,                                      // name
            this.makeFormalParameters(                      // formalParameters
                location,
                parameterNames, parameterTypes
            ),
            this.classesToTypes(location, thrownExceptions) // thrownExceptions
        );
        cd.addDeclaredMethod(md);

        // Add block as method body.
        Java.Block b = new Java.Block(location, (Java.Scope) md);
        md.setBody(b);

        return b;
    }

    /**
     * Wrap a reflection {@link Class} in a {@link Java.Type} object.
     */
    protected Java.Type classToType(
        Scanner.Location location,
        final Class      optionalClass
    ) {
        if (optionalClass == null) return null;

        return new Java.SimpleType(
            location,
            this.classLoaderIClassLoader.loadIClass(Descriptor.fromClassName(optionalClass.getName()))
        );
    }

    /**
     * Convert an array of {@link Class}es into an array of{@link Java.Type}s.
     */
    protected Java.Type[] classesToTypes(
        Scanner.Location location,
        Class[]          classes
    ) {
        Java.Type[] types = new Java.Type[classes.length];
        for (int i = 0; i < classes.length; ++i) {
            types[i] = this.classToType(location, classes[i]);
        }
        return types;
    }

    /**
     * Convert name and {@link Class}-base parameters into an array of
     * {@link Java.FormalParameter}s.
     */
    protected Java.FormalParameter[] makeFormalParameters(
        Scanner.Location location,
        String[]         parameterNames,
        Class[]          parameterTypes
    ) {
        Java.FormalParameter[] res = new Java.FormalParameter[parameterNames.length];
        for (int i = 0; i < res.length; ++i) {
            res[i] = new Java.FormalParameter(
                true,                                          // finaL
                this.classToType(location, parameterTypes[i]), // type
                parameterNames[i]                              // name
            );
        }
        return res;
    }

    /**
     * Compile the given compilation unit. (A "compilation unit" is typically the contents
     * of a Java<sup>TM</sup> source file.)
     * @param compilationUnit The parsed compilation unit
     * @param debuggingInformation Any of <code>Java.DEBUGGING_*</code>
     * @return A {@link ClassLoader} object through which the compiled classes can be accessed
     * @throws Java.CompileException
     */
    protected ClassLoader compileAndLoad(
        Java.CompilationUnit compilationUnit,
        DebuggingInformation debuggingInformation
    ) throws Java.CompileException {
        if (EvaluatorBase.DEBUG) {
            UnparseVisitor.unparse(compilationUnit, new OutputStreamWriter(System.out));
        }

        // Compile compilation unit to class files.
        ClassFile[] classFiles = compilationUnit.compile(
            this.classLoaderIClassLoader, // iClassLoader
            debuggingInformation          // debuggingInformation
        );

        // Add the generated class files to the {@link ByteArrayClassLoader}.
        for (int i = 0; i < classFiles.length; ++i) {
            ClassFile cf = classFiles[i];
            String className = cf.getThisClassName();
            if (EvaluatorBase.DEBUG) System.out.println("Define class \"" + className  + "\".");
            this.byteArrayClassLoader.addClass(className, cf.toByteArray());
        }

        return this.byteArrayClassLoader;
    }

    /**
     * Compile the given compilation unit, load all generated classes, and
     * return the class with the given name.
     * @param compilationUnit
     * @param debuggingInformation TODO
     * @param newClassName The fully qualified class name
     * @return The loaded class
     * @throws Java.CompileException
     * @throws ClassNotFoundException A class with the given name was not declared in the compilation unit
     */
    protected Class compileAndLoad(
        Java.CompilationUnit compilationUnit,
        DebuggingInformation debuggingInformation,
        String               newClassName
    ) throws Java.CompileException, ClassNotFoundException {
        return this.compileAndLoad(compilationUnit, debuggingInformation).loadClass(newClassName);
    }

    private final ClassLoaderIClassLoader classLoaderIClassLoader;
    private final ByteArrayClassLoader    byteArrayClassLoader;
}
TOP

Related Classes of net.janino.EvaluatorBase

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.