com.braffdev.server.core.container.injection.DependencyInjector.java Source code

Java tutorial

Introduction

Here is the source code for com.braffdev.server.core.container.injection.DependencyInjector.java

Source

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                         *
 *  Copyright (C) 2015, Markus Staudt <info@braffdev.com>                  *
 *                                                                         *
 *  This program is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

package com.braffdev.server.core.container.injection;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.braffdev.server.core.container.Container;
import com.braffdev.server.core.container.Registry;
import com.braffdev.server.core.io.logger.Logger;
import com.braffdev.server.lib.injection.Dependency;

/**
 *
 */
public class DependencyInjector {

    private static final Logger LOGGER = Logger.getLogger(DependencyInjector.class);

    /**
     * Injects all suitable dependencies to the instances located in the <code>InstanceRegistry</code> of the given container.
     *
     * @param container the container.
     */
    public static void inject(Container container) {
        Registry<Object> instanceRegistry = container.getInstanceRegistry();
        Map<String, Object> instances = instanceRegistry.getMap();

        Iterator<Object> iterator = instances.values().iterator();
        while (iterator.hasNext()) {
            DependencyInjector.inject(iterator.next(), container);
        }
    }

    /**
     * Injects the dependencies of the given object.
     *
     * @param target the object to inject it's dependencies.
     * @param container the container.
     */
    private static void inject(Object target, Container container) {
        List<Field> fields = DependencyInjector.getFields(target);

        for (Field field : fields) {
            DependencyInjector.injectField(field, target, container);
        }
    }

    /**
     * Injects the given field of the given object.
     *
     * @param field the field to inject.
     * @param target the object.
     * @param container the container.
     */
    private static void injectField(Field field, Object target, Container container) {
        Dependency dep = field.getAnnotation(Dependency.class);
        String dependencyName = dep.value();
        if (StringUtils.isBlank(dependencyName)) {
            // use the classes name if no name is provided
            dependencyName = DependencyInjectionUtils.getDefaultName(field);
        }

        Object dependency = container.getDependencyRegistry().get(dependencyName);
        if (dependency != null) {
            DependencyInjector.injectFieldDependency(field, target, dependencyName, dependency);

        } else {
            LOGGER.error("No dependency found with name \"" + dependencyName + "\" in class \""
                    + target.getClass().getSimpleName() + "\"");
        }
    }

    /**
     * Injects the given dependency to the given field of the given object.
     *
     * @param field the field to inject.
     * @param target the object.
     * @param dependencyName the name of the dependency.
     * @param dependency the dependency to inject.
     */
    private static void injectFieldDependency(Field field, Object target, String dependencyName,
            Object dependency) {
        Class<?> fieldClass = field.getType();
        if (!dependency.getClass().isAssignableFrom(fieldClass)) {
            LOGGER.error("Dependency \"" + dependencyName + "\"  (class " + dependency.getClass().getName()
                    + ") cannot be injected. This class is not assignable from the target field");
            return;
        }

        try {
            field.setAccessible(true);
            field.set(target, dependency);

            LOGGER.debug("Injected dependency \"" + dependencyName + "\" of class \"" + target.getClass() + "\"");
        } catch (Throwable t) {
            LOGGER.error("Cannot inject dependency \"" + dependencyName + "\"", t);
        }
    }

    /**
     * Determines the list of fields that need to be injected.
     *
     * @param target the object.
     * @return the list of fields.
     */
    private static List<Field> getFields(Object target) {
        List<Field> fields = new ArrayList<Field>();

        Class<?> clazz = target.getClass();
        while (!Object.class.equals(clazz)) {

            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {

                // is the Dependency annotation present?
                if (field.isAnnotationPresent(Dependency.class)) {
                    fields.add(field);
                }
            }

            clazz = clazz.getSuperclass();
        }

        return fields;
    }
}