Scans the source of a {@link ClassLoader} and finds all loadable classes and resources. <h2>Prefer <a href="https://github.com/classgraph/classgraph/wiki">ClassGraph</a> over {@code ClassPath}</h2> <p>We recommend using <a href="https://github.com/classgraph/classgraph/wiki">ClassGraph</a> instead
| 90 | * @since 14.0 |
| 91 | */ |
| 92 | public final class ClassPath { |
| 93 | private static final Logger logger = Logger.getLogger(ClassPath.class.getName()); |
| 94 | |
| 95 | /** Separator for the Class-Path manifest attribute value in jar files. */ |
| 96 | private static final Splitter CLASS_PATH_ATTRIBUTE_SEPARATOR = |
| 97 | Splitter.on(" ").omitEmptyStrings(); |
| 98 | |
| 99 | private static final String CLASS_FILE_NAME_EXTENSION = ".class"; |
| 100 | |
| 101 | private final ImmutableSet<ResourceInfo> resources; |
| 102 | |
| 103 | private ClassPath(ImmutableSet<ResourceInfo> resources) { |
| 104 | this.resources = resources; |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Returns a {@code ClassPath} representing all classes and resources loadable from {@code |
| 109 | * classloader} and its ancestor class loaders. |
| 110 | * |
| 111 | * <p><b>Warning:</b> {@code ClassPath} can find classes and resources only from: |
| 112 | * |
| 113 | * <ul> |
| 114 | * <li>{@link URLClassLoader} instances' {@code file:} URLs |
| 115 | * <li>the {@linkplain ClassLoader#getSystemClassLoader() system class loader}. To search the |
| 116 | * system class loader even when it is not a {@link URLClassLoader} (as in Java 9), {@code |
| 117 | * ClassPath} searches the files from the {@code java.class.path} system property. |
| 118 | * </ul> |
| 119 | * |
| 120 | * @throws IOException if the attempt to read class path resources (jar files or directories) |
| 121 | * failed. |
| 122 | */ |
| 123 | public static ClassPath from(ClassLoader classloader) throws IOException { |
| 124 | ImmutableSet<LocationInfo> locations = locationsFrom(classloader); |
| 125 | |
| 126 | // Add all locations to the scanned set so that in a classpath [jar1, jar2], where jar1 has a |
| 127 | // manifest with Class-Path pointing to jar2, we won't scan jar2 twice. |
| 128 | Set<File> scanned = new HashSet<>(); |
| 129 | for (LocationInfo location : locations) { |
| 130 | scanned.add(location.file()); |
| 131 | } |
| 132 | |
| 133 | // Scan all locations |
| 134 | ImmutableSet.Builder<ResourceInfo> builder = ImmutableSet.builder(); |
| 135 | for (LocationInfo location : locations) { |
| 136 | builder.addAll(location.scanResources(scanned)); |
| 137 | } |
| 138 | return new ClassPath(builder.build()); |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Returns all resources loadable from the current class path, including the class files of all |
| 143 | * loadable classes but excluding the "META-INF/MANIFEST.MF" file. |
| 144 | */ |
| 145 | public ImmutableSet<ResourceInfo> getResources() { |
| 146 | return resources; |
| 147 | } |
| 148 | |
| 149 | /** |
nothing calls this directly
no test coverage detected