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

com.sun.ejb.containers.interceptors.CallbackInvocationContext Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation.
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.ejb.containers.interceptors;

import static com.sun.ejb.containers.interceptors.InterceptorUtil.hasCompatiblePrimitiveWrapper;
import static com.sun.enterprise.deployment.LifecycleCallbackDescriptor.CallbackType.AROUND_CONSTRUCT;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import com.sun.ejb.containers.BaseContainer;
import com.sun.ejb.containers.EJBContextImpl;
import com.sun.enterprise.container.common.spi.util.InterceptorInfo;
import com.sun.enterprise.deployment.LifecycleCallbackDescriptor.CallbackType;

import jakarta.interceptor.InvocationContext;

/**
 * Concrete InvocationContext implementation passed to callback methods defined in interceptor classes.
 */
public class CallbackInvocationContext implements InvocationContext {

    private Map contextData;
    private int callbackIndex = 0;
    private CallbackChainImpl callbackChain;
    private Object[] interceptorInstances;
    private Object targetObjectInstance;
    private CallbackType eventType;
    Method method;

    // For AroundConstruct callback
    private Class targetObjectClass;
    private Constructor ctor;
    private Class[] ctorParamTypes;
    private Object[] ctorParams;
    private BaseContainer container;
    private EJBContextImpl ctx;
    private InterceptorInfo interceptorInfo;

    public CallbackInvocationContext(Object targetObjectInstance, Object[] interceptorInstances, CallbackChainImpl chain) {
        this.targetObjectInstance = targetObjectInstance;
        this.interceptorInstances = interceptorInstances;
        callbackChain = chain;
    }

    public CallbackInvocationContext(Object targetObjectInstance, Object[] interceptorInstances, CallbackChainImpl chain, CallbackType eventType) {
        this(targetObjectInstance, interceptorInstances, chain);
        this.eventType = eventType;
    }

    /**
     * AroundConstruct
     */
    public CallbackInvocationContext(Class targetObjectClass, Object[] interceptorInstances, CallbackChainImpl chain, CallbackType eventType, InterceptorInfo interceptorInfo) {
        this(null, interceptorInstances, chain, eventType);

        this.targetObjectClass = targetObjectClass;

        Constructor[] ctors = targetObjectClass.getConstructors();
        for (Constructor ctor0 : ctors) {
            ctor = ctor0;
            if (ctor0.getParameterTypes().length == 0) {
                // We are looking for a no-arg constructor
                break;
            }
        }

        ctorParamTypes = ctor.getParameterTypes();
        ctorParams = new Object[ctorParamTypes.length];

        this.interceptorInfo = interceptorInfo;
    }

    /**
     * AroundConstruct
     */
    public CallbackInvocationContext(Class targetObjectClass, Object[] interceptorInstances, CallbackChainImpl chain, CallbackType eventType, BaseContainer container, EJBContextImpl ctx) {
        this(targetObjectClass, interceptorInstances, chain, eventType, null);

        this.container = container;
        this.ctx = ctx;
    }

    // InvocationContext methods

    @Override
    public Object getTarget() {
        return targetObjectInstance;
    }

    public Object[] getInterceptorInstances() {
        return interceptorInstances;
    }

    @Override
    public Object getTimer() {
        return null;
    }

    @Override
    public Constructor getConstructor() {
        if (eventType == AROUND_CONSTRUCT) {
            return ctor;
        }
        return null;
    }

    @Override
    public Method getMethod() {
        if (eventType == AROUND_CONSTRUCT) {
            return null;
        }
        return method;
    }

    @Override
    public Object[] getParameters() {
        if (eventType == AROUND_CONSTRUCT) {
            return ctorParams;
        } else {
            throw new IllegalStateException("not applicable to Callback methods");
        }
    }

    @Override
    public void setParameters(Object[] params) {
        if (eventType == AROUND_CONSTRUCT) {
            checkSetParameters(params);
            ctorParams = params;
        } else {
            throw new IllegalStateException("not applicable to Callback methods");
        }
    }

    @Override
    public Map getContextData() {
        if (contextData == null) {
            contextData = new HashMap<>();
        }

        return contextData;
    }

    @Override
    public Object proceed() throws Exception {
        try {
            callbackIndex++;
            return callbackChain.invokeNext(callbackIndex, this);
        } catch (Exception ex) {
            throw ex;
        } catch (Throwable th) {
            throw new Exception(th);
        }
    }

    /**
     * Called from Interceptor Chain to create the bean instance.
     */
    public void invokeSpecial() throws Throwable {
        if (eventType == AROUND_CONSTRUCT) {
            if (container == null) {
                targetObjectInstance = targetObjectClass.newInstance();
                interceptorInfo.setTargetObjectInstance(targetObjectInstance);
            } else {
                container.createEjbInstanceForInterceptors(ctorParams, ctx);
                targetObjectInstance = ctx.getEJB();
            }
        } // else do nothing? XXX
    }

    private void checkSetParameters(Object[] params) {
        if (ctor == null) {
            throw new IllegalStateException("Internal Error: Got null constructor");
        }

        if (params == null && ctorParamTypes.length != 0) {
            throw new IllegalArgumentException("Wrong number of parameters for " + " constructor: " + ctor);
        }
        if (params != null && ctorParamTypes.length != params.length) {
            throw new IllegalArgumentException("Wrong number of parameters for " + " constructor: " + ctor);
        }

        int index = 0;
        for (Class type : ctorParamTypes) {
            if (params[index] == null) {
                if (type.isPrimitive()) {
                    throw new IllegalArgumentException("Parameter type mismatch for constructor " + ctor
                            + ".  Attempt to set a null value for Arg[" + index + "]. Expected a value of type: " + type.getName());
                }
            } else if (type.isPrimitive()) {
                if (!hasCompatiblePrimitiveWrapper(type, params[index].getClass())) {
                    throw new IllegalArgumentException("Parameter type mismatch for constructor " + ctor + ".  Arg[" + index + "] type: "
                            + params[index].getClass().getName() + " is not compatible with the expected type: " + type.getName());
                }
            } else if (!type.isAssignableFrom(params[index].getClass())) {
                throw new IllegalArgumentException("Parameter type mismatch for constructor " + ctor + ".  Arg[" + index + "] type: "
                        + params[index].getClass().getName() + " does not match the expected type: " + type.getName());
            }

            index++;
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy