Search in sources :

Example 1 with CompositeClassLoader

use of org.mule.runtime.core.internal.util.CompositeClassLoader in project mule by mulesoft.

the class AnnotatedObjectInvocationHandler method addAnnotationsToClass.

/**
 * Enhances the given {@code nonAnnotatedClass} to be an implementation of {@link Component}.
 *
 * @param clazz the {@link Class} to enhance to implement {@link Component}.
 * @return the enhanced class, or the given {@code clazz} if it was already annotated.
 * @throws UnsupportedOperationException if the given {@code clazz} is <b>not</b> annotated and is declared as {@code final}.
 */
public static <T, A extends Component> Class<A> addAnnotationsToClass(Class<T> clazz) {
    if (Component.class.isAssignableFrom(clazz) && asList(clazz.getMethods()).stream().anyMatch(m -> "getAnnotations".equals(m.getName()) && !m.isDefault())) {
        return (Class<A>) clazz;
    }
    if (isFinal(clazz.getModifiers())) {
        throw new UnsupportedOperationException("Class '" + clazz.getName() + "' must either not be final or implement '" + Component.class.getName() + "'");
    }
    Enhancer enhancer = new Enhancer();
    enhancer.setInterfaces(new Class[] { DynamicallyComponent.class });
    enhancer.setSuperclass(clazz);
    ComponentInterceptor annotatedObjectInvocationHandler = new ComponentInterceptor(MANAGED_METHODS);
    CallbackHelper callbackHelper = new CallbackHelper(clazz, new Class[] { DynamicallyComponent.class }) {

        @Override
        protected Object getCallback(Method method) {
            if (MANAGED_METHODS.contains(method) || annotatedObjectInvocationHandler.getOverridingMethods().containsKey(method)) {
                return annotatedObjectInvocationHandler;
            } else {
                Optional<Method> overridingMethod = MANAGED_METHODS.stream().filter(m -> m.getName().equals(method.getName()) && Arrays.equals(m.getParameterTypes(), method.getParameterTypes())).findFirst();
                if (overridingMethod.isPresent()) {
                    annotatedObjectInvocationHandler.getOverridingMethods().put(method, overridingMethod.get());
                    return annotatedObjectInvocationHandler;
                } else {
                    return NoOp.INSTANCE;
                }
            }
        }
    };
    enhancer.setCallbackTypes(callbackHelper.getCallbackTypes());
    enhancer.setCallbackFilter(callbackHelper);
    if (Enhancer.class.getClassLoader() != clazz.getClassLoader()) {
        enhancer.setClassLoader(new CompositeClassLoader(AnnotatedObjectInvocationHandler.class.getClassLoader(), clazz.getClassLoader()));
        enhancer.setUseCache(false);
    }
    Class<A> annotatedClass = enhancer.createClass();
    registerStaticCallbacks(annotatedClass, callbackHelper.getCallbacks());
    return annotatedClass;
}
Also used : Enhancer.registerStaticCallbacks(net.sf.cglib.proxy.Enhancer.registerStaticCallbacks) Arrays(java.util.Arrays) CallbackHelper(net.sf.cglib.proxy.CallbackHelper) MethodInterceptor(net.sf.cglib.proxy.MethodInterceptor) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader) Set(java.util.Set) MuleRuntimeException(org.mule.runtime.api.exception.MuleRuntimeException) HashMap(java.util.HashMap) Modifier.isStatic(java.lang.reflect.Modifier.isStatic) Field(java.lang.reflect.Field) DynamicallyComponent(org.mule.runtime.core.internal.component.DynamicallyComponent) AbstractComponent(org.mule.runtime.api.component.AbstractComponent) HashSet(java.util.HashSet) Collections.unmodifiableSet(java.util.Collections.unmodifiableSet) Arrays.asList(java.util.Arrays.asList) NoOp(net.sf.cglib.proxy.NoOp) Collections.synchronizedMap(java.util.Collections.synchronizedMap) Component(org.mule.runtime.api.component.Component) Map(java.util.Map) Modifier.isFinal(java.lang.reflect.Modifier.isFinal) Optional(java.util.Optional) Enhancer(net.sf.cglib.proxy.Enhancer) Method(java.lang.reflect.Method) MethodProxy(net.sf.cglib.proxy.MethodProxy) Enhancer(net.sf.cglib.proxy.Enhancer) CallbackHelper(net.sf.cglib.proxy.CallbackHelper) Method(java.lang.reflect.Method) DynamicallyComponent(org.mule.runtime.core.internal.component.DynamicallyComponent) AbstractComponent(org.mule.runtime.api.component.AbstractComponent) Component(org.mule.runtime.api.component.Component) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader)

Example 2 with CompositeClassLoader

use of org.mule.runtime.core.internal.util.CompositeClassLoader in project mule by mulesoft.

the class DefaultConnectionProviderObjectBuilder method applyExtensionClassLoaderProxy.

/**
 * Wraps the {@link ConnectionProvider} inside of a dynamic proxy which changes the current {@link ClassLoader} to the the
 * extension's {@link ClassLoader} when executing any method of this wrapped {@link ConnectionProvider}
 * <p>
 * This ensures that every time that the {@link ConnectionProvider} is used, it will work in the correct classloader.
 * <p>
 * Although if the {@link ConnectionProvider} is created with the correct classloader and then used with an incorrect one this
 * may work, due that static class references were loaded correctly, logic loading class in a dynamic way will fail.
 *
 * @param provider The {@link ConnectionProvider} to wrap
 * @return The wrapped {@link ConnectionProvider}
 */
private ConnectionProvider<C> applyExtensionClassLoaderProxy(ConnectionProvider provider) {
    Enhancer enhancer = new Enhancer();
    ClassLoader classLoader = getClassLoader(extensionModel);
    Class[] proxyInterfaces = getProxyInterfaces(provider);
    enhancer.setInterfaces(proxyInterfaces);
    MethodInterceptor returnProviderInterceptor = (obj, method, args, proxy) -> provider;
    MethodInterceptor invokerInterceptor = (obj, method, args, proxy) -> {
        Reference<Object> resultReference = new Reference<>();
        Reference<Throwable> errorReference = new Reference<>();
        withContextClassLoader(classLoader, () -> {
            try {
                resultReference.set(method.invoke(provider, args));
            } catch (InvocationTargetException e) {
                errorReference.set(e.getTargetException());
            } catch (Throwable t) {
                errorReference.set(t);
            }
        });
        if (errorReference.get() != null) {
            throw errorReference.get();
        } else {
            return resultReference.get();
        }
    };
    CallbackHelper callbackHelper = new CallbackHelper(Object.class, proxyInterfaces) {

        @Override
        protected Object getCallback(Method method) {
            if (method.getDeclaringClass().equals(HasDelegate.class) && method.getName().equals("getDelegate")) {
                return returnProviderInterceptor;
            } else {
                return invokerInterceptor;
            }
        }
    };
    enhancer.setCallbackTypes(callbackHelper.getCallbackTypes());
    enhancer.setCallbackFilter(callbackHelper);
    if (Enhancer.class.getClassLoader() != classLoader) {
        enhancer.setClassLoader(new CompositeClassLoader(DefaultConnectionProviderObjectBuilder.class.getClassLoader(), classLoader));
        enhancer.setUseCache(false);
    }
    Class<ConnectionProvider<C>> proxyClass = enhancer.createClass();
    registerStaticCallbacks(proxyClass, callbackHelper.getCallbacks());
    try {
        return proxyClass.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
        throw new MuleRuntimeException(e);
    }
}
Also used : ErrorTypeHandlerConnectionProviderWrapper(org.mule.runtime.core.internal.connection.ErrorTypeHandlerConnectionProviderWrapper) ConnectionProviderModel(org.mule.runtime.api.meta.model.connection.ConnectionProviderModel) MuleExtensionUtils.getClassLoader(org.mule.runtime.module.extension.internal.util.MuleExtensionUtils.getClassLoader) ResolverSet(org.mule.runtime.module.extension.internal.runtime.resolver.ResolverSet) POOLING(org.mule.runtime.api.meta.model.connection.ConnectionManagementType.POOLING) ClassUtils(org.apache.commons.lang3.ClassUtils) MuleContext(org.mule.runtime.core.api.MuleContext) MuleException(org.mule.runtime.api.exception.MuleException) ReconnectableConnectionProviderWrapper(org.mule.runtime.core.internal.connection.ReconnectableConnectionProviderWrapper) PoolingProfile(org.mule.runtime.api.config.PoolingProfile) ClassUtils.withContextClassLoader(org.mule.runtime.core.api.util.ClassUtils.withContextClassLoader) Pair(org.mule.runtime.api.util.Pair) Enhancer(net.sf.cglib.proxy.Enhancer) Method(java.lang.reflect.Method) PoolingConnectionProviderWrapper(org.mule.runtime.core.internal.connection.PoolingConnectionProviderWrapper) IntrospectionUtils.injectFields(org.mule.runtime.module.extension.internal.util.IntrospectionUtils.injectFields) Enhancer.registerStaticCallbacks(net.sf.cglib.proxy.Enhancer.registerStaticCallbacks) CallbackHelper(net.sf.cglib.proxy.CallbackHelper) ConnectionProvider(org.mule.runtime.api.connection.ConnectionProvider) ResolverSetBasedObjectBuilder(org.mule.runtime.module.extension.internal.runtime.objectbuilder.ResolverSetBasedObjectBuilder) MethodInterceptor(net.sf.cglib.proxy.MethodInterceptor) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader) MuleRuntimeException(org.mule.runtime.api.exception.MuleRuntimeException) Initialisable(org.mule.runtime.api.lifecycle.Initialisable) ConnectionManagementType(org.mule.runtime.api.meta.model.connection.ConnectionManagementType) ExtensionModel(org.mule.runtime.api.meta.model.ExtensionModel) InvocationTargetException(java.lang.reflect.InvocationTargetException) List(java.util.List) HasDelegate(org.mule.runtime.core.internal.connection.HasDelegate) ReconnectionConfig(org.mule.runtime.core.internal.retry.ReconnectionConfig) Reference(org.mule.runtime.api.util.Reference) ResolverSetResult(org.mule.runtime.module.extension.internal.runtime.resolver.ResolverSetResult) Enhancer(net.sf.cglib.proxy.Enhancer) CallbackHelper(net.sf.cglib.proxy.CallbackHelper) Reference(org.mule.runtime.api.util.Reference) Method(java.lang.reflect.Method) HasDelegate(org.mule.runtime.core.internal.connection.HasDelegate) InvocationTargetException(java.lang.reflect.InvocationTargetException) ConnectionProvider(org.mule.runtime.api.connection.ConnectionProvider) MethodInterceptor(net.sf.cglib.proxy.MethodInterceptor) MuleRuntimeException(org.mule.runtime.api.exception.MuleRuntimeException) MuleExtensionUtils.getClassLoader(org.mule.runtime.module.extension.internal.util.MuleExtensionUtils.getClassLoader) ClassUtils.withContextClassLoader(org.mule.runtime.core.api.util.ClassUtils.withContextClassLoader) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader)

Example 3 with CompositeClassLoader

use of org.mule.runtime.core.internal.util.CompositeClassLoader in project mule by mulesoft.

the class ObjectFactoryClassRepository method getObjectFactoryDynamicClass.

private Class<ObjectFactory> getObjectFactoryDynamicClass(final ComponentBuildingDefinition componentBuildingDefinition, final Class objectFactoryType, final Class createdObjectType, final Supplier<Boolean> isLazyInitFunction, final Optional<Consumer<Object>> instancePostCreationFunction) {
    /*
     * We need this to allow spring create the object using a FactoryBean but using the object factory setters and getters so we
     * create as FactoryBean a dynamic class that will have the same attributes and methods as the ObjectFactory that the user
     * defined. This way our API does not expose spring specific classes.
     */
    Enhancer enhancer = new Enhancer();
    // Use SmartFactoryBean since it's the only way to force spring to pre-instantiate FactoryBean for singletons
    enhancer.setInterfaces(new Class[] { SmartFactoryBean.class });
    enhancer.setSuperclass(objectFactoryType);
    enhancer.setCallbackType(MethodInterceptor.class);
    if (SmartFactoryBean.class.getClassLoader() != objectFactoryType.getClassLoader()) {
        // CGLIB needs access to both the spring interface and the extended factory class.
        // If the factory class is defined in a plugin, its classloader has to be passed.
        enhancer.setClassLoader(new CompositeClassLoader(ObjectFactoryClassRepository.class.getClassLoader(), objectFactoryType.getClassLoader()));
    }
    // The use of the CGLIB cache is turned off when a post creation function is passed as argument in order to
    // enrich the created proxy with properties. This is only to enable injecting properties in components
    // from the compatibility module.
    // Setting this to false will generate an excessive amount of different proxy classes loaded by the container CL
    // that will end up in Metaspace OOM.
    enhancer.setUseCache(!instancePostCreationFunction.isPresent());
    Class<ObjectFactory> factoryBeanClass = enhancer.createClass();
    registerStaticCallbacks(factoryBeanClass, new Callback[] { (MethodInterceptor) (obj, method, args, proxy) -> {
        final boolean eager = !isLazyInitFunction.get();
        if (method.getName().equals("isSingleton")) {
            return !componentBuildingDefinition.isPrototype();
        }
        if (method.getName().equals("getObjectType") && !ObjectTypeProvider.class.isAssignableFrom(obj.getClass())) {
            return createdObjectType;
        }
        if (method.getName().equals("getObject")) {
            Object createdInstance = proxy.invokeSuper(obj, args);
            instancePostCreationFunction.ifPresent(consumer -> consumer.accept(createdInstance));
            return createdInstance;
        }
        if (method.getName().equals("isPrototype")) {
            return componentBuildingDefinition.isPrototype();
        }
        if (method.getName().equals("isEagerInit")) {
            return eager;
        }
        return proxy.invokeSuper(obj, args);
    } });
    return factoryBeanClass;
}
Also used : MethodInterceptor(org.springframework.cglib.proxy.MethodInterceptor) Consumer(java.util.function.Consumer) Enhancer(org.springframework.cglib.proxy.Enhancer) ComponentBuildingDefinition(org.mule.runtime.dsl.api.component.ComponentBuildingDefinition) Enhancer.registerStaticCallbacks(org.springframework.cglib.proxy.Enhancer.registerStaticCallbacks) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader) Callback(org.springframework.cglib.proxy.Callback) SmartFactoryBean(org.springframework.beans.factory.SmartFactoryBean) Optional(java.util.Optional) ObjectFactory(org.mule.runtime.dsl.api.component.ObjectFactory) Supplier(java.util.function.Supplier) ObjectTypeProvider(org.mule.runtime.dsl.api.component.ObjectTypeProvider) ObjectTypeProvider(org.mule.runtime.dsl.api.component.ObjectTypeProvider) Enhancer(org.springframework.cglib.proxy.Enhancer) ObjectFactory(org.mule.runtime.dsl.api.component.ObjectFactory) SmartFactoryBean(org.springframework.beans.factory.SmartFactoryBean) CompositeClassLoader(org.mule.runtime.core.internal.util.CompositeClassLoader)

Aggregations

CompositeClassLoader (org.mule.runtime.core.internal.util.CompositeClassLoader)3 Method (java.lang.reflect.Method)2 Optional (java.util.Optional)2 CallbackHelper (net.sf.cglib.proxy.CallbackHelper)2 Enhancer (net.sf.cglib.proxy.Enhancer)2 Enhancer.registerStaticCallbacks (net.sf.cglib.proxy.Enhancer.registerStaticCallbacks)2 MethodInterceptor (net.sf.cglib.proxy.MethodInterceptor)2 MuleRuntimeException (org.mule.runtime.api.exception.MuleRuntimeException)2 Field (java.lang.reflect.Field)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Modifier.isFinal (java.lang.reflect.Modifier.isFinal)1 Modifier.isStatic (java.lang.reflect.Modifier.isStatic)1 Arrays (java.util.Arrays)1 Arrays.asList (java.util.Arrays.asList)1 Collections.synchronizedMap (java.util.Collections.synchronizedMap)1 Collections.unmodifiableSet (java.util.Collections.unmodifiableSet)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1