com.gzj.tulip.jade.context.spring.JadeBeanFactoryPostProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.gzj.tulip.jade.context.spring.JadeBeanFactoryPostProcessor.java

Source

/*
 * Copyright 2009-2012 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 i 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 com.gzj.tulip.jade.context.spring;

import com.gzj.tulip.jade.dataaccess.DataAccessFactory;
import com.gzj.tulip.jade.dataaccess.DataAccessFactoryAdapter;
import com.gzj.tulip.jade.dataaccess.DataSourceFactory;
import com.gzj.tulip.jade.rowmapper.DefaultRowMapperFactory;
import com.gzj.tulip.jade.rowmapper.RowMapperFactory;
import com.gzj.tulip.jade.statement.Interpreter;
import com.gzj.tulip.jade.statement.InterpreterFactory;
import com.gzj.tulip.jade.statement.StatementWrapperProvider;
import com.gzj.tulip.jade.statement.cached.CacheProvider;
import com.gzj.tulip.load.ResourceRef;
import com.gzj.tulip.load.RoseScanner;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;

import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * {@link JadeBeanFactoryPostProcessor}
 * ??applicationContext-jade.xmlSpring????
 * ?Jade DAO ??SpringBeanSpring
 * <p/>
 * <p/>
 * <h1>==</h1>
 * <p/>
 * <p/>
 * jade?jar? applicationContext-jade.xml
 * ??Springjade???jade
 * ???????
 * <p/>
 * <p/>
 * <strong>jade.context.spring</strong><br>
 * ?(?Jade??)jadespring??<br>
 * jade??DAO?Spring????
 * ??jade
 * <p/>
 * <p/>
 * <strong>jade.context.spring.com.yourcompany.dao.UserDAO</strong><br>
 * ?0101?<br>
 * jadespring????0DAO??Spring?
 * 1DAO?Spring?<br>
 * jade?jade.context.spring.com.yourcompany.dao
 *  jade.context.spring.*Jade
 * <p/>
 * <p/>
 * <strong>jade.context.spring.*</strong><br>
 * ? jade.context.spring.com  jade.context.spring.cn
 *  jade.context.spring.*, ? jade.context.spring<br>
 * jade 1?0
 * ?1package????Spring
 * <p/>
 * <p/>
 * <h1>=DAO?=</h1>
 * <p/>
 * ? {@link RoseScanner#getJarOrClassesFolderResources()}
 * ?classes?rosejar?
 * jarDAO?rose?daoDAO
 * <p/>
 * ??classesjar?jadeDAO?
 * <ul>
 * <li>
 * DAO?package?daodao.UserDAO?myapp.dao.UserDAO?myapp.dao.blog
 * .BlogDAO</li>
 * <li>DAO?DAOUserDAO?BlogDAO</li>
 * <li>DAO?@DAOJade???Class.forName</li>
 * </ul>
 * <p/>
 * ??DAO????? {@link JadeFactoryBean}
 * ?Spring
 * <p/>
 * <h1>=??=</h1>
 * <p/>
 * ?? {@link DataSource} ????jade{@link DataSourceFactory}
 * ?DAO?????spring????
 * <p/>
 * <h2>==?==</h2><br>
 * <ul>
 * <li>spring?id/name  "jade.dataSourceFactory"
 * jadebean?? {@link DataSourceFactory}DAO????</li>
 * <li>springid/name  "jade.dataSourceFactory"???
 * {@link DataSourceFactory}jadebean ??DAO????</li>
 * <li>springid/name  "jade.dataSourceFactory"
 * {@link DataSourceFactory}1??DAO?
 * IllegalStateException ?? {@link SpringDataSourceFactoryDelegate}</li>
 * </ul>
 * <p/>
 * <h2>==?==</h2><br>
 * spring? {@link DataSourceFactory} jade??DAO????
 * {@link SpringDataSourceFactory}
 * DAO????spring??DAO?
 * com.mycompany.myapp.dao.UserDAO, 
 * <p/>
 * <ul>
 * <li>id/namejade.dataSource.com.mycompany.myapp.dao.
 * UserDAO??DAO???????jade.dataSource.com</li>
 * <li>?UserDAO??UserDAO?<code>@DAO</code>
 * catalog??myteam.myappmyteam.myapp?package???</li>
 * <ul>
 * <li>??Spring?jade.dataSource.myteam.myapp.UserDAO...jade.
 * dataSource.myteam</li>
 * </ul>
 * <li>
 * ?UserDAO???id/namejade.dataSource?dataSource??</li>
 * <li>
 * ?UserDAO?????</li>
 * </ul> <br>
 * <p/>
 * <h1>=SQL?=</h1>
 * <p/>
 * DAO??jadeSQL??/SQL????<br>
 * Jade {@link InterpreterFactory} ?DAO?? ?
 * {@link InterpreterFactory}  {@link SpringInterpreterFactory}<br>
 * {@link SpringInterpreterFactory}??Spring {@link Interpreter}
 * {@link Order}??DAO
 *
 * @author  [qieqie.wang@gmail.com]
 * @author  [in355hz@gmail.com]
 */
public class JadeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    private static ResourceBundle bundle;

    static {
        try {
            bundle = ResourceBundle.getBundle("rose");
        } catch (Exception e) {
            //e.printStackTrace();
        }
    }

    /**
     * ??
     */
    private static final String propertyPrefix = "jade.context.spring";

    /**
     * 
     */
    private final Log logger = LogFactory.getLog(JadeBeanFactoryPostProcessor.class);

    /**
     * ?????
     * <p/>
     *
     * @see #getDataAccessFactory(ConfigurableListableBeanFactory)
     */
    private DataAccessFactory dataAccessFactory;

    /**
     * ?????
     * <p/>
     *
     * @see #getRowMapperFactory()
     */
    private RowMapperFactory rowMapperFactory;

    /**
     * ?DAO????DAO?SQL???
     * <p/>
     *
     * @see #getInterpreterFactory(ConfigurableListableBeanFactory)
     */
    private InterpreterFactory interpreterFactory;

    /**
     * StatmentWrapper??bean??none?null
     */
    private String statmentWrapperProviderName;

    /**
     * ??bean??none?null
     */
    private String cacheProviderName;

    // ------------------------------

    public DataAccessFactory getDataAccessFactory(ConfigurableListableBeanFactory beanFactory) {
        if (this.dataAccessFactory == null) {
            dataAccessFactory = new DataAccessFactoryAdapter(//
                    new SpringDataSourceFactoryDelegate(beanFactory));
        }
        return dataAccessFactory;
    }

    public InterpreterFactory getInterpreterFactory(ConfigurableListableBeanFactory beanFactory) {
        if (interpreterFactory == null) {
            interpreterFactory = new SpringInterpreterFactory(beanFactory);
        }
        return interpreterFactory;
    }

    public RowMapperFactory getRowMapperFactory() {
        if (rowMapperFactory == null) {
            rowMapperFactory = new DefaultRowMapperFactory();
        }
        return rowMapperFactory;
    }

    public void setRowMapperFactory(RowMapperFactory rowMapperFactory) {
        this.rowMapperFactory = rowMapperFactory;
    }

    public String getCacheProviderName(ConfigurableListableBeanFactory beanFactory) {
        if (cacheProviderName == null) {
            String[] names = beanFactory.getBeanNamesForType(CacheProvider.class);
            if (names.length == 0) {
                cacheProviderName = "none";
            } else if (names.length == 1) {
                cacheProviderName = names[0];
            } else {
                String topPriority = "jade.cacheProvider";
                if (ArrayUtils.contains(names, topPriority)) {
                    cacheProviderName = topPriority;
                } else {
                    throw new IllegalStateException(
                            "required not more than 1 CacheProvider, but found " + names.length);
                }
            }
        }
        return "none".equals(cacheProviderName) ? null : cacheProviderName;
    }

    public String getStatementWrapperProvider(ConfigurableListableBeanFactory beanFactory) {
        if (statmentWrapperProviderName == null) {
            String[] names = beanFactory.getBeanNamesForType(StatementWrapperProvider.class);
            if (names.length == 0) {
                statmentWrapperProviderName = "none";
            } else if (names.length == 1) {
                statmentWrapperProviderName = names[0];
            } else {
                String topPriority = "jade.statmentWrapperProvider";
                if (ArrayUtils.contains(names, topPriority)) {
                    statmentWrapperProviderName = topPriority;
                } else {
                    throw new IllegalStateException(
                            "required not more than 1 StatmentWrapperProvider, but found " + names.length);
                }
            }
        }
        return "none".equals(statmentWrapperProviderName) ? null : statmentWrapperProviderName;
    }

    // ------------------------------

    /**
     * Spring??? Jade DAO
     * ??SpringBeanSpring
     * <p/>
     * <p/>
     * ?? applicationContext-jade.xml rose?
     * ??????JavaDoc
     * <p/>
     *
     * @see BeanFactoryPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory)
     */
    @Override
    public final void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String springFlag = System.getProperty(propertyPrefix);
        if (bundle != null) {
            try {
                springFlag = bundle.getString(propertyPrefix);
            } catch (Exception e) {
                //e.printStackTrace();
            }
        }

        // ?jade.context.spring jadespring??
        if (springFlag != null && springFlag.length() > 0) {
            logger.info("found " + propertyPrefix + "=" + springFlag);
            return;
        }

        // 
        doPostProcessBeanFactory(beanFactory);
    }

    private void doPostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 
        if (logger.isInfoEnabled()) {
            logger.info("[jade] starting ...");
        }

        // 1??rose?(ResourceRef)?classes?/META-INF/rose.properties/META-INF/MENIFEST.MF?rosejar
        final List<ResourceRef> resources = findRoseResources();

        // 2???(resources)rose=*?rose=DAO?rose=dao?URL?
        List<String> urls = findJadeResources(resources);

        // 3??URL?DAO?JadeFactoryBean?Spring
        findJadeDAODefinitions(beanFactory, urls);

        // ?
        if (logger.isInfoEnabled()) {
            logger.info("[jade] exits");
        }
    }

    /*
     * ?rosejar
     */
    private List<ResourceRef> findRoseResources() {
        final List<ResourceRef> resources;
        try {
            resources = RoseScanner.getInstance().getJarOrClassesFolderResources();
        } catch (IOException e) {
            throw new ApplicationContextException("error on getJarResources/getClassesFolderResources", e);
        }
        return resources;
    }

    /*
     * ?dao?DAOurl
     */
    private List<String> findJadeResources(final List<ResourceRef> resources) {
        List<String> urls = new LinkedList<String>();
        for (ResourceRef ref : resources) {
            if (ref.hasModifier("dao") || ref.hasModifier("DAO")) {
                try {
                    Resource resource = ref.getResource();
                    File resourceFile = resource.getFile();
                    if (resourceFile.isFile()) {
                        urls.add("jar:file:" + resourceFile.toURI().getPath() + ResourceUtils.JAR_URL_SEPARATOR);
                    } else if (resourceFile.isDirectory()) {
                        urls.add(resourceFile.toURI().toString());
                    }
                } catch (IOException e) {
                    throw new ApplicationContextException("error on resource.getFile", e);
                }
            }
        }
        if (logger.isInfoEnabled()) {
            logger.info("[jade] found " + urls.size() + " jade urls: " + urls);
        }
        return urls;
    }

    /*
     * jar?DAO?Spring
     */
    private void findJadeDAODefinitions(ConfigurableListableBeanFactory beanFactory, List<String> urls) {
        JadeComponentProvider provider = new JadeComponentProvider();
        Set<String> daoClassNames = new HashSet<String>();

        for (String url : urls) {
            if (logger.isInfoEnabled()) {
                logger.info("[jade] call 'jade/find'");
            }

            Set<BeanDefinition> dfs = provider.findCandidateComponents(url);
            if (logger.isInfoEnabled()) {
                logger.info("[jade] found " + dfs.size() + " beanDefinition from '" + url + "'");
            }

            for (BeanDefinition beanDefinition : dfs) {
                String daoClassName = beanDefinition.getBeanClassName();
                if (getDisableFlag(daoClassName)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("[jade] ignored disabled jade dao class: " + daoClassName + "  [" + url + "]");
                    }
                    continue;
                }
                if (daoClassNames.contains(daoClassName)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(
                                "[jade] ignored replicated jade dao class: " + daoClassName + "  [" + url + "]");
                    }
                    continue;
                }
                daoClassNames.add(daoClassName);

                registerDAODefinition(beanFactory, beanDefinition);
            }
        }
    }

    /*
     * DAO?Spring
     */
    private void registerDAODefinition(ConfigurableListableBeanFactory beanFactory, BeanDefinition beanDefinition) {
        final String daoClassName = beanDefinition.getBeanClassName();
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
        /*
         * ?? JadeFactoryBean ??
         */
        propertyValues.addPropertyValue("objectType", daoClassName);
        propertyValues.addPropertyValue("dataAccessFactory", getDataAccessFactory(beanFactory));
        propertyValues.addPropertyValue("rowMapperFactory", getRowMapperFactory());
        propertyValues.addPropertyValue("interpreterFactory", getInterpreterFactory(beanFactory));
        String cacheProviderName = getCacheProviderName(beanFactory);
        if (cacheProviderName != null) {
            RuntimeBeanReference beanRef = new RuntimeBeanReference(cacheProviderName);
            propertyValues.addPropertyValue("cacheProvider", beanRef);
        }
        String statementWrapperProvider = getStatementWrapperProvider(beanFactory);
        if (statementWrapperProvider != null) {
            RuntimeBeanReference beanRef = new RuntimeBeanReference(statementWrapperProvider);
            propertyValues.addPropertyValue("statementWrapperProvider", beanRef);
        }
        ScannedGenericBeanDefinition scannedBeanDefinition = (ScannedGenericBeanDefinition) beanDefinition;
        scannedBeanDefinition.setPropertyValues(propertyValues);
        scannedBeanDefinition.setBeanClass(JadeFactoryBean.class);

        DefaultListableBeanFactory defaultBeanFactory = (DefaultListableBeanFactory) beanFactory;
        defaultBeanFactory.registerBeanDefinition(daoClassName, beanDefinition);

        if (logger.isDebugEnabled()) {
            logger.debug("[jade] register DAO: " + daoClassName);
        }
    }

    /*
     * ?dao
     */
    protected boolean getDisableFlag(String daoType) {
        String name = daoType;
        while (true) {
            String flag;
            if (name.length() == 0) {
                flag = System.getProperty(propertyPrefix + ".*");
                if (bundle != null) {
                    try {
                        flag = bundle.getString(propertyPrefix + ".*");
                    } catch (Exception e) {
                        //e.printStackTrace();
                    }
                }
            } else {
                flag = System.getProperty(propertyPrefix + "." + name);
                if (bundle != null) {
                    try {
                        flag = bundle.getString(propertyPrefix + "." + name);
                    } catch (Exception e) {
                        //e.printStackTrace();
                    }
                }
            }
            if (flag == null) {
                int index = name.lastIndexOf('.');
                if (index == -1) {
                    if (name.length() == 0) {
                        return false;
                    } else {
                        name = "";
                    }
                } else {
                    name = name.substring(0, index);
                }
                continue;
            }
            if ("0".equals(flag)) {
                return true;
            } else if (flag == null || "1".equals(flag)) {
                return false;
            } else {
                if (name.length() == 0) {
                    name = "*";
                }
                throw new IllegalArgumentException(
                        "illegal value of property: " + propertyPrefix + "." + name + "='" + flag + "'");
            }
        }
    }
}