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

org.jboss.weld.injection.ConstructorInjectionPoint Maven / Gradle / Ivy

There is a newer version: 3.0.0.Alpha1
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.weld.injection;

import static org.jboss.weld.injection.Exceptions.rethrowException;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.TransientReference;
import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.Bean;

import org.jboss.weld.annotated.enhanced.ConstructorSignature;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
import org.jboss.weld.construction.api.AroundConstructCallback;
import org.jboss.weld.construction.api.ConstructionHandle;
import org.jboss.weld.context.CreationalContextImpl;
import org.jboss.weld.exceptions.WeldException;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.security.GetAccessibleCopyOfMember;
import org.jboss.weld.util.collections.Arrays2;
import org.jboss.weld.util.reflection.Reflections;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
 * High-level representation of an injected constructor. This class does not need to be serializable because it is never injected.
 *
 * @author Pete Muir
 * @author Jozef Hartinger
 *
 * @param 
 */
@SuppressFBWarnings("EQ_DOESNT_OVERRIDE_EQUALS")
public class ConstructorInjectionPoint extends AbstractCallableInjectionPoint> {

    private final AnnotatedConstructor constructor;
    private final ConstructorSignature signature;
    private final Constructor accessibleConstructor;

    protected ConstructorInjectionPoint(EnhancedAnnotatedConstructor constructor, Bean declaringBean, Class declaringComponentClass, InjectionPointFactory factory, BeanManagerImpl manager) {
        super(constructor, declaringBean, declaringComponentClass, false, factory, manager);
        this.constructor = constructor.slim();
        this.signature = constructor.getSignature();
        this.accessibleConstructor = AccessController.doPrivileged(new GetAccessibleCopyOfMember>(constructor.getJavaMember()));
    }

    public T newInstance(BeanManagerImpl manager, CreationalContext ctx) {
        CreationalContext transientReferenceContext = null;
        if (hasTransientReferenceParameter) {
            transientReferenceContext = manager.createCreationalContext(null);
        }
        try {
            Object[] parameterValues = getParameterValues(manager, ctx, transientReferenceContext);
            if (ctx instanceof CreationalContextImpl) {
                CreationalContextImpl weldCtx = Reflections.cast(ctx);
                return invokeAroundConstructCallbacks(parameterValues, weldCtx);
            } else {
                return newInstance(parameterValues);
            }
        } finally {
            if (hasTransientReferenceParameter) {
                transientReferenceContext.release();
            }
        }
    }

    private T invokeAroundConstructCallbacks(Object[] parameters, CreationalContextImpl ctx) {
        final List> callbacks = ctx.getAroundConstructCallbacks();
        if (callbacks.isEmpty()) {
            return newInstance(parameters);
        }
        final Iterator> iterator = callbacks.iterator();
        return invokeAroundConstructCallback(iterator.next(), new ConstructionHandle() {
            @Override
            public T proceed(Object[] parameters, Map data) {
                if (iterator.hasNext()) {
                    return invokeAroundConstructCallback(iterator.next(), this, getComponentConstructor(), parameters, data);
                } else {
                    return newInstance(parameters);
                }
            }
        }, getComponentConstructor(), parameters, new HashMap());
    }

    private T invokeAroundConstructCallback(AroundConstructCallback callback, ConstructionHandle ctx, AnnotatedConstructor constructor, Object[] parameters, Map data) {
        try {
            return callback.aroundConstruct(ctx, constructor, parameters, data);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new WeldException(e);
        }
    }

    protected T newInstance(Object[] parameterValues) {
        try {
            return accessibleConstructor.newInstance(parameterValues);
        } catch (IllegalArgumentException e) {
            rethrowException(e);
        } catch (InstantiationException e) {
            rethrowException(e);
        } catch (IllegalAccessException e) {
            rethrowException(e);
        } catch (InvocationTargetException e) {
            rethrowException(e);
        }
        return null;
    }

    /**
     * Helper method for getting the current parameter values from a list of annotated parameters.
     *
     * @param parameters The list of annotated parameter to look up
     * @param manager The Bean manager
     * @return The object array of looked up values
     */
    public Object[] getParameterValues(BeanManagerImpl manager, CreationalContext ctx, CreationalContext transientReference) {
        if (getInjectionPoints().isEmpty()) {
            return Arrays2.EMPTY_ARRAY;
        }
        Object[] parameterValues = new Object[getParameterInjectionPoints().size()];
        List> parameters = getParameterInjectionPoints();
        for (int i = 0; i < parameterValues.length; i++) {
            ParameterInjectionPoint param = parameters.get(i);
            if (hasTransientReferenceParameter && param.getAnnotated().isAnnotationPresent(TransientReference.class)) {
                parameterValues[i] = param.getValueToInject(manager, transientReference);
            } else {
                parameterValues[i] = param.getValueToInject(manager, ctx);
            }
        }
        return parameterValues;
    }

    public AnnotatedConstructor getAnnotated() {
        return constructor;
    }

    public ConstructorSignature getSignature() {
        return signature;
    }

    public AnnotatedConstructor getComponentConstructor() {
        return constructor;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((constructor == null) ? 0 : constructor.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!super.equals(obj)) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        ConstructorInjectionPoint other = (ConstructorInjectionPoint) obj;
        if (constructor == null) {
            if (other.constructor != null) {
                return false;
            }
        } else if (!constructor.equals(other.constructor)) {
            return false;
        }
        return true;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy