org.jboss.spring.facade.ControllerBeanFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.spring.facade.ControllerBeanFactory.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.spring.facade;

import java.util.HashSet;
import java.util.Set;

import org.jboss.beans.info.spi.BeanInfo;
import org.jboss.beans.metadata.spi.BeanMetaData;
import org.jboss.beans.metadata.spi.ConstructorMetaData;
import org.jboss.beans.metadata.spi.PropertyMetaData;
import org.jboss.beans.metadata.spi.ValueMetaData;
import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
import org.jboss.beans.metadata.spi.factory.AbstractBeanFactory;
import org.jboss.dependency.spi.Controller;
import org.jboss.dependency.spi.ControllerContext;
import org.jboss.dependency.spi.ControllerState;
import org.jboss.kernel.spi.dependency.KernelControllerContext;
import org.jboss.reflect.spi.ClassInfo;
import org.jboss.reflect.spi.TypeInfoFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

/**
 * BeanFactory facade over MC's Controller.
 *
 * @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a>
 * @author <a href="mailto:mariusb@redhat.com">Marius Bogoevici</a>
 */
public abstract class ControllerBeanFactory implements BeanFactory {

    private Controller controller;

    public ControllerBeanFactory(Controller controller) {
        if (controller == null) {
            throw new IllegalArgumentException("Null controller");
        }

        this.controller = controller;
    }

    /**
     * Get the controller context.
     *
     * @param name the context name
     * @return context or null if not found
     */
    protected ControllerContext getInstalledContext(String name) {
        return controller.getInstalledContext(name);
    }

    /**
     * Get the controller context.
     *
     * @param name  the context name
     * @param state the state
     * @return context or null if not found
     */
    protected ControllerContext getContext(String name, ControllerState state) {
        return controller.getContext(name, state);
    }

    public Object getBean(String name) throws BeansException {
        ControllerContext context = getInstalledContext(name);
        if (context == null) {
            throw new NoSuchBeanDefinitionException(name);
        }

        return context.getTarget();
    }

    @SuppressWarnings("unchecked")
    public Object getBean(String name, Class clazz) throws BeansException {
        if (clazz == null) {
            return getBean(name);
        } else {
            return getBeanWithType(name, clazz);
        }
    }

    /**
     * Get exact bean.
     *
     * @param name  the bean name
     * @param clazz the expected class
     * @param <T>   the exact type
     * @return exact bean
     * @throws BeansException for any error
     */
    protected <T> T getBeanWithType(String name, Class<T> clazz) throws BeansException {
        Object result = getBean(name);
        if (!clazz.isInstance(result)) {
            throw new BeanNotOfRequiredTypeException(name, clazz, result.getClass());
        }

        return clazz.cast(result);
    }

    @SuppressWarnings({ "SynchronizationOnLocalVariableOrMethodParameter" })
    public Object getBean(String name, Object[] parameters) throws BeansException {
        AbstractBeanFactory result = getBeanWithType(name, AbstractBeanFactory.class);
        ConstructorMetaData cmd = result.getConstructor();

        BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder("Temp");
        for (Object parameter : parameters) {
            builder.addConstructorParameter(null, parameter);
        }
        ConstructorMetaData tempCMD = builder.getBeanMetaData().getConstructor();

        synchronized (result) {
            result.setConstructor(tempCMD);
            try {
                return createBean(result);
            } finally {
                result.setConstructor(cmd);
            }
        }
    }

    public boolean containsBean(String name) {
        return getInstalledContext(name) != null;
    }

    public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return !isPrototype(name);
    }

    public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
        Object result = getBean(name);
        return isPrototype(result);
    }

    /**
     * Is the result prototype.
     *
     * @param result the result
     * @return true if prototyle, false otherwise
     */
    protected boolean isPrototype(Object result) {
        return org.jboss.beans.metadata.spi.factory.BeanFactory.class.isInstance(result);
    }

    /**
     * Create the bean.
     *
     * @param factory the bean factory
     * @return new bean instance
     * @throws BeansException for any error
     */
    protected Object createBean(Object factory) throws BeansException {
        try {
            return org.jboss.beans.metadata.spi.factory.BeanFactory.class.cast(factory).createBean();
        } catch (Throwable t) {
            throw new FatalBeanException("Cannot create bean: " + factory, t);
        }
    }

    public boolean isTypeMatch(String name, Class clazz) throws NoSuchBeanDefinitionException {
        return clazz.isInstance(getBean(name));
    }

    @SuppressWarnings("deprecation")
    public Class getType(String name) throws NoSuchBeanDefinitionException {
        ControllerContext context = getContext(name, ControllerState.DESCRIBED);
        if (context == null) {
            throw new NoSuchBeanDefinitionException(name);
        }

        if (context instanceof KernelControllerContext) {
            KernelControllerContext kcc = (KernelControllerContext) context;
            BeanInfo beanInfo = kcc.getBeanInfo();
            ClassInfo classInfo = beanInfo.getClassInfo();
            TypeInfoFactory tif = classInfo.getTypeInfoFactory();
            // it's a bean factory
            if (tif.getTypeInfo(AbstractBeanFactory.class).isAssignableFrom(classInfo)) {
                return getPrototypeClass(kcc);
            } else {
                return classInfo.getType();
            }
        }
        return null;
    }

    /**
     * Get prototype class.
     *
     * @param cc the controller context
     * @return prototype's class
     */
    protected Class<?> getPrototypeClass(ControllerContext cc) {
        if (cc instanceof KernelControllerContext == false) {
            return null;
        }

        KernelControllerContext kcc = (KernelControllerContext) cc;
        BeanMetaData bmd = kcc.getBeanMetaData();
        Set<PropertyMetaData> properties = bmd.getProperties();
        for (PropertyMetaData pmd : properties) {
            if ("bean".equals(pmd.getName())) {
                ValueMetaData value = pmd.getValue();
                if (value != null && value.getUnderlyingValue() != null) {
                    String className = value.getUnderlyingValue().toString();
                    return getBeanClass(className, kcc);
                } else {
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * Get the bean class.
     *
     * @param className the class name
     * @param context   the context
     * @return bean's class
     * @throws BeansException for any error
     */
    protected Class<?> getBeanClass(String className, KernelControllerContext context) throws BeansException {
        try {
            ClassLoader cl = context.getClassLoader();
            return cl.loadClass(className);
        } catch (Throwable t) {
            throw new FatalBeanException("Cannot load class: " + className + ", context: " + context, t);
        }
    }

    public String[] getAliases(String name) {
        ControllerContext context = getContext(name, null);
        if (context == null || context.getAliases() == null) {
            return new String[] {};
        } else {
            Set<Object> aliases = context.getAliases();
            String[] result = new String[aliases.size()];
            int i = 0;
            for (Object alias : aliases) {
                result[i++] = alias.toString();
            }
            return result;
        }
    }
}