package com.bj58.argo;
import com.bj58.argo.convention.GroupConvention;
import com.bj58.argo.inject.ArgoModule;
import com.bj58.argo.logs.Logger;
import com.bj58.argo.logs.LoggerFactory;
import com.bj58.argo.servlet.ArgoDispatcher;
import com.bj58.argo.utils.OnlyOnceCondition;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
/**
* Argo是整个项目的上帝,是整个项目的根对象(root)
*
* 负责环境的管理和各个对象的创建,从Argo可以抵达项目的每个对象
*
* @author renjun
*/
public class Argo {
public static final Argo instance = new Argo();
private Injector injector;
private ServletContext servletContext;
private GroupConvention groupConvention;
private Set<Class<? extends ArgoController>> controllerClasses;
private File currentFolder;
private LoggerFactory loggerFactory;
private Logger logger;
private final OnlyOnceCondition onlyOnce = OnlyOnceCondition
.create("Argo has been initialized.");
private Argo() {
}
public ArgoDispatcher init(ServletContext servletContext, GroupConvention groupConvention) {
onlyOnce.check();
servletContext.log("initializing Argo...");
this.servletContext = servletContext;
this.groupConvention = groupConvention;
this.controllerClasses = groupConvention.currentProject().controllerClasses();
this.currentFolder = innerCurrentFolder();
List<Module> modules = Lists.newArrayList();
modules.add(new ArgoModule(this));
Module groupModule = groupConvention.group().module();
if (null != groupModule)
modules.add(groupModule);
Module projectModule = groupConvention.currentProject().module();
if (null != projectModule)
modules.add(projectModule);
servletContext.log("preparing an injector");
this.injector = buildInjector(modules);
servletContext.log("injector completed");
this.loggerFactory = getInstance(LoggerFactory.class);
this.logger = getLogger("ARGO");
logger.info("preparing an argo dispatcher");
this.argoDispatcher = getInstance(ArgoDispatcher.class);
logger.info("the argo dispatcher completed");
logger.info("argo initialized");
return argoDispatcher;
}
private Injector buildInjector(List<Module> modules) {
return Guice.createInjector(modules);
}
/**
* Returns the appropriate instance for the given injection type.
*
* @param type the given injection type
* @return the appropriate instance
*/
public <T> T getInstance(Class<T> type) {
return injector().getInstance(type);
}
/**
* Injects dependencies into the fields and methods of {@code instance}.
* Ignores the presence of absence of an injectable constructor.
*
* @param instance to inject members on
*/
public <T> T injectMembers(T instance) {
injector().injectMembers(instance);
return instance;
}
/**
* an injector singleton instance.
*
* @return 注入器
*/
public Injector injector() {
return injector;
}
/**
* 公用线程池
*
* @return 公用线程池
*/
public Executor commonExecutor() {
return getInstance(Executor.class);
}
/**
* 项目的ServletContext
*
* @return 项目的ServletContext
*/
public ServletContext servletContext() {
return this.servletContext;
}
private volatile ArgoDispatcher argoDispatcher;
/**
* Servlet的适配器,负责url转发
*
* @return ArgoDispatcher
*/
public ArgoDispatcher argoDispatcher() {
return argoDispatcher;
}
/**
* 当前的Request
*
* @return 当前的Request
*/
public HttpServletRequest currentRequest() {
return argoDispatcher().currentRequest();
}
public HttpServletResponse currentResponse() {
return argoDispatcher().currentResponse();
}
/**
* 当前请求的上下文
*
* @return 当前请求的上下文
*/
public BeatContext beatContext() {
return argoDispatcher().currentBeatContext();
}
/**
* 组织级策略
*
* @return 组织级策略
*/
public GroupConvention groupConvention() {
return this.groupConvention;
}
/**
* 项目所管理的所有Controller类集合
*
* @return 所有Controller类集合
*/
public Set<Class<? extends ArgoController>> getControllerClasses() {
return controllerClasses;
}
/**
* 根据名字获得logger
*
* @param name 需要获得的logger名字
* @return 对应名字的logger
*/
public Logger getLogger(String name) {
return loggerFactory.getLogger(name);
}
/**
* 根据类获得logger
* @param clazz 类
* @return logger
*/
public Logger getLogger(Class<?> clazz) {
return loggerFactory.getLogger(clazz);
}
public Logger getLogger() {
return this.logger;
}
/**
* Classloader所在文件夹
* @return 启动文件夹 classloader
*/
public File currentFolder() {
return currentFolder;
}
private File innerCurrentFolder() {
// System.out.println("Current Folder: " + getClass().getResource("/").getFile());
return new File(getClass().getResource("/").getFile());
}
}