![JAR search and dependency download from the Maven repository](/logo.png)
net.hasor.cobble.loader.providers.ClassPathResourceLoader Maven / Gradle / Ivy
/*
* Copyright 2008-2009 the original author or authors.
*
* 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.hasor.cobble.loader.providers;
import net.hasor.cobble.loader.AbstractResourceLoader;
import net.hasor.cobble.loader.ResourceLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.*;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
* 用于创建一个可以从 classpath 中获取资源的 ResourceLoader
* @version : 2021-10-10
* @author 赵永春 ([email protected])
*/
public class ClassPathResourceLoader extends AbstractResourceLoader {
public static ResourceLoader INSTANCE = new ClassPathResourceLoader();
private final ClassLoader classLoader;
private final List classpath;
public ClassPathResourceLoader() {
super(Thread.currentThread().getContextClassLoader());
this.classLoader = Thread.currentThread().getContextClassLoader();
this.classpath = getClassPath(this.classLoader);
}
public ClassPathResourceLoader(ClassLoader parent) {
super(parent);
this.classLoader = Objects.requireNonNull(parent);
this.classpath = getClassPath(this.classLoader);
}
/** 获取ClassPath路径 */
private static List getClassPath(ClassLoader classLoader) {
List classLoaders = new ArrayList<>();
while (true) {
if (classLoader == null) {
break;
} else {
classLoaders.add(classLoader);
classLoader = classLoader.getParent();
}
}
List resources = new ArrayList<>();
for (ClassLoader loader : classLoaders) {
if (loader instanceof URLClassLoader) {
URL[] urLs = ((URLClassLoader) loader).getURLs();
if (urLs != null) {
for (URL url : urLs) {
if (!resources.contains(url)) {
resources.add(url);
}
}
}
}
}
return resources;
}
private String formatResourcePath(String resourcePath) {
resourcePath = resourcePath.replaceAll("/{2}", "/");
if (resourcePath.charAt(0) == '/') {
resourcePath = resourcePath.substring(1);
}
return resourcePath;
}
@Override
public URL getResource(String resource) throws IOException {
return this.classLoader.getResource(formatResourcePath(resource));
}
@Override
public InputStream getResourceAsStream(String resource) {
return this.classLoader.getResourceAsStream(formatResourcePath(resource));
}
@Override
public List getResources(String resource) throws IOException {
resource = formatResourcePath(resource);
List urls = new ArrayList<>();
Enumeration urlEnumeration = this.classLoader.getResources(resource);
while (urlEnumeration.hasMoreElements()) {
URL url = urlEnumeration.nextElement();
if (url != null) {
urls.add(url);
}
}
return urls;
}
@Override
public List getResourcesAsStream(String resource) throws IOException {
resource = formatResourcePath(resource);
List ins = new ArrayList<>();
Enumeration urlEnumeration = this.classLoader.getResources(resource);
while (urlEnumeration.hasMoreElements()) {
URL url = urlEnumeration.nextElement();
InputStream in = (url != null) ? url.openStream() : null;
if (in != null) {
ins.add(in);
}
}
return ins;
}
@Override
public boolean exist(String resource) {
return this.classLoader.getResource(formatResourcePath(resource)) != null;
}
@Override
public List scanResources(MatchType matchType, Scanner scanner, String[] scanPaths) throws IOException {
List result = new ArrayList<>();
Predicate[] testJar = buildPredicate(matchType, scanPaths, ZipEntry::getName);
Predicate[] testDir = buildPredicate(matchType, scanPaths, File::getPath);
for (URL url : this.classpath) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
File contextDir = new File(URLDecoder.decode(url.getFile()));
if (contextDir.isDirectory()) {
dirScan(result, contextDir, contextDir, testDir, scanner, false);
} else {
JarFile jarFile = new net.hasor.cobble.loader.jar.JarFile(contextDir);
jarScan(result, jarFile, testJar, scanner, false);
}
} else if (protocol.equals("jar")) {
JarURLConnection jarc = (JarURLConnection) url.openConnection();
JarFile jarFile = jarc.getJarFile();
jarScan(result, jarFile, testJar, scanner, false);
}
}
return result;
}
@Override
public T scanOneResource(MatchType matchType, Scanner scanner, String[] scanPaths) throws IOException {
List result = new ArrayList<>();
Predicate[] testJar = buildPredicate(matchType, scanPaths, ZipEntry::getName);
Predicate[] testDir = buildPredicate(matchType, scanPaths, File::getPath);
for (URL url : this.classpath) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
File contextDir = new File(URLDecoder.decode(url.getFile()));
if (contextDir.isDirectory()) {
dirScan(result, contextDir, contextDir, testDir, scanner, true);
} else {
JarFile jarFile = new net.hasor.cobble.loader.jar.JarFile(contextDir);
jarScan(result, jarFile, testJar, scanner, true);
}
} else if (protocol.equals("jar")) {
JarURLConnection jarc = (JarURLConnection) url.openConnection();
JarFile jarFile = jarc.getJarFile();
jarScan(result, jarFile, testJar, scanner, true);
}
if (!result.isEmpty()) {
return result.get(0);
}
}
return null;
}
private static void jarScan(List result, JarFile jarFile, Predicate[] jarTest, Scanner scanner, boolean matchOnce) throws IOException {
URL content = new File(jarFile.getName()).toURI().toURL();
Iterator zipEntry = jarFile.stream().iterator();
while (zipEntry.hasNext()) {
JarEntry entry = zipEntry.next();
if (!jarTestFound(entry, jarTest)) {
continue;
}
URL url = new URL("jar:" + content + "!/" + entry.getName());
InputStreamGet inputStream = () -> jarFile.getInputStream(entry);
T res = scanner.found(new ScanEvent(entry.getName(), entry.getSize(), url, inputStream));
if (res != null) {
result.add(res);
}
if (matchOnce && !result.isEmpty()) {
return;
}
}
}
private static boolean jarTestFound(JarEntry entry, Predicate[] jarTest) {
if (jarTest == null || jarTest.length == 0) {
return true;
} else {
for (Predicate predicate : jarTest) {
if (predicate.test(entry)) {
return true;
}
}
return false;
}
}
private static void dirScan(List result, File contextDir, File curFile, Predicate[] testDir, Scanner scanner, boolean matchOnce) throws IOException {
if (matchOnce && !result.isEmpty()) {
return;
}
File[] listFiles = curFile.listFiles();
if (listFiles == null) {
return;
}
for (File fileItem : listFiles) {
if (matchOnce && !result.isEmpty()) {
return;
}
if (fileItem.isHidden() || !fileItem.exists()) {
continue;
}
if (fileItem.isDirectory()) {
dirScan(result, contextDir, fileItem, testDir, scanner, matchOnce);
continue;
}
String resourceName = fileItem.getAbsolutePath().substring(contextDir.getAbsolutePath().length() + 1);
if (!dirTestFound(new File(resourceName), testDir)) {
continue;
}
InputStreamGet inputStream = () -> {
if (fileItem.canRead()) {
return new FileInputStream(fileItem);
} else {
throw new IOException("file cannot be read :" + fileItem);
}
};
T res = scanner.found(new ScanEvent(resourceName, fileItem.length(), fileItem.toURI().toURL(), inputStream));
if (res != null) {
result.add(res);
}
}
}
private static boolean dirTestFound(File entry, Predicate[] dirTest) {
if (dirTest == null || dirTest.length == 0) {
return true;
} else {
for (Predicate predicate : dirTest) {
if (predicate.test(entry)) {
return true;
}
}
return false;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy