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

ru.yandex.clickhouse.jdbcbridge.core.ExpandedUrlClassLoader Maven / Gradle / Ivy

/**
 * Copyright 2019-2021, Zhichun Wu
 *
 * 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 ru.yandex.clickhouse.jdbcbridge.core;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Enhanced URL class loader which supports directory.
 * 
 * @since 2.0
 */
public class ExpandedUrlClassLoader extends URLClassLoader {
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExpandedUrlClassLoader.class);

    static final String PROTOCOL_FILE = "file";
    static final String FILE_URL_PREFIX = PROTOCOL_FILE + ":///";
    static final String DRIVER_EXTENSION = ".jar";

    // not going to use OSGi and maven which are over-complex
    protected static URL[] expandURLs(String... urls) {
        Set cache = new HashSet<>();
        List list = new ArrayList<>(Objects.requireNonNull(urls).length * 2);
        Set negativeSet = new HashSet<>();

        for (String s : urls) {
            if (s == null || s.isEmpty() || cache.contains(s)) {
                continue;
            }

            boolean isNegative = s.length() > 1 && s.charAt(0) == '!';
            if (isNegative) {
                s = s.substring(1);
            }

            URL url = null;
            try {
                url = cache.add(s) ? new URL(s) : null;
            } catch (MalformedURLException e) {
                // might be a local path?
                try {
                    URL tmp = Paths.get(s).normalize().toFile().toURI().toURL();
                    if (cache.add(s = tmp.toString())) {
                        url = tmp;
                    }
                } catch (InvalidPathException exp) {
                    log.warn("Skip invalid path [{}]", s);
                } catch (MalformedURLException exp) {
                    log.warn("Skip malformed URL [{}]", s);
                }
            }

            if (url == null) {
                continue;
            }

            boolean isValid = true;
            if (PROTOCOL_FILE.equals(url.getProtocol())) {
                Path path = null;
                try {
                    path = Paths.get(url.toURI());
                } catch (URISyntaxException e) {
                    isValid = false;
                    log.warn("Skip invalid URL [{}]", url);
                } catch (InvalidPathException e) {
                    isValid = false;
                    log.warn("Skip invalid path [{}]", url);
                }

                if (path != null && Files.isDirectory(path)) {
                    File dir = path.normalize().toFile();
                    String[] files = dir.list();
                    Arrays.sort(files);
                    for (String file : files) {
                        if (file.endsWith(DRIVER_EXTENSION)) {
                            file = new StringBuilder().append(FILE_URL_PREFIX).append(dir.getPath())
                                    .append(File.separatorChar).append(file).toString();

                            if (isNegative) {
                                try {
                                    negativeSet.add(new URL(file));
                                } catch (Exception e) {
                                    // ignore
                                }
                            } else if (cache.add(file)) {
                                try {
                                    list.add(new URL(file));
                                } catch (MalformedURLException e) {
                                    log.warn("Skip invalid file [{}]", file);
                                }
                            } else {
                                log.warn("Discard duplicated file [{}]", file);
                            }
                        }
                    }
                }
            }

            if (isValid) {
                (isNegative ? negativeSet : list).add(url);
            }
        }

        if (list.removeAll(negativeSet)) {
            if (log.isDebugEnabled()) {
                log.debug("Excluded URLs: {}", negativeSet);
            }
        }

        return list.toArray(new URL[list.size()]);
    }

    public ExpandedUrlClassLoader(ClassLoader parent, String... urls) {
        super(expandURLs(urls), parent == null ? ExpandedUrlClassLoader.class.getClassLoader() : parent);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy