Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ru.qoqqi.sandbox.classloader;
- import java.io.File;
- import java.io.IOException;
- import java.nio.file.Files;
- import java.nio.file.Path;
- import java.nio.file.Paths;
- import java.util.HashMap;
- import java.util.Map;
- public class TestClassLoader extends ClassLoader {
- /**
- * Кеш загруженных классов.
- * */
- private Map<String, Class> cache = new HashMap<>();
- /**
- * Список папок для поиска классов.
- * */
- private final String[] classPath;
- /**
- * Конструктор. Принимает список папок для поиска классов.
- * */
- public TestClassLoader(String[] classPath) {
- if (classPath == null) {
- classPath = getDefaultClasspath();
- }
- this.classPath = classPath;
- }
- /**
- * Конструктор. Устанавливает список папое для поиска классов из системы.
- * */
- public TestClassLoader() {
- this(getDefaultClasspath());
- }
- private static String[] getDefaultClasspath() {
- String javaClasspath = System.getProperty("java.class.path");
- String pathSeparator = System.getProperty("path.separator");
- return javaClasspath.split(pathSeparator);
- }
- /**
- * Загружает класс. Примеры имени класса:
- * ClassName - класс из стандартного пакета
- * package.name.ClassName - класс из указанного пакета
- * .ClassName - класс из того же пакета, что и загрузчик
- * */
- @Override
- protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- String decodedName = decodeName(name);
- Class<?> result = findClass(decodedName);
- if (resolve) {
- resolveClass(result);
- }
- return result;
- }
- /**
- * Декодирует имя класса. Дает возможность пропускать имя пакета, если класс находится в
- * том же пакете, что и загрузчик.
- * */
- public String decodeName(String name) {
- if (name.startsWith(".")) {
- String packname = getClass().getPackage().getName();
- if (!packname.isEmpty()) {
- name = packname + name;
- } else {
- name = name.substring(1);
- }
- }
- return name;
- }
- /**
- * Ищет класс. Порядок поиска:
- * кеш загруженных ранее классов
- * список папок для поиска классов
- * системный список папок для поиска классов
- * */
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- Class<?> result = cache.get(name);
- if (result != null) {
- return result;
- }
- Path path = findFile(name);
- if (path == null) {
- return findSystemClass(name);
- }
- result = defineClass(name, path);
- cache.put(name, result);
- return result;
- }
- /**
- * Загруает данные класса из файла и добавляет новый класс в программу.
- * */
- private Class<?> defineClass(String name, Path path) throws ClassNotFoundException {
- Class<?> result;
- try {
- byte[] bytes = Files.readAllBytes(path);
- result = defineClass(name, bytes, 0, bytes.length);
- } catch (IOException e) {
- throw new ClassNotFoundException("Unable to read file " + path.getFileName(), e);
- } catch (ClassFormatError e) {
- throw new ClassNotFoundException("Format of class file incorrect for class " + name, e);
- }
- return result;
- }
- /**
- * Ищет файл класса во всех папках в classPath.
- * */
- private Path findFile(String className) {
- String filepath = className.replace('.', File.separatorChar) + ".class";
- for (String pathbase : classPath) {
- Path path = Paths.get(pathbase, filepath);
- if (Files.exists(path)) {
- return path;
- }
- }
- return null;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement