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

de.florianmichael.asmfabricloader.loader.feature.JarBooter Maven / Gradle / Ivy

/*
 * This file is part of AsmFabricLoader - https://github.com/FlorianMichael/AsmFabricLoader
 * Copyright (C) 2023-2024 FlorianMichael/EnZaXD 
 *
 *  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 de.florianmichael.asmfabricloader.loader.feature;

import de.florianmichael.asmfabricloader.loader.AFLFeature;
import de.florianmichael.asmfabricloader.loader.classloading.AFLConstants;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.metadata.CustomValue;
import net.lenni0451.reflect.ClassLoaders;
import net.lenni0451.reflect.stream.RStream;

import java.io.File;
import java.net.MalformedURLException;
import java.util.Collection;

public class JarBooter {

    public JarBooter(final Collection modContainers) {
        AFLFeature.applyForMods(modContainers, "jarbooter", (modContainer, value) -> {
            if (value.getType() == CustomValue.CvType.ARRAY) {
                for (CustomValue customValue : value.getAsArray()) {
                    final File target = new File(customValue.getAsString());

                    replaceJar(target);
                }
            } else if (value.getType() == CustomValue.CvType.STRING) {
                final File target = new File(value.getAsString());

                replaceJar(target);
            }
        });
    }

    /**
     * Recursively iterates over the given file and loads all jar files to the front of the classpath
     *
     * @param file The file to iterate over
     */
    public void replaceJar(final File file) {
        try {
            replaceJar0(file);
        } catch (MalformedURLException e) {
            AFLConstants.LOGGER.error("Failed to load jar file {} to the front of the classpath", file.getName(), e);
        }
    }

    /**
     * Recursively iterates over the given file and loads all jar files to the front of the classpath
     *
     * @param file The file to iterate over
     * @throws MalformedURLException If the file is not a valid URL
     */
    public void replaceJar0(final File file) throws MalformedURLException {
        for (File listFile : file.listFiles()) {
            final ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
            try {
                final ClassLoader actualLoader = RStream.of(oldLoader).fields().by("urlLoader").get();
                Thread.currentThread().setContextClassLoader(actualLoader);
                if (listFile.getName().endsWith(".jar")) {
                    ClassLoaders.loadToFront(listFile.toURI().toURL());

                    if (AFLConstants.isDebugEnabled()) {
                        AFLConstants.LOGGER.info("Loaded jar file {} to the front of the classpath", listFile.getName());
                    }
                } else if (listFile.isDirectory()) {
                    replaceJar0(listFile);
                }
            } finally {
                Thread.currentThread().setContextClassLoader(oldLoader);
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy