All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.codehaus.janino.SimpleCompiler Maven / Gradle / Ivy


/*
 * Janino - An embedded Java[TM] com.hazelcast.com.iler
 *
 * Copyright (c) 2001-2010 Arno Unkrig. All rights reserved.
 * Copyright (c) 2015-2016 TIBCO Software Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 * following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 *       following disclaimer in the documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.hazelcast.org.codehaus.janino;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.CompileException;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.Cookable;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.ErrorHandler;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.ICookable;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.ISimpleCompiler;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.Location;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.Sandbox;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.WarningHandler;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.nullanalysis.Nullable;
import com.hazelcast.org.codehaus.janino.Java.Type;
import com.hazelcast.org.codehaus.janino.Visitor.AtomVisitor;
import com.hazelcast.org.codehaus.janino.Visitor.TypeVisitor;
import com.hazelcast.org.codehaus.janino.util.ClassFile;

/**
 * To set up a {@link SimpleCompiler} object, proceed as described for {@link ISimpleCompiler}. Alternatively, a number
 * of "convenience constructors" exist that execute the described steps instantly.
 */
public
class SimpleCompiler extends Cookable implements ISimpleCompiler {

    private static final Logger LOGGER = Logger.getLogger(SimpleCompiler.class.getName());

    private ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();

    // Set while "cook()"ing.
    @Nullable private ClassLoaderIClassLoader classLoaderIClassLoader;

    @Nullable private ClassLoader    result;
    @Nullable private ErrorHandler   optionalCompileErrorHandler;
    @Nullable private WarningHandler optionalWarningHandler;

    private boolean debugSource = Boolean.getBoolean(ICookable.SYSTEM_PROPERTY_SOURCE_DEBUGGING_ENABLE);
    private boolean debugLines  = this.debugSource;
    private boolean debugVars   = this.debugSource;

    @Nullable private Permissions permissions;

    private EnumSet options = EnumSet.noneOf(JaninoOption.class);

    public static void // SUPPRESS CHECKSTYLE JavadocMethod
    main(String[] args) throws Exception {
        if (args.length >= 1 && "-help".equals(args[0])) {
            System.out.println("Usage:");
            System.out.println("    com.hazelcast.org.codehaus.janino.SimpleCompiler   {  }");
            System.out.println("Reads a com.hazelcast.com.ilation unit from the given  and invokes method");
            System.out.println("\"public static void main(String[])\" of class , passing the");
            System.out.println("given s.");
            System.exit(1);
        }

        if (args.length < 2) {
            System.err.println("Source file and/or class name missing; try \"-help\".");
            System.exit(1);
        }

        // Get source file.
        String sourceFileName = args[0];

        // Get class name.
        String className = args[1];

        // Get arguments.
        String[] arguments = new String[args.length - 2];
        System.arraycopy(args, 2, arguments, 0, arguments.length);

        // Compile the source file.
        ClassLoader cl = new SimpleCompiler(sourceFileName, new FileInputStream(sourceFileName)).getClassLoader();

        // Load the class.
        Class c = cl.loadClass(className);

        // Invoke the "public static main(String[])" method.
        Method m = c.getMethod("main", String[].class);
        m.invoke(null, (Object) arguments);
    }

    /**
     * Equivalent to
     * 
     *     SimpleCompiler sc = new SimpleCompiler();
     *     sc.cook(optionalFileName, in);
     * 
* * @see #SimpleCompiler() * @see Cookable#cook(String, Reader) */ public SimpleCompiler(@Nullable String optionalFileName, Reader in) throws IOException, CompileException { this.cook(optionalFileName, in); } /** * Equivalent to *
     *     SimpleCompiler sc = new SimpleCompiler();
     *     sc.cook(optionalFileName, is);
     * 
* * @see #SimpleCompiler() * @see Cookable#cook(String, InputStream) */ public SimpleCompiler(@Nullable String optionalFileName, InputStream is) throws IOException, CompileException { this.cook(optionalFileName, is); } /** * Equivalent to *
     *     SimpleCompiler sc = new SimpleCompiler();
     *     sc.cook(fileName);
     * 
* * @see #SimpleCompiler() * @see Cookable#cookFile(String) */ public SimpleCompiler(String fileName) throws IOException, CompileException { this.cookFile(fileName); } /** * Equivalent to *
     *     SimpleCompiler sc = new SimpleCompiler();
     *     sc.setParentClassLoader(optionalParentClassLoader);
     *     sc.cook(scanner);
     * 
* * @see #SimpleCompiler() * @see #setParentClassLoader(ClassLoader) * @see Cookable#cook(Reader) */ public SimpleCompiler(Scanner scanner, @Nullable ClassLoader optionalParentClassLoader) throws IOException, CompileException { this.setParentClassLoader(optionalParentClassLoader); this.cook(scanner); } public SimpleCompiler() {} @Override public void setParentClassLoader(@Nullable ClassLoader optionalParentClassLoader) { this.parentClassLoader = ( optionalParentClassLoader != null ? optionalParentClassLoader : Thread.currentThread().getContextClassLoader() ); } @Override public void setDebuggingInformation(boolean debugSource, boolean debugLines, boolean debugVars) { this.debugSource = debugSource; this.debugLines = debugLines; this.debugVars = debugVars; } /** * Scans, parses and com.hazelcast.com.iles a given com.hazelcast.com.ilation unit from the given {@link Reader}. After com.hazelcast.com.letion, {@link * #getClassLoader()} returns a {@link ClassLoader} that allows for access to the com.hazelcast.com.iled classes. */ @Override public final void cook(@Nullable String optionalFileName, Reader r) throws CompileException, IOException { this.cook(new Scanner(optionalFileName, r)); } /** * Scans, parses and com.hazelcast.com.iles a given com.hazelcast.com.ilation unit from the given scanner. After com.hazelcast.com.letion, {@link * #getClassLoader()} returns a {@link ClassLoader} that allows for access to the com.hazelcast.com.iled classes. */ public void cook(Scanner scanner) throws CompileException, IOException { this.com.hazelcast.com.ileToClassLoader(new Parser(scanner).parseCompilationUnit()); } /** * Cooks this com.hazelcast.com.ilation unit directly and invokes {@link #cook(ClassFile[])}. */ public void cook(Java.CompilationUnit com.hazelcast.com.ilationUnit) throws CompileException { SimpleCompiler.LOGGER.entering(null, "cook", com.hazelcast.com.ilationUnit); ClassFile[] classFiles; IClassLoader icl = (this.classLoaderIClassLoader = new ClassLoaderIClassLoader(this.parentClassLoader)); try { // Compile com.hazelcast.com.ilation unit to class files. UnitCompiler unitCompiler = new UnitCompiler(com.hazelcast.com.ilationUnit, icl).options(this.options); unitCompiler.setCompileErrorHandler(this.optionalCompileErrorHandler); unitCompiler.setWarningHandler(this.optionalWarningHandler); classFiles = unitCompiler.com.hazelcast.com.ileUnit(this.debugSource, this.debugLines, this.debugVars); } finally { this.classLoaderIClassLoader = null; } this.cook(classFiles); } /** * Serializes the given classFiles as bytecode, stores them in a map, and then invokes {@link * #cook(Map)}. */ public void cook(ClassFile[] classFiles) { // Convert the class files to bytes and store them in a Map. final Map classes = new HashMap(); for (ClassFile cf : classFiles) { classes.put(cf.getThisClassName(), cf.toByteArray()); } this.cook(classes); } /** * Creates a {@link ClassLoader} that loads the given classes (lazily), and makes that class loader * available through {@link #getClassLoader()}. * * @param classes Maps fully qualified classes names to bytecodes */ public void cook(final Map classes) { // Create a ClassLoader that loads the generated classes. ClassLoader cl = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() { @Override public ClassLoader run() { return new ByteArrayClassLoader( classes, // classes SimpleCompiler.this.parentClassLoader // parent ); } }); // Apply any configured permissions. if (this.permissions != null) Sandbox.confine(cl, this.permissions); this.result = cl; } @Override public ClassLoader getClassLoader() { if (this.getClass() != SimpleCompiler.class) { throw new IllegalStateException("Must not be called on derived instances"); } return this.assertCooked(); } @Override public void setPermissions(Permissions permissions) { this.permissions = permissions; } @Override public void setNoPermissions() { this.setPermissions(new Permissions()); } /** * Two {@link SimpleCompiler}s are regarded equal iff *
    *
  • Both are objects of the same class (e.g. both are {@link ScriptEvaluator}s) *
  • Both generated functionally equal classes as seen by {@link ByteArrayClassLoader#equals(Object)} *
*/ @Override public boolean equals(@Nullable Object o) { if (!(o instanceof SimpleCompiler)) return false; SimpleCompiler that = (SimpleCompiler) o; if (this.getClass() != that.getClass()) return false; return this.assertCooked().equals(that.assertCooked()); } @Override public int hashCode() { return this.parentClassLoader.hashCode(); } @Override public void setCompileErrorHandler(@Nullable ErrorHandler optionalCompileErrorHandler) { this.optionalCompileErrorHandler = optionalCompileErrorHandler; } @Override public void setWarningHandler(@Nullable WarningHandler optionalWarningHandler) { this.optionalWarningHandler = optionalWarningHandler; } /** * @return A reference to the currently effective com.hazelcast.com.ilation options; changes to it take * effect immediately */ public EnumSet options() { return this.options; } /** * Sets the options for all future com.hazelcast.com.ilations. */ public SimpleCompiler options(EnumSet options) { this.options = options; return this; } /** * Wraps a reflection {@link Class} in a {@link Java.Type} object. */ @Nullable protected Java.Type optionalClassToType(final Location location, @Nullable final Class clazz) { if (clazz == null) return null; return this.classToType(location, clazz); } /** * Wraps a reflection {@link Class} in a {@link Java.Type} object. */ protected Java.Type classToType(final Location location, final Class clazz) { // Can't use a SimpleType here because the classLoaderIClassLoader is not yet set up. Instead, create a // Type that lazily creates a delegate Type at COMPILE TIME. return new Java.Type(location) { @Nullable private Java.SimpleType delegate; @Override @Nullable public R accept(AtomVisitor visitor) throws EX { return visitor.visitType(this.getDelegate()); } @Override @Nullable public R accept(TypeVisitor visitor) throws EX { return this.getDelegate().accept(visitor); } @Override public String toString() { return this.getDelegate().toString(); } private Type getDelegate() { if (this.delegate != null) return this.delegate; ClassLoaderIClassLoader icl = SimpleCompiler.this.classLoaderIClassLoader; assert icl != null; IClass iClass; try { iClass = icl.loadIClass( Descriptor.fromClassName(clazz.getName()) ); } catch (ClassNotFoundException ex) { throw new InternalCompilerException("Loading IClass \"" + clazz.getName() + "\": " + ex); } if (iClass == null) { throw new InternalCompilerException( "Cannot load class '" + clazz.getName() + "' through the parent loader" ); } // Verify that the class loaders match. IClass iClass2 = iClass; Class class2 = clazz; for (;;) { IClass ct = iClass2.getComponentType(); if (ct == null) { if (class2.getComponentType() != null) { throw new InternalCompilerException("Array type/class inconsistency"); } break; } iClass2 = ct; class2 = class2.getComponentType(); if (class2 == null) throw new InternalCompilerException("Array type/class inconsistency"); } if (class2.isPrimitive()) { if (!iClass2.isPrimitive()) { throw new InternalCompilerException("Primitive type/class inconsistency"); } } else { if (iClass2.isPrimitive()) { throw new InternalCompilerException("Primitive type/class inconsistency"); } if (((ReflectionIClass) iClass2).getClazz() != class2) { throw new InternalCompilerException( "Class '" + class2.getName() + "' was loaded through a different loader" ); } } return (this.delegate = new Java.SimpleType(location, iClass)); } }; } /** * Converts an array of {@link Class}es into an array of{@link Java.Type}s. */ protected Java.Type[] classesToTypes(Location location, @Nullable Class[] classes) { if (classes == null) return new Java.Type[0]; 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; } /** * Compiles the given com.hazelcast.com.ilation unit. (A "com.hazelcast.com.ilation unit" is typically the contents of a Java source file.) * * @param com.hazelcast.com.ilationUnit The parsed com.hazelcast.com.ilation unit * @return The {@link ClassLoader} into which the com.hazelcast.com.iled classes were defined * @throws CompileException */ protected final ClassLoader com.hazelcast.com.ileToClassLoader(Java.CompilationUnit com.hazelcast.com.ilationUnit) throws CompileException { assert this.classLoaderIClassLoader == null; this.cook(com.hazelcast.com.ilationUnit); return this.assertCooked(); } /** * @return The class loader created when this {@link SimpleCompiler} was {@link #cook(Reader)}ed */ private ClassLoader assertCooked() { ClassLoader cl = this.result; if (cl == null) throw new IllegalStateException("Must only be called after \"cook()\""); return cl; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy