/*
 * This file is part of LuckPerms, licensed under the MIT License.
 *
 *  Copyright (c) lucko (Luck) <luck@lucko.me>
 *  Copyright (c) contributors
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */

package me.lucko.luckperms.common.dependencies.classloader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;

public class ReflectionClassLoader implements PluginClassLoader {
    private static final Method ADD_URL_METHOD;

    static {
        try {
            ADD_URL_METHOD = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
            ADD_URL_METHOD.setAccessible(true);
        } catch (NoSuchMethodException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private final URLClassLoader classLoader;

    public ReflectionClassLoader(Object plugin) throws IllegalStateException {
        ClassLoader classLoader = plugin.getClass().getClassLoader();
        if (classLoader instanceof URLClassLoader) {
            this.classLoader = (URLClassLoader) classLoader;
        } else {
            throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
        }
    }

    @Override
    public void addJarToClasspath(Path file) {
        try {
            ADD_URL_METHOD.invoke(this.classLoader, file.toUri().toURL());
        } catch (IllegalAccessException | InvocationTargetException | MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }
}

@@ -1300,16 +1300,169 @@
 oader;%0A%0A
+import com.google.common.base.Supplier;%0Aimport com.google.common.base.Suppliers;%0A%0Aimport me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;%0A%0A
 import j
@@ -1740,100 +1740,13 @@
 ate 
-static final Method ADD_URL_METHOD;%0A%0A    static %7B%0A        try %7B%0A            ADD_URL_METHOD =
+final
  URL
@@ -1760,262 +1760,183 @@
 ader
-.
+ 
 class
-.getDeclaredMethod(%22addURL%22, URL.class);%0A            ADD_URL_METHOD.setAccessible(true);%0A        %7D catch (NoSuchMethodException e) %7B%0A            throw new ExceptionInInitializerError(e);%0A        %7D%0A    %7D%0A%0A    private final URLClassLoader classLoader
+Loader;%0A%0A    @SuppressWarnings(%22Guava%22) // we can't use java.util.Function because old Guava versions are used at runtime%0A    private final Supplier%3CMethod%3E addUrlMethod
 ;%0A%0A 
@@ -1971,21 +1971,36 @@
 der(
-Object plugin
+LuckPermsBootstrap bootstrap
 ) th
@@ -2062,22 +2062,25 @@
 oader = 
-plugin
+bootstrap
 .getClas
@@ -2331,24 +2331,905 @@
 );%0A        %7D
+%0A%0A        this.addUrlMethod = Suppliers.memoize(() -%3E %7B%0A            if (getJavaMajorVersion() %3E= 9) %7B%0A                bootstrap.getPluginLogger().info(%22It is safe to ignore any warning printed following this message %22 +%0A                        %22starting with 'WARNING: An illegal reflective access operation has occurred, Illegal reflective %22 +%0A                        %22access by %22 + getClass().getName() + %22'.%22);%0A                bootstrap.getPluginLogger().info(%22This is intended, and will not have any impact the operation of LuckPerms.%22);%0A            %7D%0A%0A            try %7B%0A                Method addUrlMethod = URLClassLoader.class.getDeclaredMethod(%22addURL%22, URL.class);%0A                addUrlMethod.setAccessible(true);%0A                return addUrlMethod;%0A            %7D catch (NoSuchMethodException e) %7B%0A                throw new RuntimeException(e);%0A            %7D%0A        %7D);
 %0A    %7D%0A%0A    
@@ -3315,22 +3315,31 @@
     
-ADD_URL_METHOD
+this.addUrlMethod.get()
 .inv
@@ -3538,11 +3538,422 @@
  %7D%0A    %7D
+%0A%0A    private static int getJavaMajorVersion() %7B%0A        String version = System.getProperty(%22java.version%22);%0A        if (version.startsWith(%221.%22)) %7B%0A            version = version.substring(2, 3);%0A        %7D else %7B%0A            int dot = version.indexOf(%22.%22);%0A            if (dot != -1) %7B%0A                version = version.substring(0, dot);%0A            %7D%0A        %7D%0A        return Integer.parseInt(version);%0A    %7D
 %0A%7D%0A

Add notice to inform users to ignore 'illegal reflective access' warning messages (#952)