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

com.ui4j.bytebuddy.dynamic.ClassLoadingStrategy Maven / Gradle / Ivy

The newest version!
package com.ui4j.bytebuddy.dynamic;

import com.ui4j.bytebuddy.dynamic.loading.ByteArrayClassLoader;
import com.ui4j.bytebuddy.dynamic.loading.ClassLoaderByteArrayInjector;
import com.ui4j.bytebuddy.instrumentation.type.TypeDescription;

import java.security.ProtectionDomain;
import java.util.Map;

/**
 * A strategy for loading a collection of types.
 */
public interface ClassLoadingStrategy {

    /**
     * Loads a given collection of classes given their binary representation.
     *
     * @param classLoader The class loader to used for loading the classes.
     * @param types       Byte array representations of the types to be loaded mapped by their descriptions,
     *                    where an iteration order defines an order in which they are supposed to be loaded,
     *                    if relevant.
     * @return A collection of the loaded classes which will be initialized in the iteration order of the
     * returned collection.
     */
    Map> load(ClassLoader classLoader, Map types);

    /**
     * This class contains implementations of default class loading strategies.
     */
    static enum Default implements WithDefaultProtectionDomain {

        /**
         * This strategy creates a new {@link com.ui4j.bytebuddy.dynamic.loading.ByteArrayClassLoader} with the given
         * class loader as its parent. The byte array class loader is aware of a any dynamically created type and can
         * natively load the given classes. This allows to load classes with cyclic load-time dependencies since the
         * byte array class loader is queried on each encountered unknown class. Due to the encapsulation of the
         * classes that were loaded by a byte array class loader, this strategy will lead to the unloading of these
         * classes once this class loader, its classes or any instances of these classes become unreachable.
         */
        WRAPPER {
            @Override
            public Map> load(ClassLoader classLoader, Map types) {
                return ByteArrayClassLoader.load(classLoader,
                        types,
                        DEFAULT_PROTECTION_DOMAIN,
                        ByteArrayClassLoader.PersistenceHandler.LATENT, PARENT_FIRST);
            }

            @Override
            public ClassLoadingStrategy withProtectionDomain(ProtectionDomain protectionDomain) {
                return new ProtectionDomainWrapper(protectionDomain,
                        ByteArrayClassLoader.PersistenceHandler.LATENT,
                        PARENT_FIRST);
            }
        },

        /**
         * The strategy is identical to {@link com.ui4j.bytebuddy.dynamic.ClassLoadingStrategy.Default#WRAPPER} but exposes
         * the byte arrays that represent a class by {@link java.lang.ClassLoader#getResourceAsStream(String)}. For
         * this purpose, all class files are persisted as byte arrays withing the wrapping class loader.
         */
        WRAPPER_PERSISTENT {
            @Override
            public Map> load(ClassLoader classLoader, Map types) {
                return ByteArrayClassLoader.load(classLoader,
                        types,
                        DEFAULT_PROTECTION_DOMAIN,
                        ByteArrayClassLoader.PersistenceHandler.MANIFEST,
                        PARENT_FIRST);
            }

            @Override
            public ClassLoadingStrategy withProtectionDomain(ProtectionDomain protectionDomain) {
                return new ProtectionDomainWrapper(protectionDomain,
                        ByteArrayClassLoader.PersistenceHandler.MANIFEST,
                        PARENT_FIRST);
            }
        },

        /**
         * 

* The child-first class loading strategy is a modified version of the * {@link com.ui4j.bytebuddy.dynamic.ClassLoadingStrategy.Default#WRAPPER} where the dynamic types are given * priority over any types of a parent class loader with the same name. *

*

* Important: This does not replace a type of the same name, but it makes the type invisible by * the reach of this class loader. *

*/ CHILD_FIRST { @Override public Map> load(ClassLoader classLoader, Map types) { return ByteArrayClassLoader.load(classLoader, types, DEFAULT_PROTECTION_DOMAIN, ByteArrayClassLoader.PersistenceHandler.LATENT, PARENT_LAST); } @Override public ClassLoadingStrategy withProtectionDomain(ProtectionDomain protectionDomain) { return new ProtectionDomainWrapper(protectionDomain, ByteArrayClassLoader.PersistenceHandler.LATENT, PARENT_LAST); } }, /** * The strategy is identical to {@link com.ui4j.bytebuddy.dynamic.ClassLoadingStrategy.Default#CHILD_FIRST} but * exposes the byte arrays that represent a class by {@link java.lang.ClassLoader#getResourceAsStream(String)}. * For this purpose, all class files are persisted as byte arrays withing the wrapping class loader. */ CHILD_FIRST_PERSISTENT { @Override public Map> load(ClassLoader classLoader, Map types) { return ByteArrayClassLoader.load(classLoader, types, DEFAULT_PROTECTION_DOMAIN, ByteArrayClassLoader.PersistenceHandler.MANIFEST, PARENT_LAST); } @Override public ClassLoadingStrategy withProtectionDomain(ProtectionDomain protectionDomain) { return new ProtectionDomainWrapper(protectionDomain, ByteArrayClassLoader.PersistenceHandler.MANIFEST, PARENT_LAST); } }, /** * This strategy does not create a new class loader but injects all classes into the given {@link java.lang.ClassLoader} * by reflective access. This prevents the loading of classes with cyclic load-time dependencies but avoids the * creation of an additional class loader. The advantage of this strategy is that the loaded classes will have * package-private access to other classes within their package of the class loader into which they are * injected what is not permitted when the wrapper class loader is used. This strategy is implemented using a * {@link com.ui4j.bytebuddy.dynamic.loading.ClassLoaderByteArrayInjector}. Note that this strategy usually yields * a better runtime performance. */ INJECTION { @Override public Map> load(ClassLoader classLoader, Map types) { return ClassLoaderByteArrayInjector.inject(new ClassLoaderByteArrayInjector(classLoader), types); } @Override public ClassLoadingStrategy withProtectionDomain(ProtectionDomain protectionDomain) { return new ProtectionDomainInjection(protectionDomain); } }; /** * An identifier for a class loading-order for making the code more readable. */ private static final boolean PARENT_LAST = true, PARENT_FIRST = false; /** * A convenience reference that references the default protection domain which is {@code null}. */ private static final ProtectionDomain DEFAULT_PROTECTION_DOMAIN = null; /** * A class loading strategy which applies a class loader injection while applying a given * {@link java.security.ProtectionDomain} on class injection. */ protected static class ProtectionDomainInjection implements ClassLoadingStrategy { /** * The protection domain to apply. */ private final ProtectionDomain protectionDomain; /** * Creates a new protection domain injection class loading strategy. * * @param protectionDomain The protection domain to apply. */ protected ProtectionDomainInjection(ProtectionDomain protectionDomain) { this.protectionDomain = protectionDomain; } @Override public Map> load(ClassLoader classLoader, Map types) { return ClassLoaderByteArrayInjector.inject(new ClassLoaderByteArrayInjector(classLoader, protectionDomain), types); } @Override public boolean equals(Object other) { return this == other || !(other == null || getClass() != other.getClass()) && protectionDomain.equals(((ProtectionDomainInjection) other).protectionDomain); } @Override public int hashCode() { return protectionDomain.hashCode(); } @Override public String toString() { return "ClassLoadingStrategy.Default.ProtectionDomainInjection{protectionDomain=" + protectionDomain + '}'; } } /** * A class loading strategy which creates a wrapping class loader while applying a given * {@link java.security.ProtectionDomain} on class loading. */ protected static class ProtectionDomainWrapper implements ClassLoadingStrategy { /** * The protection domain to apply. */ private final ProtectionDomain protectionDomain; /** * The persistence handler to apply. */ private final ByteArrayClassLoader.PersistenceHandler persistenceHandler; /** * {@code true} if the created class loader should apply child-first semantics. */ private final boolean childFirst; /** * Creates a new protection domain specific class loading wrapper. * * @param protectionDomain The protection domain to apply. * @param persistenceHandler The persistence handler to apply. * @param childFirst {@code true} if the created class loader should apply child-first semantics. */ public ProtectionDomainWrapper(ProtectionDomain protectionDomain, ByteArrayClassLoader.PersistenceHandler persistenceHandler, boolean childFirst) { this.protectionDomain = protectionDomain; this.persistenceHandler = persistenceHandler; this.childFirst = childFirst; } @Override public Map> load(ClassLoader classLoader, Map types) { return ByteArrayClassLoader.load(classLoader, types, protectionDomain, persistenceHandler, childFirst); } @Override public boolean equals(Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; ProtectionDomainWrapper that = (ProtectionDomainWrapper) other; return childFirst == that.childFirst && persistenceHandler == that.persistenceHandler && protectionDomain.equals(that.protectionDomain); } @Override public int hashCode() { int result = protectionDomain.hashCode(); result = 31 * result + (childFirst ? 1 : 0); result = 31 * result + persistenceHandler.hashCode(); return result; } @Override public String toString() { return "ClassLoadingStrategy.Default.ProtectionDomainWrapper{" + "protectionDomain=" + protectionDomain + ", childFirst=" + childFirst + ", persistenceHandler=" + persistenceHandler + '}'; } } } /** * A {@link com.ui4j.bytebuddy.dynamic.ClassLoadingStrategy} that applies a default {@link java.security.ProtectionDomain}. */ static interface WithDefaultProtectionDomain extends ClassLoadingStrategy { /** * Overrides the implicitly set default {@link java.security.ProtectionDomain} with an explicit one. * * @param protectionDomain The protection domain to apply. * @return This class loading strategy with an explicitly set {@link java.security.ProtectionDomain}. */ ClassLoadingStrategy withProtectionDomain(ProtectionDomain protectionDomain); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy