hsa.awp.common.util.StaticInitializerBeanFactoryPostProcessor.java Source code

Java tutorial

Introduction

Here is the source code for hsa.awp.common.util.StaticInitializerBeanFactoryPostProcessor.java

Source

/*
 * Copyright (c) 2010-2012 Matthias Klass, Johannes Leimer,
 *               Rico Lieback, Sebastian Gabriel, Lothar Gesslein,
 *               Alexander Rampp, Kai Weidner
 *
 * This file is part of the Physalix Enrollment System
 *
 * Foobar 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.
 *
 * Foobar 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */

package hsa.awp.common.util;

import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;

/**
 * This {@link BeanFactoryPostProcessor} can initialize static variables in Spring Beans.
 *
 * @author johannes
 */
public class StaticInitializerBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    /**
     * The map of all classes containing static variables to initialize.
     */
    private Map<?, ?> classes;

    /**
     * The {@link BeanWrapperImpl} which is used to convert the parameters if necessary.
     */
    private BeanWrapperImpl bri;

    /**
     * Initializes a new {@link StaticInitializerBeanFactoryPostProcessor} and instantiates a new {@link BeanWrapperImpl}.
     */
    public StaticInitializerBeanFactoryPostProcessor() {

        bri = new BeanWrapperImpl();
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) {

        for (Iterator<?> classIterator = classes.keySet().iterator(); classIterator.hasNext();) {
            String className = (String) classIterator.next();
            // System.out.println("Class " + className + ":");
            Map<?, ?> vars = (Map<?, ?>) classes.get(className);
            Class<?> c = null;
            try {
                c = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new StaticInitializerBeansException("Class not found for " + className, e);
            }
            Method[] methods = c.getMethods();
            for (Iterator<?> fieldIterator = vars.keySet().iterator(); fieldIterator.hasNext();) {
                String fieldName = (String) fieldIterator.next();
                Object value = vars.get(fieldName);
                Method method = findStaticSetter(methods, fieldName);
                if (method == null) {
                    throw new StaticInitializerBeansException(
                            "No static setter method found for class " + className + ", field " + fieldName);
                }
                // System.out.println("\tFound method " + method.getName() + " for field " + fieldName + ", value " + value);
                Object newValue = bri.convertIfNecessary(value, getPropertyType(method));
                try {
                    method.invoke(null, new Object[] { newValue });
                } catch (Exception e) {
                    throw new StaticInitializerBeansException("Invocation of method " + method.getName()
                            + " on class " + className + " with value " + value + " failed.", e);
                }
            }
        }
    }

    /**
     * Look for a static setter method for field named fieldName in Method[]. Return null if none found.
     *
     * @param methods   {@link Method} array where to look for the setter
     * @param fieldName the name of the field
     * @return the static setter {@link Method} object
     */
    private Method findStaticSetter(Method[] methods, String fieldName) {

        String methodName = setterName(fieldName);
        for (int i = 0; i < methods.length; i++) {
            if (methods[i].getName().equals(methodName) && Modifier.isStatic(methods[i].getModifiers())) {
                return methods[i];
            }
        }
        return null;
    }

    /**
     * Returns the standard setter name for the given field name.
     *
     * @param fieldName the name of the field
     * @return the name of the setter
     */
    private String setterName(String fieldName) {

        String nameToUse = null;
        if (fieldName.length() == 1) {
            if (Character.isLowerCase(fieldName.charAt(0))) {
                nameToUse = fieldName.toUpperCase();
            } else {
                nameToUse = fieldName;
            }
        } else {
            if (Character.isLowerCase(fieldName.charAt(0)) && Character.isLowerCase(fieldName.charAt(1))) {
                nameToUse = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            } else {
                nameToUse = fieldName;
            }
        }
        return "set" + nameToUse;
    }

    /**
     * Finds the parameter types from the first argument of the given method.
     *
     * @param setter the method to find out the parameter types
     * @return the parameter type of the first argument
     */
    private Class<?> getPropertyType(Method setter) {

        Class<?>[] params = setter.getParameterTypes();
        if (params.length != 1) {
            throw new StaticInitializerBeansException("bad write method arg count: " + setter);
        }
        return params[0];
    }

    /**
     * The {@link Map} of all classes containing static variables to initialize. Every entry in this map represents one class. Every
     * class entry consists of a map. Here are the variable names mapped to the values.
     *
     * @param classes the map of the classes to initialize
     */
    public void setClasses(Map<?, ?> classes) {

        this.classes = classes;
    }
}

/**
 * This exception is thrown when an exception occurs in the {@link StaticInitializerBeanFactoryPostProcessor}.
 *
 * @author johannes
 */
class StaticInitializerBeansException extends BeansException {
    /**
     * serial version UID.
     */
    private static final long serialVersionUID = -6821119492403266859L;

    /**
     * Constructs a new {@link StaticInitializerBeansException} with the given message.
     *
     * @param message the message
     */
    StaticInitializerBeansException(String message) {

        super(message);
    }

    /**
     * Constructs a new {@link StaticInitializerBeansException} with the given message and cause.
     *
     * @param message the message
     * @param cause   the cause of this exception
     */
    StaticInitializerBeansException(String message, Throwable cause) {

        super(message, cause);
    }
}