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

org.jboss.weld.environment.tomcat.WeldForwardingInstanceManager Maven / Gradle / Ivy

package org.jboss.weld.environment.tomcat;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.naming.NamingException;

import jakarta.servlet.ServletContext;

import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.ApplicationContextFacade;
import org.apache.catalina.core.StandardContext;
import org.apache.tomcat.InstanceManager;
import org.jboss.weld.environment.servlet.logging.TomcatLogger;
import org.jboss.weld.environment.util.Reflections;
import org.jboss.weld.manager.api.WeldManager;
import org.jboss.weld.util.collections.Arrays2;

/**
 * Forwards all calls in turn to two delegates: first to InstanceManager, then to WeldInstanceManager
 *
 * @author Matija Mazi
 */
public class WeldForwardingInstanceManager extends ForwardingInstanceManager {

    private static final String CONTEXT_FIELD_NAME = "context";

    private static final String INSTANCE_MANAGER_SETTER_NAME = "setInstanceManager";

    private static final String INSTANCE_MANAGER_GETTER_NAME = "getInstanceManager";

    private static final String INSTANCE_MANAGER_FIELD_NAME = "instanceManager";

    private final InstanceManager firstProcessor;

    private final InstanceManager secondProcessor;

    public WeldForwardingInstanceManager(InstanceManager originalAnnotationProcessor, InstanceManager weldProcessor) {
        this.firstProcessor = originalAnnotationProcessor;
        this.secondProcessor = weldProcessor;
    }

    @Override
    protected InstanceManager delegate() {
        return firstProcessor;
    }

    @Override
    public void destroyInstance(Object o) throws IllegalAccessException, InvocationTargetException {
        super.destroyInstance(o);
        secondProcessor.destroyInstance(o);
    }

    @Override
    public void newInstance(Object o) throws IllegalAccessException, InvocationTargetException, NamingException {
        super.newInstance(o);
        secondProcessor.newInstance(o);
    }

    @Override
    public Object newInstance(String fqcn, ClassLoader classLoader)
            throws IllegalAccessException, InvocationTargetException, NamingException,
            InstantiationException, ClassNotFoundException, NoSuchMethodException {
        Object a = super.newInstance(fqcn, classLoader);
        secondProcessor.newInstance(a);
        return a;
    }

    @Override
    public Object newInstance(String fqcn)
            throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException,
            ClassNotFoundException, NoSuchMethodException {
        Object a = super.newInstance(fqcn);
        secondProcessor.newInstance(a);
        return a;
    }

    @Override
    public Object newInstance(Class clazz) throws IllegalAccessException, InvocationTargetException, NamingException,
            InstantiationException, NoSuchMethodException {
        Object a = super.newInstance(clazz);
        secondProcessor.newInstance(a);
        return a;
    }

    public static void replaceInstanceManager(ServletContext context, WeldManager manager) {
        StandardContext stdContext = getStandardContext(context);
        setInstanceManager(stdContext, createInstance(manager, stdContext));
    }

    private static WeldForwardingInstanceManager createInstance(WeldManager manager, StandardContext stdContext) {
        try {
            InstanceManager weldProcessor = new WeldInstanceManager(manager);
            return new WeldForwardingInstanceManager(getInstanceManager(stdContext), weldProcessor);
        } catch (Exception e) {
            throw TomcatLogger.LOG.cannotCreatWeldForwardingAnnotationProcessor(e);
        }
    }

    private static StandardContext getStandardContext(ServletContext context) {
        try {
            // Hack into Tomcat to replace the InstanceManager using
            // reflection to access private fields
            ApplicationContext appContext = (ApplicationContext) getContextFieldValue((ApplicationContextFacade) context,
                    ApplicationContextFacade.class);
            return (StandardContext) getContextFieldValue(appContext, ApplicationContext.class);
        } catch (Exception e) {
            throw TomcatLogger.LOG.cannotGetStandardContext(e);
        }
    }

    private static  Object getContextFieldValue(E obj, Class clazz) throws NoSuchFieldException, IllegalAccessException {
        Field field = org.jboss.weld.util.reflection.Reflections.lookupField(clazz, CONTEXT_FIELD_NAME);
        org.jboss.weld.util.reflection.Reflections.ensureAccessible(field, obj);
        return field.get(obj);
    }

    private static InstanceManager getInstanceManager(StandardContext stdContext) {
        try {
            Method method = org.jboss.weld.util.reflection.Reflections.lookupMethod(stdContext.getClass(),
                    INSTANCE_MANAGER_GETTER_NAME, Arrays2.EMPTY_CLASS_ARRAY);
            org.jboss.weld.util.reflection.Reflections.ensureAccessible(method, stdContext);
            try {
                return Reflections.cast(method.invoke(stdContext));
            } catch (Exception e) {
                TomcatLogger.LOG.errorInvokingMethod(method.getName(), stdContext, Arrays2.EMPTY_ARRAY);
            }
        } catch (NoSuchMethodException e1) {
            // Getter/setter not found
        }
        try {
            Field field = org.jboss.weld.util.reflection.Reflections.lookupField(stdContext.getClass(),
                    INSTANCE_MANAGER_FIELD_NAME);
            org.jboss.weld.util.reflection.Reflections.ensureAccessible(field, stdContext);
            try {
                return Reflections.cast(field.get(stdContext));
            } catch (Exception e) {
                TomcatLogger.LOG.errorReadingField(field.getName(), stdContext);
            }
        } catch (NoSuchFieldException e1) {
            // Field not found
        }
        throw TomcatLogger.LOG.neitherFieldNorGetterSetterFound(stdContext.getClass());
    }

    private static void setInstanceManager(StandardContext stdContext, InstanceManager instanceManager) {
        try {
            Method method = org.jboss.weld.util.reflection.Reflections.lookupMethod(stdContext.getClass(),
                    INSTANCE_MANAGER_SETTER_NAME,
                    new Class[] { InstanceManager.class });
            org.jboss.weld.util.reflection.Reflections.ensureAccessible(method, stdContext);
            try {
                method.invoke(stdContext, instanceManager);
                return;
            } catch (Exception e) {
                TomcatLogger.LOG.errorInvokingMethod(method.getName(), stdContext, instanceManager);
            }
        } catch (NoSuchMethodException e1) {
            // Getter/setter not found
        }
        try {
            Field field = org.jboss.weld.util.reflection.Reflections.lookupField(stdContext.getClass(),
                    INSTANCE_MANAGER_FIELD_NAME);
            org.jboss.weld.util.reflection.Reflections.ensureAccessible(field, stdContext);
            try {
                field.set(stdContext, instanceManager);
                return;
            } catch (Exception e) {
                TomcatLogger.LOG.errorWritingField(field.getName(), stdContext, instanceManager);
            }
        } catch (NoSuchFieldException e1) {
            // Field not found
        }
        throw TomcatLogger.LOG.neitherFieldNorGetterSetterFound(stdContext.getClass());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy