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

org.neo4j.codegen.CodeGenerator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.codegen;

import static java.util.Objects.requireNonNull;
import static org.neo4j.codegen.ByteCodeVisitor.DO_NOTHING;
import static org.neo4j.codegen.CodeGenerationStrategy.codeGenerator;
import static org.neo4j.codegen.TypeReference.OBJECT;
import static org.neo4j.codegen.TypeReference.typeReference;
import static org.neo4j.codegen.TypeReference.typeReferences;

import org.neo4j.util.Preconditions;
import org.neo4j.util.VisibleForTesting;

/**
 * Do you also want to generate code? Start here.
 *
 * CodeGenerator is the entry point of code generation. I allows generation of multiple
 * dependent classes per compilation unit.
 * 

* Example use: * *

 *      ClassGenerator c1 = generator.generateClass(...)
 *
 *      // start generating class 1 using the c1 generator
 *
 *      ClassGenerator c2 = generator.generateClass(...)
 *
 *      // generate class 2 using c2
 *
 *      ClassHandle c2handle = c2.handle
 *      c2.close()
 *
 *      // use c2handle to generate newInstance calls in c1
 *
 *      ClassHandle c1handle = c1.handle
 *      c1.close()
 *
 *      c1handle.loadClass // Forces compilation on the whole unit (c1 + c2), which
 *                         // will stage them for loading in {@link CodeLoader}. c1 will
 *                         // then immediately be loaded and the class object returned.
 *                         // Sometime later when c2 is needed, it will also be loaded.
 *                         // This could be once a c1 instance is executed, and need to
 *                         // instantiate a c2, or if we reflectively access c1 for example.
 * 
*/ public abstract class CodeGenerator { private final CodeLoader loader; private long currentCompilationUnit; private long openClassCount; private ByteCodeVisitor byteCodeVisitor = DO_NOTHING; public static CodeGenerator generateCode(CodeGenerationStrategy strategy, CodeGeneratorOption... options) throws CodeGenerationNotSupportedException { return generateCode(Thread.currentThread().getContextClassLoader(), strategy, options); } public static CodeGenerator generateCode( ClassLoader loader, CodeGenerationStrategy strategy, CodeGeneratorOption... options) throws CodeGenerationNotSupportedException { return codeGenerator(requireNonNull(loader, "ClassLoader"), strategy, options); } public CodeGenerator(ClassLoader loader) { this.loader = new CodeLoader(loader); } private synchronized ClassHandle openClass(String packageName, String name, TypeReference parent) { openClassCount++; return new ClassHandle(packageName, name, parent, this, currentCompilationUnit); } synchronized void closeClass() { openClassCount--; } @VisibleForTesting public void setByteCodeVisitor(ByteCodeVisitor visitor) { this.byteCodeVisitor = visitor; } // GENERATE public ClassGenerator generateClass(String packageName, String name, Class firstInterface, Class... more) { return generateClass(packageName, name, typeReferences(firstInterface, more)); } public ClassGenerator generateClass(Class base, String packageName, String name, Class... interfaces) { return generateClass(typeReference(base), packageName, name, typeReferences(interfaces)); } public ClassGenerator generateClass(String packageName, String name, TypeReference... interfaces) { return generateClass(OBJECT, packageName, name, interfaces); } public ClassGenerator generateClass( TypeReference base, String packageName, String name, TypeReference... interfaces) { return generateClass(openClass(packageName, name, base), base, interfaces); } private ClassGenerator generateClass(ClassHandle handle, TypeReference base, TypeReference... interfaces) { return new ClassGenerator(handle, generate(handle, base, interfaces)); } protected abstract ClassWriter generate(TypeReference type, TypeReference base, TypeReference... interfaces); // COMPILE AND LOAD protected abstract Iterable compile(ClassLoader classpathLoader) throws CompilationFailureException; synchronized Class loadClass(String name, long generation) throws CompilationFailureException { compileAndStageForLoading(generation); try { return loader.findClass(name); } catch (ClassNotFoundException e) { throw new IllegalStateException("Could not find defined class.", e); } } synchronized Class loadAnonymousClass(String name, long generation) throws CompilationFailureException { compileAndStageForLoading(generation); try { return loader.defineHiddenClass(name); } catch (Throwable e) { throw new IllegalStateException("Could not find defined class.", e); } } /** * Compile all classes in the target compilation unit, and stage them for loading. * * If the target compilation unit has already been compiled ({@code compilationUnit < this.compilationUnit}), * this method does nothing. * * @param compilationUnit the target compilation unit */ private void compileAndStageForLoading(long compilationUnit) throws CompilationFailureException { Preconditions.checkState( compilationUnit <= this.currentCompilationUnit, "Future compilation units are not supported"); if (compilationUnit == this.currentCompilationUnit) { Preconditions.checkState(openClassCount == 0, "Compilation has not completed."); this.currentCompilationUnit++; loader.stageForLoading(compile(loader.getParent()), byteCodeVisitor); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy