/*
Copyright (c) putdb.com, all rights reserved.
Contact: contact@putdb.com
Visit: http://www.ag6666666
 */
package com.wb.common;

import com.wb.tool.TaskManager;
import com.wb.util.FileUtil;
import com.wb.util.StringUtil;
import com.wb.util.SysUtil;
import com.wb.util.WebUtil;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebBuilder基本过滤器，拦截所有的请求路径。任何对应用发起的请求都会触发doFilter方法。
 * <p>
 * 主要作用有：
 * 初始化系统，完成对静态变量的设置和计划任务的加载。
 * 对XWL模块的访问处理，解析对模块文件的访问。
 * 缓存wb目录下的资源，缓存文件内容至内存并根据需要启用gzip压缩，以提高响应性能。
 * 禁止对系统目录的访问，禁止从外部对wb/system进行访问。
 * </p>
 * 
 * @author Jie Chen
 * @version 7
 * @see com.wb.common.FileBuffer
 * @see com.wb.common.Parser
 */
public class Base implements Filter {
	/** Servlet上下文对象。 */
	public static ServletContext servletContext;
	/** 应用目录的根路径。 */
	public static File path;
	/** 应用目录的根路径长度。 */
	public static int pathLen;
	/** 模块文件的根路径。 */
	public static File modulePath;
	/** 模块目录路径文本。 */
	public static String modulePathText;
	/** 模块目录路径长度。 */
	public static int modulePathLen;
	/** 系统的启动时间。 */
	public static Date startTime;
	/** 提供静态ConcurrentHashMap，该对象可为任何应用使用。 */
	public static ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();
	/** 是否初始化失败。 */
	private static boolean initFailed;
	/** 初始化失败异常对象。 */
	private static Throwable initError;

	/**
	 * WebBuilder过滤器，实现对xwl文件的执行，文件的缓存和系统文件的保护功能。
	 * 
	 * @param request ServletRequest 请求对象。
	 * @param response ServletResponse 响应对象。
	 * @param chain 过滤器链。
	 * @throws ServletException 如果执行过程中发生异常将抛出。
	 */
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		if (initFailed)
			throw new RuntimeException(initError);
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		String url, xwl;



		url = req.getServletPath();

		xwl = UrlBuffer.get(url);
		if (xwl != null) {
			// WebBuilder模块
			request.setCharacterEncoding("utf-8");
			if (xwl.isEmpty()) {
				xwl = request.getParameter("xwl");
				if (xwl == null) {
					resp.sendError(HttpServletResponse.SC_BAD_REQUEST,
							"null xwl");
					return;
				}
				xwl = StringUtil.concat(xwl, ".xwl");
			}
			
			setRequest(req);
			com.wb.common.Parser parser = new Parser(req, resp);
			parser.parse(xwl);
		} else {
			String lowerUrl = url.toLowerCase();
		
			if (lowerUrl.startsWith("/wb/modules/")
					|| lowerUrl.startsWith("/wb/system/")) {
				// 系统保护的目录
				resp.sendError(HttpServletResponse.SC_FORBIDDEN, url);
			} else if (com.wb.common.Var.cacheEnabled && lowerUrl.startsWith("/wb/")) {
				// WebBuilder缓存目录
				FileBuffer.service(url, req, resp);
			} else {
				// 其他交由用户自定义处理
				chain.doFilter(request, response);
			}
		}
	}

	/**
	 * 系统的初始化以及定义系统常用的静态变量。
	 * 
	 * @param config 过滤器配置对象。
	 * @throws ServletException 如果执行过程中发生异常将抛出。
	 */
	public void init(FilterConfig config) throws ServletException {
		try {
			startTime = new Date();
			servletContext = config.getServletContext();
			path = new File(servletContext.getRealPath("/"));
			pathLen = FileUtil.getPath(path).length() + 1;
			modulePath = new File(path, "wb/modules");
			modulePathText = FileUtil.getPath(Base.modulePath);
			modulePathLen = modulePathText.length() + 1;
			SysUtil.reload(2);
			if (!Var.jndi.isEmpty()) {
				// 如果默认jndi为空，表示数据库未配置。待安装配置完成后加载数据库相关类。
				SysUtil.reload(3);
				TaskManager.start();
			}
			
		} catch (Throwable e) {
			initFailed = true;
			initError = e;
		}
	}

	/**
	 * 对request对象进行一些属性设置。
	 */
	private void setRequest(HttpServletRequest request) {
		request.setAttribute("sys.date", new Date());
		request.setAttribute("sys.id", SysUtil.getId());
		request.setAttribute("sys.userid", request.getSession().getAttribute("sys.user"));
		request.setAttribute("sys.tentantid", request.getSession().getAttribute("sys.tentantid"));
		request.setAttribute("sys.deptcod", request.getSession().getAttribute("sys.deptcod"));
		request.setAttribute("sys.portcod", request.getSession().getAttribute("sys.portcod"));
		//System.out.println(request.getSession().getAttribute("sys.portcod"));
		WebUtil.setLanguage(request);
	}

	/**
	 * 系统停止时执行，完成系统的清理。
	 */
	public void destroy() {
		try {
			TaskManager.stop();
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}
}
