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

org.kasource.spring.integration.SpringContext Maven / Gradle / Ivy

package org.kasource.spring.integration;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Set;

import javax.annotation.Resource;

import org.kasource.commons.reflection.filter.FieldFilterBuilder;
import org.kasource.commons.reflection.util.FieldUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Provides static access to a spring context. Can be used in integration scenarios when Spring is not bootstrapped with
 * the application.
 * 
 * @author rikardwi
 **/
public class SpringContext {

    public static final String ENABLE_SYSTEM_PROPERTY = "spring.context.enable";
    public static final String CONTEXT_LOCATION_SYSTEM_PROPERTY = "spring.context.location";
    private static final String DEFAULT_CONTEXT_LOCATION = "spring/application-context.xml";

    private static final SpringContext INSTANCE = new SpringContext();

    private ApplicationContext applicationContext;
    private String contextLocation;

    private SpringContext() {
        loadContext();
    }

    /**
     * Returns the bean from the Spring Application context of the supplied name and type.
     * 
     * @param 
     *            Type of the bean
     * @param beanName
     *            Name of the bean to retrieve.
     * @param ofType
     *            Type of the bean
     * 
     * @return The bean in the spring context found for the supplied name and type.
     * 
     * @throws IllegalStateException
     *             if not enabled
     **/
    public static  T getBean(String beanName, Class ofType) throws IllegalStateException {
        checkEnabled();
        return INSTANCE.getBeanOfType(beanName, ofType);
    }

    /**
     * Inject dependencies of Fields on the target object, which is annotated with @Resource or @Autowired.
     * 
     * @param target
     *            Object to inject dependencies to.
     * 
     * @throws IllegalStateException
     *             if not enabled or dependencies could not be injected or error occurs while trying to inject values.
     **/
    public static void injectDependencies(Object target) throws IllegalStateException {
        checkEnabled();
        INSTANCE.injectDependenciesForObject(target);

    }

    /**
     * Returns true of the context loading is enabled, else false.
     * 
     * @return true of the context loading is enabled, else false.
     **/
    private static boolean isEnabled() {
        String enable = System.getProperty(ENABLE_SYSTEM_PROPERTY);
        if (enable != null && enable.toLowerCase().equals("true")) {
            return true;
        }
        return false;
    }

    /**
     * Loads a spring application context from classpath.
     **/
    private void loadContext() {

        if (isEnabled()) {
            System.out.println("loads app context ");
            contextLocation = System.getProperty(CONTEXT_LOCATION_SYSTEM_PROPERTY, DEFAULT_CONTEXT_LOCATION);
            applicationContext = new ClassPathXmlApplicationContext(contextLocation);
        }

    }

    /**
     * Throws exception if not enabled.
     * 
     * @throws IllegalStateException
     *             if the context loading is not enabled.
     **/
    private static void checkEnabled() throws IllegalStateException {
        if (!isEnabled()) {
            throw new IllegalStateException("The Spring Context is disabled, set system property "
                        + ENABLE_SYSTEM_PROPERTY + "=true to enable it.");
        }
    }

    /**
     * Returns the bean from the Spring Application context of the supplied name and type.
     * 
     * @param 
     *            Type of the bean
     * @param beanName
     *            Name of the bean to retrieve.
     * @param ofType
     *            Type of the bean
     * 
     * @return The bean in the spring context found for the supplied name and type.
     **/
    private  T getBeanOfType(String beanName, Class ofType) {

        return applicationContext.getBean(beanName, ofType);
    }

    /**
     * Inject dependencies of Fields on the target object, which is annotated with @Resource or @Autowired.
     * 
     * @param target
     *            Object to inject dependencies to.
     * 
     * @throws IllegalStateException
     *             if dependencies could not be injected or error occurs while trying to inject values.
     **/
    private void injectDependenciesForObject(Object target) throws IllegalStateException {

        Set annotatedFields = FieldUtils.getFields(target.getClass(),
                    new FieldFilterBuilder().annotated(Resource.class).or().annotated(Autowired.class).build());
        for (Field field : annotatedFields) {
            injectFieldValue(target, field);
        }

    }

    /**
     * Inject dependencies to the supplied field that is annotated with @Resource or @Autowired.
     * 
     * @param target
     *            Object to inject dependencies to.
     * @param field
     *            The field to inject dependency into.
     * 
     * @throws IllegalStateException
     *             if dependencies could not be injected or error occurs while trying to inject values.
     **/
    private void injectFieldValue(Object target, Field field) throws IllegalStateException {
        try {
            if (field.isAnnotationPresent(Autowired.class)) {
                injectByAutowired(target, field);
            } else {
                injectByResource(target, field);
            }
        } catch (Exception e) {
            throw new IllegalStateException("Could not inject value into " + field, e);
        }
    }

    /**
     * Inject value to field by @Resource annotation.
     * 
     * @param target
     *            Object to inject dependencies to.
     * @param field
     *            The field to inject dependency into.
     * 
     * @throws IllegalAccessException
     *             If setting the value the field causes this exception.
     **/
    private void injectByResource(Object target, Field field) throws IllegalAccessException {
        Resource resource = field.getAnnotation(Resource.class);
        if (resource.name().length() > 0) {
            injectByName(target, field, resource.name());
        } else {
            injectByType(target, field);
        }
    }

    /**
     * Inject value to field by @Autowired annotation.
     * 
     * @param target
     *            Object to inject dependencies to.
     * @param field
     *            The field to inject dependency into.
     * 
     * @throws IllegalAccessException
     *             If setting the value the field causes this exception.
     **/
    private void injectByAutowired(Object target, Field field) throws IllegalAccessException {
        Qualifier qualifier = field.getAnnotation(Qualifier.class);
        if (qualifier != null && qualifier.value().length() > 0) {
            injectByName(target, field, qualifier.value());
        } else {
            injectByType(target, field);
        }
    }

    /**
     * Inject dependency into the field, looks up beans in the application context of the fields type.
     * 
     * @param target
     *            Target object to inject dependency to.
     * @param field
     *            Field to inject value to.
     * 
     * @throws IllegalArgumentException
     *             If setting the value the field causes this exception.
     * @throws IllegalAccessException
     *             If setting the value the field causes this exception.
     * @throws IllegalStateException
     *             If no bean of the fields type could be found or if more than one bean of the fields type is found.
     **/
    private void injectByType(Object target, Field field) throws IllegalArgumentException, IllegalAccessException,
                IllegalStateException {
        String[] beans = applicationContext.getBeanNamesForType(field.getType());
        if (beans.length == 1) {
            injectByName(target, field, beans[0]);
        } else if (beans.length == 0) {
            throw new IllegalStateException("No beans found of type " + field.getType() + " in context "
                        + contextLocation);
        } else {
            throw new IllegalStateException("More than one bean found of type " + field.getType() + " in context "
                        + contextLocation + " possible candidates are: " + Arrays.asList(beans));
        }
    }

    /**
     * Inject dependency into the field, by looking up bean with the supplied name in the spring application context.
     * 
     * @param target
     *            Target object to inject dependency to.
     * @param field
     *            Field to inject value to.
     * @param name
     *            Name of the bean to inject into field.
     * 
     * @throws IllegalArgumentException
     *             If setting the value the field causes this exception.
     * @throws IllegalAccessException
     *             If setting the value the field causes this exception.
     */
    private void injectByName(Object target, Field field, String name) throws IllegalArgumentException,
                IllegalAccessException {
        Object object = applicationContext.getBean(name);
        field.setAccessible(true);
        field.set(target, object);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy