Package co.paralleluniverse.common

Source Code of co.paralleluniverse.common.PathClassLoader

/*
* Capsule
* Copyright (c) 2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are licensed under the terms
* of the Eclipse Public License v1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package co.paralleluniverse.common;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.ProviderNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

/**
*
* @author pron
*/
public class PathClassLoader extends ClassLoader {
    private final Object[] paths;
    private final boolean childFirst;
    private final ThreadLocal<Boolean> inGetResourceAsStream = new ThreadLocal<Boolean>();

    public PathClassLoader(Path[] paths, ClassLoader parent, boolean childFirst) throws IOException {
        super(parent);
        this.paths = process(paths);
        this.childFirst = childFirst;
    }

    public PathClassLoader(Path[] paths, boolean childFirst) throws IOException {
        this.paths = process(paths);
        this.childFirst = childFirst;
    }

    public PathClassLoader(Path[] paths, ClassLoader parent) throws IOException {
        this(paths, parent, false);
    }

    public PathClassLoader(Path[] paths) throws IOException {
        this(paths, false);
    }

    private static Object[] process(Path[] paths) throws IOException {
        try {
            final Object[] os = new Object[paths.length];
            for (int i = 0; i < paths.length; i++) {
                final Path p = paths[i];
                final Object o;
                if (Files.isRegularFile(p))
                    o = FileSystems.newFileSystem(p, null);
                else
                    o = p;
                os[i] = o;
            }
            return os;
        } catch (ProviderNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public final void close() {
        IOException ex = null;
        for (Object p : paths) {
            if (p instanceof FileSystem) {
                try {
                    ((FileSystem) p).close();
                } catch (IOException e) {
                    if (ex == null)
                        ex = e;
                    else
                        ex.addSuppressed(e);
                }
            }
        }
    }

    @Override
    public URL getResource(String name) {
        if (!childFirst)
            return super.getResource(name);
        URL url = findResource(name);
        if (url == null)
            url = super.getResource(name);
        return url;
    }

    @Override
    public InputStream getResourceAsStream(String name) {
        inGetResourceAsStream.set(Boolean.TRUE);
        try {
            InputStream is = null;
            if (!childFirst)
                is = super.getResourceAsStream(name);
            if (is == null)
                is = findResourceAsStream(name);
            if (is == null && childFirst)
                is = super.getResourceAsStream(name);
            return is;
        } finally {
            inGetResourceAsStream.remove();
        }
    }

    private Path resolve(Object o, String name) {
        final Path p;
        if (o instanceof FileSystem)
            p = ((FileSystem) o).getPath(name);
        else
            p = ((Path) o).resolve(name);
        return p;
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        if (!childFirst)
            return super.loadClass(name, resolve);
        Class c;
        try {
            c = findClass(name);
            if (resolve)
                resolveClass(c);
            return c;
        } catch (ClassNotFoundException e) {
        }
        return super.loadClass(name, resolve);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        final byte[] buf = readResource(name.replace('.', '/') + ".class");
        if (buf == null)
            throw new ClassNotFoundException(name);
        return defineClass(name, buf, 0, buf.length);
    }

    @Override
    protected URL findResource(String name) {
        if (inGetResourceAsStream.get() == Boolean.TRUE)
            return null;
        try {
            for (Object o : paths) {
                final Path p = resolve(o, name);
                if (Files.exists(p))
                    return p.toUri().toURL();
            }
            return null;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Enumeration<URL> getResources(String name) throws IOException {
        Enumeration[] tmp = new Enumeration[2];
        tmp[childFirst ? 1 : 0] = super.getResources(name);
        tmp[childFirst ? 0 : 1] = findResources1(name);
        return new sun.misc.CompoundEnumeration<>(tmp);
    }

    protected Enumeration<URL> findResources1(String name) throws IOException {
        try {
            List<URL> urls = new ArrayList<>();
            for (Object o : paths) {
                final Path p = resolve(o, name);
                if (Files.exists(p))
                    urls.add(p.toUri().toURL());
            }
            return Collections.enumeration(urls);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private InputStream findResourceAsStream(String name) {
        try {
            for (Object o : paths) {
                final Path p = resolve(o, name);
                if (isFileResource(p))
                    return Files.newInputStream(p);
            }
            return null;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private byte[] readResource(String name) {
        try {
            for (Object o : paths) {
                final Path p = resolve(o, name);
                if (isFileResource(p))
                    return Files.readAllBytes(p);
            }
            return null;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private boolean isFileResource(Path p) {
        return Files.exists(p) && !Files.isDirectory(p);
    }
}
TOP

Related Classes of co.paralleluniverse.common.PathClassLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.