All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.hasor.cobble.loader.providers.JarResourceLoader Maven / Gradle / Ivy

The newest version!
/*
 * 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.ExceptionUtils;
import net.hasor.cobble.function.ESupplier;
import net.hasor.cobble.loader.AbstractResourceLoader;
import net.hasor.cobble.loader.MatchType;
import net.hasor.cobble.loader.ScanEvent;
import net.hasor.cobble.loader.Scanner;
import net.hasor.cobble.loader.jar.JarFile;
import net.hasor.cobble.logging.Logger;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

/**
 * 可以处理 jar 包的 ResourceLoader,并且支持 jar in jar
 * @version : 2021-09-29
 * @author 赵永春 ([email protected])
 */
public class JarResourceLoader extends AbstractResourceLoader {
    private static final Logger        logger = Logger.getLogger(JarResourceLoader.class);
    private final        JarFile       jarFile;
    private final        List nestedJarFile;

    public JarResourceLoader(File file) throws IOException {
        this(null, file, Collections.emptyList());
    }

    public JarResourceLoader(ClassLoader parent, File file) throws IOException {
        super(parent);
        this.jarFile = new JarFile(file);
        this.nestedJarFile = new ArrayList<>();
    }

    public JarResourceLoader(ClassLoader parent, File file, List nestedList) throws IOException {
        super(parent);
        this.jarFile = new JarFile(file);
        this.nestedJarFile = new ArrayList<>();
        for (String nestedJar : nestedList) {
            JarEntry jarEntry = this.jarFile.getJarEntry(nestedJar);
            if (jarEntry != null) {
                this.nestedJarFile.add(this.jarFile.getNestedJarFile(jarEntry));
            }
        }
    }

    public JarResourceLoader(ClassLoader parent, File file, Predicate nestedPredicate) throws IOException {
        super(parent);
        this.jarFile = new JarFile(file);
        this.nestedJarFile = new ArrayList<>();
        if (nestedPredicate != null) {
            for (JarEntry jarEntry : this.jarFile) {
                if (jarEntry != null && nestedPredicate.test(jarEntry)) {
                    this.nestedJarFile.add(this.jarFile.getNestedJarFile(jarEntry));
                }
            }
        }
    }

    public Manifest getManifest() throws IOException {
        return this.jarFile.getManifest();
    }

    public Manifest getManifest(String nestedJarName) throws IOException {
        for (JarFile jarFile : this.nestedJarFile) {
            if (jarFile.getName().equals(nestedJarName)) {
                return jarFile.getManifest();
            }
        }
        return null;
    }

    @Override
    public URL getResource(String resource) throws IOException {
        ZipEntry zipEntry = this.jarFile.getEntry(resource);
        if (zipEntry != null) {
            return new URL(this.jarFile.getUrl(), zipEntry.getName());
        } else if (!this.nestedJarFile.isEmpty()) {
            for (JarFile nestedJar : this.nestedJarFile) {
                ZipEntry nestedZipEntry = nestedJar.getEntry(resource);
                if (nestedZipEntry != null) {
                    return new URL(nestedJar.getUrl(), nestedZipEntry.getName());
                }
            }
        }
        return null;
    }

    @Override
    public InputStream getResourceAsStream(String resource) throws IOException {
        ZipEntry zipEntry = this.jarFile.getEntry(resource);
        if (zipEntry != null) {
            return this.jarFile.getInputStream(zipEntry);
        } else if (!this.nestedJarFile.isEmpty()) {
            for (JarFile nestedJar : this.nestedJarFile) {
                ZipEntry nestedZipEntry = nestedJar.getEntry(resource);
                if (nestedZipEntry != null) {
                    return nestedJar.getInputStream(nestedZipEntry);
                }
            }
        }
        return null;
    }

    @Override
    public long getResourceSize(String resource) throws IOException {
        ZipEntry zipEntry = this.jarFile.getEntry(resource);
        if (zipEntry != null) {
            return zipEntry.getSize();
        } else if (!this.nestedJarFile.isEmpty()) {
            for (JarFile nestedJar : this.nestedJarFile) {
                ZipEntry nestedZipEntry = nestedJar.getEntry(resource);
                if (nestedZipEntry != null) {
                    return nestedZipEntry.getSize();
                }
            }
        }
        return -1;
    }

    @Override
    public List getResources(String resource) throws IOException {
        List result = new ArrayList<>();

        ZipEntry zipEntry = this.jarFile.getEntry(resource);
        if (zipEntry != null) {
            result.add(new URL(this.jarFile.getUrl(), zipEntry.getName()));
        }
        if (!this.nestedJarFile.isEmpty()) {
            for (JarFile nestedJar : nestedJarFile) {
                ZipEntry nestedZipEntry = nestedJar.getEntry(resource);
                if (nestedZipEntry != null) {
                    result.add(new URL(nestedJar.getUrl(), nestedJar.getName()));
                }
            }
        }
        return result;
    }

    @Override
    public List getResourcesAsStream(String resource) throws IOException {
        List result = new ArrayList<>();

        ZipEntry zipEntry = this.jarFile.getEntry(resource);
        if (zipEntry != null) {
            result.add(this.jarFile.getInputStream(zipEntry));
        }
        if (!this.nestedJarFile.isEmpty()) {
            for (JarFile nestedJar : nestedJarFile) {
                ZipEntry nestedZipEntry = nestedJar.getEntry(resource);
                if (nestedZipEntry != null) {
                    result.add(nestedJar.getInputStream(nestedZipEntry));
                }
            }
        }
        return result;
    }

    @Override
    public boolean exist(String resource) {
        ZipEntry zipEntry = this.jarFile.getEntry(resource);
        if (zipEntry != null) {
            return true;
        } else if (!this.nestedJarFile.isEmpty()) {
            for (JarFile nestedJar : this.nestedJarFile) {
                ZipEntry nestedZipEntry = nestedJar.getEntry(resource);
                if (nestedZipEntry != null) {
                    return true;
                }
            }
        }
        return false;
    }

    protected boolean testFound(JarEntry entry, Predicate[] testPredicates) {
        if (testPredicates == null || testPredicates.length == 0) {
            return true;
        } else {
            for (Predicate predicate : testPredicates) {
                if (predicate.test(entry)) {
                    return true;
                }
            }
            return false;
        }
    }

    private  void scanJarFile(List result, JarFile jarFile, Scanner scanner, Predicate[] scanPaths, boolean matchOnce) throws IOException {
        Iterator zipEntry = jarFile.stream().iterator();
        while (zipEntry.hasNext()) {
            JarEntry entry = zipEntry.next();
            if (!testFound(entry, scanPaths)) {
                continue;
            }

            try {
                URI uri = new URL(jarFile.getUrl(), entry.getName()).toURI();
                ESupplier inputStream = () -> jarFile.getInputStream(entry);
                T res = scanner.found(new ScanEvent(entry.getName(), entry.getSize(), uri, inputStream));
                if (res != null) {
                    result.add(res);
                }
            } catch (URISyntaxException e) {
                if (logger.isDebugEnabled()) {
                    logger.warn("scanJarFile :" + e.getMessage(), e);
                } else {
                    logger.debug("scanJarFile :" + e.getMessage());
                }
            }
            if (matchOnce && !result.isEmpty()) {
                return;
            }
        }
    }

    @Override
    public  List scanResources(MatchType matchType, Predicate matcher, Scanner scanner, String[] scanPaths) throws IOException {
        try {
            List result = new ArrayList<>();
            Predicate[] tests = buildPredicate(matchType, scanPaths, ZipEntry::getName);

            if (matcher.test(this.jarFile.getUrl().toURI())) {
                this.scanJarFile(result, this.jarFile, scanner, tests, false);
            }

            if (!this.nestedJarFile.isEmpty()) {
                for (JarFile nestedJar : this.nestedJarFile) {
                    if (matcher.test(nestedJar.getUrl().toURI())) {
                        this.scanJarFile(result, nestedJar, scanner, tests, false);
                    }
                }
            }
            return result;
        } catch (URISyntaxException e) {
            logger.error("cannot convert URL to URI jar (" + this.jarFile.getUrl() + ") " + e.getMessage(), e);
            throw ExceptionUtils.toRuntime(e);
        }
    }

    @Override
    public  T scanOneResource(MatchType matchType, Predicate matcher, Scanner scanner, String[] scanPaths) throws IOException {
        try {
            List result = new ArrayList<>();
            Predicate[] tests = buildPredicate(matchType, scanPaths, ZipEntry::getName);

            if (matcher.test(this.jarFile.getUrl().toURI())) {
                this.scanJarFile(result, this.jarFile, scanner, tests, true);
                if (!result.isEmpty()) {
                    return result.get(0);
                }
            }
            if (!this.nestedJarFile.isEmpty()) {
                for (JarFile nestedJar : this.nestedJarFile) {
                    if (matcher.test(nestedJar.getUrl().toURI())) {
                        this.scanJarFile(result, nestedJar, scanner, tests, true);
                        if (!result.isEmpty()) {
                            return result.get(0);
                        }
                    }
                }
            }
            return null;
        } catch (URISyntaxException e) {
            logger.error("cannot convert URL to URI jar (" + this.jarFile.getUrl() + ") " + e.getMessage(), e);
            throw ExceptionUtils.toRuntime(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy