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

net.sandius.rembulan.load.ChunkClassLoader Maven / Gradle / Ivy

There is a newer version: 1.0.3
Show newest version
/*
 * Copyright 2016 Miroslav Janíček
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.sandius.rembulan.load;

import net.sandius.rembulan.util.ByteVector;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Class loader for Lua chunks.
 */
public class ChunkClassLoader extends ClassLoader {

	private final Map installed;
	private final Set loaded;

	/**
	 * Constructs a new {@code ChunkClassLoader} with the specified class loader {@code parent}
	 * as its parent in the class loading hierarchy.
	 *
	 * @param parent  the parent class loader
	 */
	public ChunkClassLoader(ClassLoader parent) {
		super(parent);
		this.installed = new HashMap<>();
		this.loaded = new HashSet<>();
	}

	/**
	 * Constructs a new {@code ChunkClassLoader} using the class loader that loaded
	 * the {@code ChunkClassLoader} class as the parent class loader.
	 */
	public ChunkClassLoader() {
		this(ChunkClassLoader.class.getClassLoader());
	}

	/**
	 * Installs the compiled chunk {@code chunk} into this chunk class loader, returning
	 * the class name of the main class in {@code chunk}.
	 *
	 * 

Once this method returns (and not before), the returned main class may be loaded * and instantiated.

* * @param chunk chunk to be installed, must not be {@code null} * @return the class name of the main class in {@code chunk} * * @throws NullPointerException if {@code chunk} is {@code null} * @throws IllegalStateException if a class with the same name as a class in {@code chunk} * has already been installed into this chunk class loader * */ public String install(CompiledChunk chunk) { Map classes = chunk.classMap(); synchronized (this) { for (String name : classes.keySet()) { if (installed.containsKey(name) || loaded.contains(name)) { // class already installed throw new IllegalStateException("Class already installed: " + name); } installed.put(name, classes.get(name)); } String main = chunk.mainClassName(); assert (installed.containsKey(main)); return main; } } /** * Returns {@code true} if the Lua function class with the given {@code className} * has been installed into this {@code ChunkClassLoader} or has already been loaded by it. * * @param className class name of the Lua function, must not be {@code null} * @return {@code true} iff the class {@code className} has been installed into this * class loader or loaded by it * @throws NullPointerException if {@code className} is {@code null} */ public boolean isInstalled(String className) { synchronized (this) { return installed.containsKey(className) || loaded.contains(className); } } @Override protected Class findClass(String name) throws ClassNotFoundException { synchronized (this) { ByteVector bv = installed.remove(name); if (bv != null) { loaded.add(name); return defineClass(name, bv); } else { throw new ClassNotFoundException(name); } } } private Class defineClass(String name, ByteVector bytes) { byte[] byteArray = bytes.copyToNewArray(); return defineClass(name, byteArray, 0, byteArray.length); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy