Advertisement
Guest User

Untitled

a guest
Nov 21st, 2017
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 3.98 KB | None | 0 0
  1. package ru.qoqqi.sandbox.classloader;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.nio.file.Files;
  6. import java.nio.file.Path;
  7. import java.nio.file.Paths;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10.  
  11. public class TestClassLoader extends ClassLoader {
  12.    
  13.     /**
  14.      * Кеш загруженных классов.
  15.      * */
  16.     private Map<String, Class> cache = new HashMap<>();
  17.    
  18.     /**
  19.      * Список папок для поиска классов.
  20.      * */
  21.     private final String[] classPath;
  22.    
  23.     /**
  24.      * Конструктор. Принимает список папок для поиска классов.
  25.      * */
  26.     public TestClassLoader(String[] classPath) {
  27.         if (classPath == null) {
  28.             classPath = getDefaultClasspath();
  29.         }
  30.         this.classPath = classPath;
  31.     }
  32.    
  33.     /**
  34.      * Конструктор. Устанавливает список папое для поиска классов из системы.
  35.      * */
  36.     public TestClassLoader() {
  37.         this(getDefaultClasspath());
  38.     }
  39.    
  40.     private static String[] getDefaultClasspath() {
  41.         String javaClasspath = System.getProperty("java.class.path");
  42.         String pathSeparator = System.getProperty("path.separator");
  43.        
  44.         return javaClasspath.split(pathSeparator);
  45.     }
  46.    
  47.     /**
  48.      * Загружает класс. Примеры имени класса:
  49.      * ClassName - класс из стандартного пакета
  50.      * package.name.ClassName - класс из указанного пакета
  51.      * .ClassName - класс из того же пакета, что и загрузчик
  52.      * */
  53.     @Override
  54.     protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
  55.         String decodedName = decodeName(name);
  56.         Class<?> result = findClass(decodedName);
  57.        
  58.         if (resolve) {
  59.             resolveClass(result);
  60.         }
  61.        
  62.         return result;
  63.     }
  64.    
  65.     /**
  66.      * Декодирует имя класса. Дает возможность пропускать имя пакета, если класс находится в
  67.      * том же пакете, что и загрузчик.
  68.      * */
  69.     public String decodeName(String name) {
  70.        
  71.         if (name.startsWith(".")) {
  72.             String packname = getClass().getPackage().getName();
  73.             if (!packname.isEmpty()) {
  74.                 name = packname + name;
  75.             } else {
  76.                 name = name.substring(1);
  77.             }
  78.         }
  79.        
  80.         return name;
  81.     }
  82.    
  83.     /**
  84.      * Ищет класс. Порядок поиска:
  85.      * кеш загруженных ранее классов
  86.      * список папок для поиска классов
  87.      * системный список папок для поиска классов
  88.      * */
  89.     @Override
  90.     protected Class<?> findClass(String name) throws ClassNotFoundException {
  91.         Class<?> result = cache.get(name);
  92.        
  93.         if (result != null) {
  94.             return result;
  95.         }
  96.        
  97.         Path path = findFile(name);
  98.        
  99.         if (path == null) {
  100.             return findSystemClass(name);
  101.         }
  102.        
  103.         result = defineClass(name, path);
  104.         cache.put(name, result);
  105.         return result;
  106.     }
  107.    
  108.     /**
  109.      * Загруает данные класса из файла и добавляет новый класс в программу.
  110.      * */
  111.     private Class<?> defineClass(String name, Path path) throws ClassNotFoundException {
  112.         Class<?> result;
  113.        
  114.         try {
  115.             byte[] bytes = Files.readAllBytes(path);
  116.             result = defineClass(name, bytes, 0, bytes.length);
  117.            
  118.         } catch (IOException e) {
  119.             throw new ClassNotFoundException("Unable to read file " + path.getFileName(), e);
  120.            
  121.         } catch (ClassFormatError e) {
  122.             throw new ClassNotFoundException("Format of class file incorrect for class " + name, e);
  123.         }
  124.        
  125.         return result;
  126.     }
  127.    
  128.     /**
  129.      * Ищет файл класса во всех папках в classPath.
  130.      * */
  131.     private Path findFile(String className) {
  132.         String filepath = className.replace('.', File.separatorChar) + ".class";
  133.        
  134.         for (String pathbase : classPath) {
  135.             Path path = Paths.get(pathbase, filepath);
  136.            
  137.             if (Files.exists(path)) {
  138.                 return path;
  139.             }
  140.         }
  141.        
  142.         return null;
  143.     }
  144. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement