package test; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.lang.reflect.Field; import java.net.URL; import java.net.URLClassLoader; import java.util.*; import java.util.function.Consumer; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Stream; /** * ClassLoader/Class Stream based utilities */ public class CLUtil { public static Stream jars(ClassLoader cl) { if (cl == null) { return bootstrapJars(); } else { if (cl instanceof URLClassLoader) { URL[] urls = ((URLClassLoader) cl).getURLs(); List jars = new ArrayList<>(urls.length); for (URL url : urls) { if ("file".equals(url.getProtocol())) { File file = new File(url.getFile()); if (file.isFile() && file.getName().endsWith(".jar")) { jars.add(file); } } } return Stream.concat(jars(cl.getParent()), jars.stream()); } else { return jars(cl.getParent()); } } } public static Stream bootstrapJars() { List jars = new ArrayList<>(); String bootClassPath = System.getProperty("sun.boot.class.path"); for (String elt : bootClassPath.split(File.pathSeparator)) { if (elt.endsWith(".jar")) { File bootJar = new File(elt); if (bootJar.isFile()) { jars.add(bootJar); } } } return jars.stream(); } public static Stream classNames(File jar) { try (JarFile jarFile = new JarFile(jar)) { Enumeration entries = jarFile.entries(); List classNames = new ArrayList<>(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String entryName = entry.getName(); if (!entry.isDirectory() && entryName.endsWith(".class")) { String className = entryName.replace('/', '.') .substring(0, entryName.length() - ".class".length()); classNames.add(className); } } return classNames.stream(); } catch (IOException e) { throw new UncheckedIOException(e); } } public static Class classForName(String className, ClassLoader classLoader) { try { return Class.forName(className, false, classLoader); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Stream> superclasses(Class clazz) { LinkedList> superclasses = new LinkedList<>(); for (Class cl = clazz; cl != null; cl = cl.getSuperclass()) { superclasses.addFirst(cl); } return superclasses.stream(); } public static class TypeCache { private final Map, Set>> subtypes = new HashMap<>(); public void add(Class clazz) { add(clazz, clazz); } public Stream> subtypesOf(Class type) { Set> set = subtypes.get(type); return (set == null) ? Stream.empty() : set.stream(); } private void add(Class superType, Class subType) { subtypes.computeIfAbsent( superType, st -> new HashSet>() ).add(subType); Class superclass = superType.getSuperclass(); if (superclass != null) { add(superclass, subType); } for (Class interfaze : superType.getInterfaces()) { add(interfaze, subType); } } } }