org.carewebframework.api.spring.FrameworkBeanFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.carewebframework.api.spring.FrameworkBeanFactory.java

Source

/**
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 
 * If a copy of the MPL was not distributed with this file, You can obtain one at 
 * http://mozilla.org/MPL/2.0/.
 * 
 * This Source Code Form is also subject to the terms of the Health-Related Additional
 * Disclaimer of Warranty and Limitation of Liability available at
 * http://www.carewebframework.org/licensing/disclaimer.
 */
package org.carewebframework.api.spring;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.PlaceholderConfigurerSupport;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.ApplicationContext;

import org.w3c.dom.Attr;
import org.w3c.dom.Node;

/**
 * Implementation of DefaultListableBeanFactory that supports namespace extensions to bean
 * declarations. Specifically, it supports:
 * <p>
 * The <b>cwf:override</b> attribute that can explicitly allow or disallow the overriding of a bean
 * definition, independent of the settings for the application context. It should be applied to the
 * overriding bean definition.
 * <p>
 * The <b>cwf:final</b> attribute that can prevent a bean definition from being overridden under any
 * circumstances. If set to true, it takes precedence over the application context settings and the
 * cwf:override setting of any overriding bean definition. The default attribute value is false.
 */
public class FrameworkBeanFactory extends DefaultListableBeanFactory {

    private static final String CAN_OVERRIDE_ATTR = FrameworkBeanFactory.class.getName() + ".canOverride";

    private static final String IS_FINAL_ATTR = FrameworkBeanFactory.class.getName() + ".isFinal";

    private enum BeanOverride {
        DEFAULT, // Override according to application context setting.
        NEVER, // Never override.  An exception is raised if an existing bean definition is found.
        ALWAYS, // Always override.  Any existing bean definition is replaced.
        IGNORE // Ignore if a bean definition already exists.  No exception is raised.
    };

    /**
     * This is a decorator for the transferring attribute values from the custom namespace to a
     * specified metadata attribute on the bean definition.
     */
    private static class Decorator implements BeanDefinitionDecorator {

        private final String attributeName;

        /**
         * Constructor
         * 
         * @param attributeName The name of the bean definition attribute under which the custom
         *            namespace attribute value will be stored.
         */
        private Decorator(String attributeName) {
            this.attributeName = attributeName;
        }

        @Override
        public BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder holder, ParserContext ctx) {
            holder.getBeanDefinition().setAttribute(attributeName, ((Attr) source).getValue());
            return holder;
        }

    }

    /**
     * Namespace handler registers the decorator for the cwf:override attribute.
     */
    public static class NamespaceHandler extends NamespaceHandlerSupport {

        @Override
        public void init() {
            super.registerBeanDefinitionDecoratorForAttribute("final", new Decorator(IS_FINAL_ATTR));
            super.registerBeanDefinitionDecoratorForAttribute("override", new Decorator(CAN_OVERRIDE_ATTR));
        }
    }

    // Default override behavior as dictated by the application context.
    private boolean defaultOverriding = true;

    /**
     * Creates a bean factory.
     * 
     * @param parentContext Parent application context, if any. When specified, any placeholder
     *            configurers found in the parent context will be registered in this bean factory.
     * @param parentBeanFactory The parent bean factory, if any.
     */
    public FrameworkBeanFactory(ApplicationContext parentContext, BeanFactory parentBeanFactory) {
        super(parentBeanFactory);

        if (parentContext != null) {
            for (Object configurer : parentContext.getBeansOfType(PlaceholderConfigurerSupport.class, false, false)
                    .values()) {
                registerSingleton("", configurer);
            }
        }
    }

    /**
     * The application context will call this to set the override behavior of the bean factory. We
     * intercept this to set this as the default behavior for the bean factory. This setting is used
     * when no cwf:override attribute is specified.
     */
    @Override
    public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
        super.setAllowBeanDefinitionOverriding(allowBeanDefinitionOverriding);
        this.defaultOverriding = allowBeanDefinitionOverriding;
    }

    /**
     * Intercepts the call set the override behavior of the bean factory prior to registering the
     * bean. The override behavior is set to the cwf:override setting of the bean definition or, in
     * the absence of this setting, to the default override behavior for the bean factory and by the
     * cwf:final setting which can be used to prevent a bean declaration from ever being overridden.
     */
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
        boolean canOverride = defaultOverriding;
        BeanDefinition oldBeanDefinition = containsBeanDefinition(beanName) ? getBeanDefinition(beanName) : null;
        String override = oldBeanDefinition == null ? null : getAttribute(beanDefinition, CAN_OVERRIDE_ATTR);
        String isfinal = oldBeanDefinition == null ? null : getAttribute(oldBeanDefinition, IS_FINAL_ATTR);

        if (override != null) {
            switch (BeanOverride.valueOf(override.toUpperCase())) {
            case ALWAYS:
                canOverride = true;
                break;

            case NEVER:
                canOverride = false;
                break;

            case IGNORE:
                return;
            }
        }

        if (canOverride && "true".equalsIgnoreCase(isfinal)) {
            canOverride = false;
        }

        super.setAllowBeanDefinitionOverriding(canOverride);
        super.registerBeanDefinition(beanName, beanDefinition);
    }

    /**
     * Searches this bean definition and all originating bean definitions until it finds the
     * requested attribute.
     * 
     * @param beanDefinition Bean definition.
     * @param attributeName Attribute to locate.
     * @return The value of the attribute, or null if not found.
     */
    private String getAttribute(BeanDefinition beanDefinition, String attributeName) {
        String value = null;

        while (beanDefinition != null) {
            value = (String) beanDefinition.getAttribute(attributeName);

            if (value != null) {
                break;
            }

            beanDefinition = beanDefinition.getOriginatingBeanDefinition();
        }

        return value;
    }
}