001/*
002 * Colonel -- a brigadier expansion library
003 * Copyright (C) zml and Colonel contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package ca.stellardrift.colonel.impl;
018
019import java.lang.reflect.InvocationTargetException;
020import java.lang.reflect.Method;
021import java.net.URL;
022
023/**
024 * Via i509VCB, a trick to get Brig onto the Knot classpath in order to properly mix in.
025 *
026 * <p>YOU SHOULD ONLY USE THIS CLASS DURING "preLaunch" and ONLY TARGET A CLASS WHICH IS NOT ANY CLASS YOU MIXIN TO.
027 *
028 * This will likely not work on Gson because FabricLoader has some special logic related to Gson.</p>
029 *
030 * Original on GitHub at <a href="https://github.com/i509VCB/Fabric-Junkkyard/blob/ce278daa93804697c745a51af06ec812896ec2ad/src/main/java/me/i509/junkkyard/hacks/PreLaunchHacks.java">i509VCB/Fabric-Junkkyard</a>
031 */
032public class PreLaunchHacks {
033    private PreLaunchHacks() {}
034
035    private static final ClassLoader KNOT_CLASSLOADER = Thread.currentThread().getContextClassLoader();
036    private static final Method ADD_URL_METHOD;
037
038    static {
039        try {
040            ADD_URL_METHOD = KNOT_CLASSLOADER.getClass().getMethod("addURL", URL.class);
041            ADD_URL_METHOD.setAccessible(true);
042        } catch (ReflectiveOperationException e) {
043            throw new RuntimeException("Failed to load Classloader fields", e);
044        }
045    }
046
047    /**
048     * Hackily load the package which a mixin may exist within.
049     *
050     * YOU SHOULD NOT TARGET A CLASS WHICH YOU MIXIN TO.
051     *
052     * @param pathOfAClass The path of any class within the package.
053     * @throws ClassNotFoundException if an unknown class name is used
054     * @throws InvocationTargetException if an error occurs while injecting
055     * @throws IllegalAccessException if an error occurs while injecting
056     */
057    public static void hackilyLoadForMixin(String pathOfAClass) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
058        URL url = Class.forName(pathOfAClass).getProtectionDomain().getCodeSource().getLocation();
059        ADD_URL_METHOD.invoke(KNOT_CLASSLOADER, url);
060    }
061}