All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.yoojia.halo.HaloEngine Maven / Gradle / Ivy

There is a newer version: 1.1.2
Show newest version
package com.github.yoojia.halo;

import com.github.yoojia.halo.actions.HaloAction;
import com.github.yoojia.halo.interceptors.HaloInterceptor;
import com.github.yoojia.halo.supports.*;
import com.github.yoojia.halo.utils.Classes;
import com.github.yoojia.halo.utils.Scanner;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * @author YOOJIA.CHEN ([email protected])
 */
public final class HaloEngine {

    private final Logger mLogger = LoggerFactory.getLogger(HaloEngine.class);

    private final static ThreadLocal INSTANCE_FLAG = new ThreadLocal<>();

    private Context mContext;

    private final KernelChain mBridgeChain = new KernelChain();
    private final List mKernelModules = Lists.newArrayList();
    private final List mUserPlugins = Lists.newArrayList();
    private final List mUserListeners = Lists.newArrayList();
    private final List mCoreListeners = Lists.newArrayList();

    private final Ordering mPriorityOrdering = Ordering.from(new Comparator() {
        @Override
        public int compare(Config.Wrapper w1, Config.Wrapper w2) {
            return w1.priority > w2.priority ? 1 : -1;
            }
    });

    /**
     * 根据指定WebRoot路径来初始化 Engine 运行环境
     */
    public void init(String webRoot){
        mLogger.debug("[email protected]: {}", Thread.currentThread().getId());
        mLogger.debug("Web root: {}", webRoot);
        if(INSTANCE_FLAG.get() != null){
            mLogger.warn("\n\n==== ANOTHER HALOEngine INSTANCE IS RUNNING ===\n");
        }
        INSTANCE_FLAG.set(true);
        final Scanner scanner = new Scanner();
        mContext = new Context(scanner, webRoot);
        engineInit();
    }

    /**
     * 启动Engine,加载核心模块、插件及监听接口
     */
    public void startup(){
        mLogger.debug("start...");
        for (CoreLifecycle item : mCoreListeners){
            item.onStartup(mContext);
        }
    }

    /**
     * 关闭Engine实例,关闭核心模块、插件及监听接口
     */
    public void shutdown(){
        mLogger.debug("stop...");
        for (CoreLifecycle item : mCoreListeners){
            item.onShutdown(mContext);
        }
    }

    /**
     * 处理请求入口方法
     */
    public void service(ServletRequest request, ServletResponse response) {
        final HaloRequest haloRequest = new HaloRequest(request);
        final HaloResponse haloResponse = new HaloResponse(response);
        mLogger.trace("Dispatching request :::: Method={}, Uri={}", haloRequest.method, haloRequest.uri);
        try{
            mBridgeChain.startService(haloRequest, haloResponse);
        }catch (Exception error){
            haloResponse.sendError(error);
        }
    }

    private void engineInit(){
        final Scanner scanner = mContext.getClassScanner();
        scanner.start();
        final Classes classes = new Classes();
        // 1. Kernel modules
        final Config rootConfig = mContext.getRootConfig();
        final List> tempKernel = Lists.newArrayList();
        tempKernel.add(new Config.Wrapper(-99, new HaloInterceptor(), rootConfig));
        tempKernel.add(new Config.Wrapper(0, new HaloAction(), rootConfig));
        prepareKernelModules(classes, tempKernel);
        for(Config.Wrapper c : mPriorityOrdering.sortedCopy(tempKernel)) {
            final HaloModule module = c.target;
            module.init(mContext, c.args == null ? rootConfig : c.args);
            mKernelModules.add(module);
            mBridgeChain.addService(module);
        }
        mCoreListeners.addAll(mKernelModules);
        // 2. User plugins
        prepareUserPlugins(classes, mUserPlugins);
        mCoreListeners.addAll(mUserPlugins);
        // 3. User listeners
        prepareUserListeners(classes, mUserListeners);
        mCoreListeners.addAll(mUserListeners);
        // clear scanner cache
        scanner.clean();
    }

    private void prepareKernelModules(Classes util, List> tempList) {
        final List configs = mContext.getRootConfig().getConfigList("appModules");
        for (Config c : configs) {
            final String className = c.getString("class");
            final HaloModule module = util.newClassByName(className);
            final int priority = c.getIntValue("priority", 0);
            final Config args = c.getSection("args");
            mLogger.trace("Prepare APP module, Class={}, Priority={}, Args={}", className, priority, args);
            tempList.add(new Config.Wrapper<>(priority, module, args));
        }
    }

    private void prepareUserPlugins(Classes util, List plugins) {
        final List configs = mContext.getRootConfig().getConfigList("appPlugins");
        final ArrayList> wrappers = Lists.newArrayList();
        for (Config c : configs) {
            final String className = c.getString("class");
            final HaloPlugin listener = util.newClassByName(className);
            final int priority = c.getIntValue("priority", 0);
            final Config args = c.getSection("args");
            mLogger.trace("Prepare APP plugin, Class={}, Priority={}, Args={}", className, priority, args);
            wrappers.add(new Config.Wrapper<>(priority, listener, args));
        }
        // 排序Plugin数组,优先级大的排在后面
        for(Config.Wrapper w : mPriorityOrdering.sortedCopy(wrappers)){
            w.target.init(mContext, w.args);
            plugins.add(w.target);
        }
    }

    private void prepareUserListeners(Classes util, List listeners){
        final List configs = mContext.getRootConfig().getConfigList("appListeners");
        final ArrayList> wrappers = Lists.newArrayList();
        for (Config c : configs) {
            final String className = c.getString("class");
            final HaloListener listener = util.newClassByName(className);
            final int priority = c.getIntValue("priority", 0);
            mLogger.trace("Prepare APP listener, Class={}, Priority={}", className, priority);
            wrappers.add(new Config.Wrapper<>(priority, listener, null));
        }
        // 排序Listener数组,优先级大的排在后面
        for(Config.Wrapper w : mPriorityOrdering.sortedCopy(wrappers)){
            listeners.add(w.target);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy