org.guzz.GuzzContextImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.guzz.GuzzContextImpl.java

Source

/*
 * Copyright 2008-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 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.guzz;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.guzz.builder.GuzzConfigFileBuilder;
import org.guzz.builder.HbmXMLBuilder;
import org.guzz.bytecode.CglibProxyFactory;
import org.guzz.bytecode.ProxyFactory;
import org.guzz.config.ConfigServer;
import org.guzz.connection.DBGroup;
import org.guzz.connection.DBGroupManager;
import org.guzz.connection.PhysicsDBGroup;
import org.guzz.connection.VirtualDBView;
import org.guzz.dialect.Dialect;
import org.guzz.exception.DaoException;
import org.guzz.exception.GuzzException;
import org.guzz.exception.InvalidConfigurationException;
import org.guzz.io.FileResource;
import org.guzz.io.Resource;
import org.guzz.orm.Business;
import org.guzz.orm.BusinessInterpreter;
import org.guzz.orm.ColumnDataLoader;
import org.guzz.orm.ObjectMapping;
import org.guzz.orm.ShadowTableView;
import org.guzz.orm.interpreter.BusinessInterpreterManager;
import org.guzz.orm.mapping.ObjectMappingManager;
import org.guzz.orm.mapping.POJOBasedObjectMapping;
import org.guzz.orm.sql.CompiledSQL;
import org.guzz.orm.sql.CompiledSQLBuilder;
import org.guzz.orm.sql.CompiledSQLManager;
import org.guzz.orm.sql.impl.CompiledSQLBuilderImpl;
import org.guzz.orm.sql.impl.CompiledSQLManagerImpl;
import org.guzz.service.ServiceConfig;
import org.guzz.service.ServiceInfo;
import org.guzz.service.ServiceManager;
import org.guzz.service.core.DatabaseService;
import org.guzz.service.core.DebugService;
import org.guzz.service.core.DynamicSQLService;
import org.guzz.service.core.impl.DebugServiceImpl;
import org.guzz.service.core.impl.DebugServiceProxy;
import org.guzz.service.core.impl.DynamicSQLServiceProxy;
import org.guzz.service.core.impl.MultiMachinesDatabaseServiceImpl;
import org.guzz.service.core.impl.SingleMachineDatabaseServiceImpl;
import org.guzz.service.core.impl.SlowUpdateServiceImpl;
import org.guzz.service.core.impl.SlowUpdateServiceProxy;
import org.guzz.service.core.impl.TemplatedSQLServiceProxy;
import org.guzz.service.impl.ServiceManagerFactory;
import org.guzz.service.impl.ServiceManagerImpl;
import org.guzz.transaction.DefaultTranSessionLocatorImpl;
import org.guzz.transaction.TranSessionLocator;
import org.guzz.transaction.TransactionManager;
import org.guzz.transaction.TransactionManagerFactory;
import org.guzz.util.CloseUtil;
import org.guzz.util.StringUtil;
import org.guzz.web.context.ExtendedBeanFactory;
import org.guzz.web.context.ExtendedBeanFactoryAware;
import org.guzz.web.context.GuzzContextAware;

/**
 * 
 * 
 *
 * @author liukaixuan(liukaixuan@gmail.com)
 */
public class GuzzContextImpl implements GuzzContext {

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

    private Map dialects;

    private DBGroupManager dbGroupManager = null;

    private List contextLifeCycles = new LinkedList();

    /**waiting for GuzzContext's full inited.*/
    private List contextLifeCyclesWaitingStart = new LinkedList();

    ObjectMappingManager objectMappingManager;

    CompiledSQLBuilder compiledSQLBuilder;

    CompiledSQLManagerImpl compiledSQLManager;

    BusinessInterpreterManager businessInterpreterManager;

    ConfigServer configServer;

    TransactionManager transactionManager;

    ServiceManager serviceManager;

    DebugService debugService;

    DynamicSQLService dynamicSQLService;

    ProxyFactory proxyFactory;

    ExtendedBeanFactory extendedBeanFactory;

    Map globalIdGenerators = new HashMap();

    private List contextAwareListeners = new LinkedList();

    private List extendBeanFactoryAwareListeners = new LinkedList();

    private boolean fullStarted;

    protected GuzzContextImpl() {
    }

    /**
     * ??
     * @throws Exception 
     */
    protected void initFromMainConfig(Resource config) throws Exception {
        //??xml?ConfigServer???Service??

        //TODO: read this from config file.
        this.proxyFactory = new CglibProxyFactory();
        objectMappingManager = new ObjectMappingManager();
        businessInterpreterManager = new BusinessInterpreterManager(this);
        dbGroupManager = new DBGroupManager();

        //?proxied TemplatedSQLService
        TemplatedSQLServiceProxy templatedSQLService = new TemplatedSQLServiceProxy();
        compiledSQLBuilder = new CompiledSQLBuilderImpl(this, objectMappingManager, templatedSQLService);
        compiledSQLManager = new CompiledSQLManagerImpl(compiledSQLBuilder);

        GuzzConfigFileBuilder builder = GuzzConfigFileBuilder.build(this, config, "UTF-8");
        if (log.isInfoEnabled()) {
            log.info("Loading guzz config file:" + config);
        }

        //1. dialect??
        Map ds = builder.getConfiguredDialect();
        if (ds == null) {
            log.warn("dialect(s) not found.");
        } else {
            this.dialects = ds;
        }

        //2. config-server???.
        //????
        if (log.isInfoEnabled()) {
            log.info("Contacting Config Server....");
        }

        configServer = builder.loadConfigServer();
        if (configServer == null) {
            throw new GuzzException("config-server is not available.");
        }

        //Service
        this.debugService = new DebugServiceProxy(
                (DebugService) ServiceManagerImpl.createNewService(this, configServer,
                        new ServiceInfo(Service.FAMOUSE_SERVICE.GUZZ_DEBUG, "guzzDebug", DebugServiceImpl.class)));

        //2. ?
        List groups = builder.listDBGroups();
        if (groups == null) {
            log.warn("no dbgroup found.");
        } else {
            for (int i = 0; i < groups.size(); i++) {
                DBGroup m_group = (DBGroup) groups.get(i);

                this.dbGroupManager.put(m_group.getGroupName(), m_group);
            }
        }

        //2. ORM
        List globalORMs = builder.listGlobalORMs();
        for (int i = 0; i < globalORMs.size(); i++) {
            this.objectMappingManager.registerObjectMapping((ObjectMapping) globalORMs.get(i));
        }

        //3. ghost business object
        //3.1 annotated business
        if (builder.hasAnnotatedBusiness()) {
            builder.buildGlobalIdGenerators(globalIdGenerators);

            List aghosts = builder.listAnnotatedBusinessObjectMappings();
            for (int i = 0; i < aghosts.size(); i++) {
                addNewGhostBusinessToSystem((POJOBasedObjectMapping) aghosts.get(i));
            }
        }
        //3.2 hbm.xmlbusiness
        List ghosts = builder.listBusinessObjectMappings();
        for (int i = 0; i < ghosts.size(); i++) {
            addNewGhostBusinessToSystem((POJOBasedObjectMapping) ghosts.get(i));
        }
        //3.3 package-scanbusinessbusiness??
        builder.loadScanedBusinessesToGuzz();

        //4. ?sql?
        Map predefinedSQLs = builder.listConfiguedCompiledSQLs(templatedSQLService);
        Iterator entries = predefinedSQLs.entrySet().iterator();

        while (entries.hasNext()) {
            Entry entry = (Entry) entries.next();
            String key = (String) entry.getKey();
            CompiledSQL cs = (CompiledSQL) entry.getValue();

            this.compiledSQLManager.addCompliedSQL(key, cs);
        }

        //6. Service?
        if (log.isInfoEnabled()) {
            log.info("Loading Services....");
        }

        serviceManager = ServiceManagerFactory.buildServiceManager(this);
        //??Service

        serviceManager.registerService((Service) debugService);

        this.dynamicSQLService = (DynamicSQLService) ServiceManagerImpl.createNewService(this, configServer,
                new ServiceInfo(Service.FAMOUSE_SERVICE.DYNAMIC_SQL, "guzzDynamicSQL",
                        DynamicSQLServiceProxy.class));
        compiledSQLManager.setDynamicSQLService(dynamicSQLService);
        serviceManager.registerService((Service) dynamicSQLService);
        serviceManager.registerService(templatedSQLService);

        //7. ?
        if (log.isInfoEnabled()) {
            log.info("Prepare transactions....");
        }

        Class locatorCls = builder.getTranLocator();
        TranSessionLocator tranSessionLocator = null;
        if (locatorCls != null) {
            tranSessionLocator = (TranSessionLocator) locatorCls.newInstance();
        } else {
            tranSessionLocator = new DefaultTranSessionLocatorImpl();
        }

        this.registerContextLifeCycle(tranSessionLocator);

        transactionManager = TransactionManagerFactory.buildTransactionFactory(objectMappingManager,
                compiledSQLManager, compiledSQLBuilder, this.debugService, dbGroupManager, tranSessionLocator);

        Service sus = new SlowUpdateServiceProxy(
                (SlowUpdateServiceImpl) ServiceManagerImpl.createNewService(this, configServer, new ServiceInfo(
                        Service.FAMOUSE_SERVICE.SLOW_UPDATE, "guzzSlowUpdate", SlowUpdateServiceImpl.class)));

        serviceManager.registerService(sus);

        //Service
        Map services = builder.loadServices();
        LinkedList queuedServices = new LinkedList();
        while (!services.isEmpty()) {
            Iterator i = services.entrySet().iterator();
            Entry e = (Entry) i.next();
            i.remove();

            //String serviceName = (String) e.getKey() ;
            ServiceInfo serviceInfo = (ServiceInfo) e.getValue();

            initUnOrderedService(services, queuedServices, serviceInfo);
        }

        //One Service could be depend on others. So we have to compute the dependencies, and start the services in the correct order.
        for (int i = 0; i < services.size(); i++) {
            ServiceInfo info = (ServiceInfo) services.get(Integer.valueOf(i));
            Service s = ServiceManagerImpl.createNewService(this, configServer, info);
            serviceManager.registerService(s);
        }

        //8. ??
        fullStarted = true;

        //9. guzz???
        for (int i = 0; i < contextAwareListeners.size(); i++) {
            GuzzContextAware aware = (GuzzContextAware) contextAwareListeners.get(i);
            aware.setGuzzContext(this);
        }

        //10. ?(startup)
        for (int i = 0; i < this.contextLifeCyclesWaitingStart.size(); i++) {
            ContextLifeCycle c = (ContextLifeCycle) this.contextLifeCyclesWaitingStart.get(i);

            c.startup();
        }
        this.contextLifeCyclesWaitingStart.clear();
    }

    protected void initUnOrderedService(Map services, LinkedList queuedServices, ServiceInfo serviceInfo) {
        if (serviceInfo.hasDependedServices()) {
            queuedServices.addLast(serviceInfo);

            String[] dependsOn = serviceInfo.getDependedServices();

            for (int k = 0; k < dependsOn.length; k++) {
                for (int i = 0; i < queuedServices.size(); i++) {
                    String queueServiceName = ((ServiceInfo) queuedServices.get(i)).getServiceName();

                    if (queueServiceName.equals(dependsOn[k])) {
                        throw new InvalidConfigurationException("cycle dependencies found in guzz services. From ["
                                + queueServiceName + "] to [" + dependsOn[k] + "].");
                    }
                }

                //add depended-services from un-inited-services to the queuedServices
                ServiceInfo si = (ServiceInfo) services.remove(dependsOn[k]);
                if (si != null) {
                    //process the depended service first.
                    initUnOrderedService(services, queuedServices, si);
                } else {
                    //the service may have already been registered to the ServiceManager
                }
            }

            //Depended services have been inited. Start the current one.
            Service s = ServiceManagerImpl.createNewService(this, configServer, serviceInfo);
            serviceManager.registerService(s);

            queuedServices.remove(serviceInfo);
        } else {
            Service s = ServiceManagerImpl.createNewService(this, configServer, serviceInfo);
            serviceManager.registerService(s);
        }
    }

    public void setExtendedBeanFactory(ExtendedBeanFactory extendedBeanFactory) {
        this.extendedBeanFactory = extendedBeanFactory;

        for (int i = 0; i < extendBeanFactoryAwareListeners.size(); i++) {
            ExtendedBeanFactoryAware a = (ExtendedBeanFactoryAware) extendBeanFactoryAwareListeners.get(i);
            a.setExtendedBeanFactory(extendedBeanFactory);
        }

        this.extendBeanFactoryAwareListeners.clear();
    }

    /**
     * ?DatabaseService??
     * @param serviceName ???
     * @return ???dubug?null?{@link GuzzException}
     */
    public DatabaseService getOrCreateDataService(String serviceName) throws GuzzException {
        try {
            ServiceConfig[] scs = this.configServer.queryConfig(serviceName);

            if (scs == null || scs.length == 0) {
                if (this.debugService.isDebugMode()) {
                    return null;
                } else {
                    throw new GuzzException("cann't find database service:[" + serviceName + "].");
                }
            } else if (scs.length == 1) {
                SingleMachineDatabaseServiceImpl ds = new SingleMachineDatabaseServiceImpl();
                ds.setServiceInfo(
                        new ServiceInfo(serviceName, serviceName, SingleMachineDatabaseServiceImpl.class));
                ds.configure(scs[0]);
                ds.startup();

                return ds;
            } else {
                MultiMachinesDatabaseServiceImpl ds = new MultiMachinesDatabaseServiceImpl();
                ds.setServiceInfo(
                        new ServiceInfo(serviceName, serviceName, MultiMachinesDatabaseServiceImpl.class));
                ds.configure(scs);
                ds.startup();

                return ds;
            }
        } catch (IOException e) {
            throw new GuzzException(e);
        }
    }

    private Map ghosts = new HashMap();

    /**?ghost?????Ghost?null*/
    public Business getBusiness(String name) {
        return (Business) ghosts.get(name);
    }

    public void addNewGhostBusinessToSystem(POJOBasedObjectMapping map) {
        Business b = map.getBusiness();

        //?
        if (ghosts.get(b.getName()) != null) {
            throw new GuzzException("business [" + b.getName() + "] already exsits.");
        }

        objectMappingManager.registerObjectMapping(map);
        this.compiledSQLManager.addDomainBusiness(map);

        ghosts.put(b.getDomainClass().getName(), b);
        if (b.getName() != null) {
            ghosts.put(b.getName(), b);
        }
    }

    public void registerVirtualDBView(VirtualDBView view) {
        registerContextLifeCycle(view);
    }

    public void registerColumnDataLoader(ColumnDataLoader loader) {
        registerContextLifeCycle(loader);
    }

    public void registerShadowTableView(ShadowTableView view) {
        registerContextLifeCycle(view);
    }

    public void registerContextLifeCycle(ContextLifeCycle c) {
        this.contextLifeCycles.add(c);

        if (c instanceof GuzzContextAware) {
            this.registerContextStartedAware((GuzzContextAware) c);
        }

        if (this.isFullStarted()) {
            c.startup();
        } else {
            this.contextLifeCyclesWaitingStart.add(c);
        }

        if (c instanceof ExtendedBeanFactoryAware) {
            this.registerExtendedBeanFactoryAware((ExtendedBeanFactoryAware) c);
        }
    }

    public void shutdown() {
        for (int i = 0; i < this.contextLifeCycles.size(); i++) {
            ContextLifeCycle c = (ContextLifeCycle) this.contextLifeCycles.get(i);

            try {
                c.shutdown();
            } catch (Exception e) {
                log.error("error while shutting down :" + c.getClass(), e);
            }
        }
        this.contextLifeCycles.clear();

        if (serviceManager != null) {
            serviceManager.shutdown();
        }

        if (this.dbGroupManager != null) {
            this.dbGroupManager.shutdown();
        }

        this.businessInterpreterManager.shutdown();

        if (this.configServer != null) {
            this.configServer.shutdown();
        }

        this.globalIdGenerators.clear();

        if (log.isInfoEnabled()) {
            log.info("Guzz closed.");
        }
    }

    /**hbm? @param resource ?
     * @throws Exception */
    public void addHbmConfig(Business business, Resource resource) throws Exception {
        POJOBasedObjectMapping map = HbmXMLBuilder.parseHbmStream(this, business.getDbGroup(), null,
                business.getName(), business.getDomainClass(), null, resource.getInputStream());

        BusinessInterpreter bi = business.getInterpret();

        if (bi != null) {
            map.getBusiness().setInterpret(bi);
        }

        addNewGhostBusinessToSystem(map);
    }

    /**hbm
     * @param fileName ??
     */
    public void addHbmConfigFile(Business business, String fileName) throws Exception {
        Resource r = new FileResource(fileName);
        try {
            addHbmConfig(business, r);
        } finally {
            CloseUtil.close(r);
        }
    }

    public Business instanceNewGhost(String ghostName, String dbGroup, Class intepretClass, Class domainClass)
            throws ClassNotFoundException {
        if (StringUtil.isEmpty(ghostName)) {
            throw new GuzzException("business name cann't be empty.");
        }

        BusinessInterpreter ii = businessInterpreterManager.newInterpreter(ghostName, intepretClass, domainClass);

        Business business = new Business(ghostName, dbGroup);
        business.setInterpret(ii); //ii?domainClassnullnull
        if (domainClass != null) {
            business.setDomainClass(domainClass);
        }

        return business;
    }

    public DBGroup getDBGroup(String groupName) throws DaoException {
        DBGroup g = this.dbGroupManager.getGroup(groupName);

        return g;
    }

    public PhysicsDBGroup getPhysicsDBGroup(String groupName) throws DaoException {
        return this.dbGroupManager.getPhysicsDBGroup(groupName);
    }

    public Service getService(String serviceName) {
        return this.serviceManager.getService(serviceName);
    }

    public DebugService getDebugService() {
        return (DebugService) this.serviceManager.getService(Service.FAMOUSE_SERVICE.GUZZ_DEBUG);
    }

    public Dialect getDialect(String name) {
        return (Dialect) dialects.get(name);
    }

    public ObjectMappingManager getObjectMappingManager() {
        return objectMappingManager;
    }

    public BusinessInterpreterManager getGhostInterpreterManager() {
        return businessInterpreterManager;
    }

    public TransactionManager getTransactionManager() {
        return transactionManager;
    }

    public ConfigServer getConfigServer() {
        return configServer;
    }

    public ServiceManager getServiceManager() {
        return serviceManager;
    }

    public CompiledSQLBuilder getCompiledSQLBuilder() {
        return compiledSQLBuilder;
    }

    public CompiledSQLManager getCompiledSQLManager() {
        return compiledSQLManager;
    }

    public boolean isFullStarted() {
        return fullStarted;
    }

    public ProxyFactory getProxyFactory() {
        return proxyFactory;
    }

    /**
     * Get the global declared Id Generator (from the annotation).
     */
    public Object getGlobalIdGenerator(String name) {
        return globalIdGenerators.get(name);
    }

    public ExtendedBeanFactory getExtendedBeanFactory() {
        return extendedBeanFactory;
    }

    public Object getExtendedBean(String beanName) {
        if (this.extendedBeanFactory == null) {
            throw new GuzzException("ExtendedBeanFactory is not inited yet. forgot to config it?");
        }

        return extendedBeanFactory.getBean(beanName);
    }

    /**
     * Add a callback on guzz's full started.
     */
    public void registerContextStartedAware(GuzzContextAware aware) {
        if (this.fullStarted) {
            aware.setGuzzContext(this);
        } else {
            this.contextAwareListeners.add(aware);
        }
    }

    /**
     * Add a callback on guzz's {@link ExtendedBeanFactory} setted.
     */
    public void registerExtendedBeanFactoryAware(ExtendedBeanFactoryAware aware) {
        if (this.extendedBeanFactory != null) {
            aware.setExtendedBeanFactory(extendedBeanFactory);
        } else {
            this.extendBeanFactoryAwareListeners.add(aware);
        }
    }

}