001/* 002 * Copyright (c) 2012-2018 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others 003 * 004 * This program and the accompanying materials are made available under the 005 * terms of the Eclipse Public License 2.0 which is available at 006 * http://www.eclipse.org/legal/epl-2.0. 007 * 008 * SPDX-License-Identifier: EPL-2.0 009 */ 010 011package org.eclipse.golo.compiler; 012 013import java.io.InputStream; 014import java.util.List; 015 016import gololang.ir.GoloModule; 017 018/** 019 * Provides a facility to dynamically load Golo source code and access the generated code from a dedicated class loader. 020 * <p> 021 * Golo source files can be compiled and the resulting JVM bytecode be injected into the class loader. It is important 022 * to note that this class loader definition is not thread safe. 023 * <p> 024 * This class loader does not support reloading. Attempts to load source files that may produce the same bytecode 025 * definitions will resulting in exceptions. 026 */ 027public class GoloClassLoader extends ClassLoader { 028 029 private final GoloCompiler compiler; 030 031 /** 032 * Creates a class loader from a parent. 033 * 034 * @param parent the parent classloader. 035 */ 036 public GoloClassLoader(ClassLoader parent) { 037 super(parent); 038 compiler = new GoloCompiler(); 039 } 040 041 /** 042 * Creates a class loader from the default parent. 043 */ 044 public GoloClassLoader() { 045 super(); 046 compiler = new GoloCompiler(); 047 } 048 049 public GoloCompiler getCompiler() { 050 return this.compiler; 051 } 052 053 /** 054 * Compiles and loads the resulting JVM bytecode for a Golo source file. 055 * 056 * @param goloSourceFilename the source file name. 057 * @param sourceCodeInputStream the source input stream. 058 * @return the class matching the Golo module defined in the source. 059 * @throws GoloCompilationException if either of the compilation phase failed. 060 */ 061 public synchronized Class<?> load(String goloSourceFilename, InputStream sourceCodeInputStream) throws GoloCompilationException { 062 return load(compiler.compile(goloSourceFilename, sourceCodeInputStream)); 063 } 064 065 /** 066 * Compiles and loads the resulting JVM bytecode for a Golo module IR. 067 * 068 * @param goloSourceFilename the source file name. 069 * @param module the Golo module IR to load. 070 * @return the class matching the Golo module defined in the IR. 071 * @throws GoloCompilationException if either of the compilation phase failed. 072 */ 073 public synchronized Class<?> load(String goloSourceFilename, GoloModule module) { 074 compiler.refine(module); 075 return load(compiler.generate(module, goloSourceFilename)); 076 } 077 078 private Class<?> load(List<CodeGenerationResult> results) { 079 Class<?> lastClassIsModule = null; 080 for (CodeGenerationResult result : results) { 081 byte[] bytecode = result.getBytecode(); 082 lastClassIsModule = defineClass(null, bytecode, 0, bytecode.length); 083 } 084 return lastClassIsModule; 085 } 086}