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

org.glassfish.hk2.configuration.internal.ConfiguredByInjectionResolver Maven / Gradle / Ivy

/*
 * Copyright (c) 2014, 2024 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 org.glassfish.hk2.configuration.internal;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Singleton;

import org.glassfish.hk2.api.ActiveDescriptor;
import org.glassfish.hk2.api.DescriptorVisibility;
import org.glassfish.hk2.api.Injectee;
import org.glassfish.hk2.api.InjectionResolver;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.Visibility;
import org.glassfish.hk2.configuration.api.Configured;

/**
 * @author jwells
 *
 */
@Singleton
@Visibility(DescriptorVisibility.LOCAL)
public class ConfiguredByInjectionResolver implements
        InjectionResolver {
    @Inject @Named(InjectionResolver.SYSTEM_RESOLVER_NAME)
    private InjectionResolver systemResolver;
    
    @Inject
    private ConfiguredByContext context;

    private final ReentrantLock lock = new ReentrantLock();
    private final ConcurrentHashMap, BeanInfo> beanMap = new ConcurrentHashMap, BeanInfo>(); 
    
    private static String getParameterNameFromConstructor(Constructor cnst, int position) {
        Annotation paramAnnotations[] = cnst.getParameterAnnotations()[position];
        
        Configured c = null;
        for (Annotation anno : paramAnnotations) {
            if (Configured.class.equals(anno.annotationType())) {
                c = (Configured) anno;
                break;
            }
        }
        if (c == null) return null;
        
        String key = c.value();
        if (BeanUtilities.isEmpty(key)) {
            throw new AssertionError("Not enough in @Configured annotation in constructor " + cnst + " at parameter index " + position);
        }
        
        return key;
    }
    
    private static String getParameterNameFromMethod(Method method, int position) {
        Annotation paramAnnotations[] = method.getParameterAnnotations()[position];
        
        Configured c = null;
        for (Annotation anno : paramAnnotations) {
            if (Configured.class.equals(anno.annotationType())) {
                c = (Configured) anno;
                break;
            }
        }
        if (c == null) return null;
        
        String key = c.value();
        if (BeanUtilities.isEmpty(key)) {
            throw new AssertionError("Not enough in @Configured annotation in method " + method + " at parameter index " + position);
        }
        
        return key;
    }

    /* (non-Javadoc)
     * @see org.glassfish.hk2.api.InjectionResolver#resolve(org.glassfish.hk2.api.Injectee, org.glassfish.hk2.api.ServiceHandle)
     */
    @Override
    public Object resolve(Injectee injectee, ServiceHandle root) {
        lock.lock();
        try {
            ActiveDescriptor injecteeParent = injectee.getInjecteeDescriptor();
            if (injecteeParent == null) return systemResolver.resolve(injectee, root);
            
            AnnotatedElement ae = injectee.getParent();
            if (ae == null) return systemResolver.resolve(injectee, root);
            
            String parameterName = null;
            if (ae instanceof Field) {
                parameterName = BeanUtilities.getParameterNameFromField((Field) ae, false);
            }
            else if (ae instanceof Constructor) {
                parameterName = getParameterNameFromConstructor((Constructor) ae, injectee.getPosition());
            }
            else if (ae instanceof Method){
                parameterName = getParameterNameFromMethod((Method) ae, injectee.getPosition());
            }
            else {
                return systemResolver.resolve(injectee, root);
            }
            
            if (parameterName == null) return systemResolver.resolve(injectee, root);
            
            ActiveDescriptor workingOn = context.getWorkingOn();
            if (workingOn == null) return systemResolver.resolve(injectee, root);
            
            BeanInfo beanInfo = beanMap.get(workingOn);
            if (beanInfo == null) {
                throw new IllegalStateException("Could not find a configuration bean for " + injectee + " with descriptor " + workingOn);
            }
            
            return BeanUtilities.getBeanPropertyValue(injectee.getRequiredType(), parameterName, beanInfo);
        } finally {
            lock.unlock();
        }
    }

    /* (non-Javadoc)
     * @see org.glassfish.hk2.api.InjectionResolver#isConstructorParameterIndicator()
     */
    @Override
    public boolean isConstructorParameterIndicator() {
        return true;
    }

    /* (non-Javadoc)
     * @see org.glassfish.hk2.api.InjectionResolver#isMethodParameterIndicator()
     */
    @Override
    public boolean isMethodParameterIndicator() {
        return true;
    }
    
    /* package */ BeanInfo addBean(ActiveDescriptor descriptor, Object bean, String type, Object metadata) {
        lock.lock();
        try {
            BeanInfo retVal = new BeanInfo(type, descriptor.getName(), bean, metadata);
            beanMap.put(descriptor, retVal);
            return retVal;
        } finally {
            lock.unlock();
        }
    }
    
    /* package */ void removeBean(ActiveDescriptor descriptor) {
        
        lock.lock();
        try {
            beanMap.remove(descriptor);
        } finally {
            lock.unlock();
        }
    }
    
    @Override
    public String toString() {
        return "ConfiguredByInjectionResolver(" + System.identityHashCode(this) + ")";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy