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