org.springframework.data.gemfire.GemfireBeanFactoryLocator.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.data.gemfire.GemfireBeanFactoryLocator.java

Source

/*
 * Copyright 2010-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.data.gemfire;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * {@link BeanFactoryLocator} used for storing Spring application context/bean factory for Gemfire
 * user components (or {@link com.gemstone.gemfire.cache.Declarable}. As opposed to the "traditional"
 * {@link org.springframework.beans.factory.access.SingletonBeanFactoryLocator} this implementation does
 * not require any configuration file; it rather assume declaration inside an application context
 * (usually through {@link com.gemstone.gemfire.cache.CacheFactory} which it will store under the name
 * and aliases of the bean (so the same "registry" can be used for storing multiple BeanFactories). 
 * If there is only one BeanFactory registered then a null value can be used with {@link #setBeanName(String)}.
 * 
 * <p/> In most cases, one does not need to use this class directly as it is used internally 
 * by {@link com.gemstone.gemfire.cache.CacheFactory}.
 * 
 * @author Costin Leau
 */
public class GemfireBeanFactoryLocator
        implements BeanFactoryLocator, BeanFactoryAware, BeanNameAware, DisposableBean, InitializingBean {

    private static final Log log = LogFactory.getLog(GemfireBeanFactoryLocator.class);

    // alias/bean name <-> BeanFactory lookup
    private static final ConcurrentMap<String, BeanFactory> beanFactories = new ConcurrentHashMap<String, BeanFactory>();

    // default factory to return
    private static volatile boolean canUseDefaultBeanFactory = true;
    private static volatile BeanFactory defaultFactory = null;

    private static class SimpleBeanFactoryReference implements BeanFactoryReference {

        private BeanFactory bf;

        SimpleBeanFactoryReference(BeanFactory bf) {
            this.bf = bf;
        }

        public BeanFactory getFactory() {
            Assert.notNull(bf, "beanFactory already released or closed");
            return bf;
        }

        public void release() throws FatalBeanException {
            bf = null;
        }
    }

    private BeanFactory beanFactory;
    private String[] names;

    // default factory name
    private String factoryName = GemfireBeanFactoryLocator.class.getName();

    public void afterPropertiesSet() {
        // add the factory as default if possible (if it's the only one)
        synchronized (GemfireBeanFactoryLocator.class) {
            canUseDefaultBeanFactory = beanFactories.isEmpty();
            if (canUseDefaultBeanFactory) {
                if (defaultFactory == null) {
                    defaultFactory = beanFactory;
                    if (log.isDebugEnabled())
                        log.debug("default beanFactoryReference=" + defaultFactory);
                } else {
                    if (log.isDebugEnabled())
                        log.debug("more then one beanFactory - default not possible to determine");
                    canUseDefaultBeanFactory = false;
                    defaultFactory = null;
                }
            }
        }

        // add aliases
        if (StringUtils.hasText(factoryName)) {
            String[] aliases = beanFactory.getAliases(factoryName);
            names = (String[]) ObjectUtils.addObjectToArray(aliases, factoryName);

            for (String name : names) {
                if (log.isDebugEnabled())
                    log.debug("adding key=" + name + " w/ reference=" + beanFactory);

                if (beanFactories.containsKey(name) && !beanFactory.equals(beanFactories.get(name))
                        || beanFactories.putIfAbsent(name, beanFactory) != null) {
                    throw new IllegalArgumentException(
                            "a beanFactoryReference already exists for key " + factoryName);
                }
            }
        }
    }

    public void destroy() {
        if (names != null) {
            for (String name : names) {
                beanFactories.remove(name);
            }
        }
        if (beanFactory == defaultFactory) {
            synchronized (GemfireBeanFactoryLocator.class) {
                defaultFactory = null;
                canUseDefaultBeanFactory = beanFactories.isEmpty();
            }
        }
    }

    public BeanFactoryReference useBeanFactory(final String factoryKey) throws BeansException {
        // see if there is a default FactoryBean
        BeanFactory factory;

        if (!StringUtils.hasText(factoryKey)) {
            if (!canUseDefaultBeanFactory)
                throw new IllegalArgumentException(
                        "a non-null factoryKey needs to be specified as there are more then one factoryKeys available; "
                                + beanFactories.keySet());
            factory = defaultFactory;
        } else {
            factory = beanFactories.get(factoryKey);
            if (factory == null)
                throw new IllegalArgumentException("there is no beanFactory under key " + factoryKey);
        }

        return new SimpleBeanFactoryReference(factory);
    }

    public void setBeanName(String name) {
        factoryName = name;
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}