package com.nfwork.dbfound.core; import java.io.File; import java.sql.Connection; import java.sql.SQLException; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.nfwork.dbfound.db.ConnectionProvide; import com.nfwork.dbfound.db.ConnectionProvideManager; import com.nfwork.dbfound.db.dialect.SqlDialect; import com.nfwork.dbfound.el.DBFoundEL; import com.nfwork.dbfound.exception.DBFoundRuntimeException; import com.nfwork.dbfound.model.ModelCache; import com.nfwork.dbfound.model.bean.Model; import com.nfwork.dbfound.util.DataUtil; import com.nfwork.dbfound.util.JsonUtil; import com.nfwork.dbfound.util.LogUtil; public class Context { public boolean outMessage = true; public boolean isExport = false; public boolean queryLimit = DBFoundConfig.getQueryLimit(); public int queryLimitSize = DBFoundConfig.getQueryLimitSize(); public int reportQueryLimitSize = DBFoundConfig.getReportQueryLimitSize(); public HttpServletRequest request; public HttpServletResponse response; private String currentPath; private String currentModel; private Map<String, ConnObject> connMap; private boolean inWebContainer; private Map<String, Object> rootDatas; private Map<String, Object> paramDatas; private Map<String, Object> outParamDatas; private Map<String, Object> requestDatas; private Map<String, Object> sessionDatas; private Transaction transaction = new Transaction(); private String createThreadName = Thread.currentThread().getName(); public Transaction getTransaction() { String runName = Thread.currentThread().getName(); if (createThreadName.equals(runName) == false) { throw new DBFoundRuntimeException(String .format("Context transaction can not user by diffrent thread,create thread:%s, run thread:%s", createThreadName, runName)); } return transaction; } /** * 得到当前的Thread * @param request * @param response * @return */ public static Context getCurrentContext(HttpServletRequest request, HttpServletResponse response) { Object context = request.getAttribute("_currentContext"); if (context == null) { context = new Context(request, response); request.setAttribute("_currentContext", context); } return (Context) context; } public Context() { rootDatas = new HashMap<String, Object>(); } /** * 根据map生成一个thread对象 * * @param datas */ public Context(Map<String, Object> datas) { if (datas == null) { datas = new HashMap<String, Object>(); } rootDatas = datas; } private Context(HttpServletRequest request, HttpServletResponse response) { rootDatas = new HashMap<String, Object>(); cloneParamData(request); cloneRequestData(request); cloneSessionData(request.getSession()); inWebContainer = true; this.request = request; this.response = response; } /** * 复制session数据 */ @SuppressWarnings("unchecked") public void cloneSessionData(HttpSession session) { Enumeration<String> enumeration = session.getAttributeNames(); while (enumeration.hasMoreElements()) { String paramName = enumeration.nextElement(); if (paramName.indexOf(".") > -1) { continue; // 初始化复制session数据时,不克隆a.b多层次数据。 } setSessionData(paramName, session.getAttribute(paramName)); } } /** * 复制param数据 */ @SuppressWarnings("unchecked") public void cloneParamData(HttpServletRequest request) { Enumeration<String> enumeration = request.getParameterNames(); while (enumeration.hasMoreElements()) { String paramName = enumeration.nextElement(); String value = request.getParameter(paramName); Object object; if (value.startsWith("{") && value.endsWith("}")) { object = JsonUtil.jsonToMap(value); } else if (value.startsWith("[") && value.endsWith("]")) { object = JsonUtil.jsonToList(value); } else { object = value; } setParamData(paramName, object); } } /** * 复制request数据 */ @SuppressWarnings( { "unchecked" }) public void cloneRequestData(HttpServletRequest request) { Enumeration<String> enumeration = request.getAttributeNames(); while (enumeration.hasMoreElements()) { String paramName = enumeration.nextElement(); if ("_currentContext".equals(paramName)) { continue; } else if (paramName.indexOf(".") > -1) { continue; // 初始化复制request数据时,不克隆a.b多层次数据。 } setRequestData(paramName, request.getAttribute(paramName)); } } public Object getData(String express) { return DBFoundEL.getData(express, rootDatas); } /** * 根据表达式得到context内容 * @param express * @param class1 * @return */ public <T> T getData(String express, Class<T> class1) { Object object = getData(express); if (object == null) { return null; } else if (object.getClass().equals(class1)) { } else if (class1.equals(Integer.class) || class1.equals(int.class)) { object = DataUtil.intValue(object); } else if (class1.equals(Long.class) || class1.equals(long.class)) { object = DataUtil.longValue(object); } else if (class1.equals(Float.class) || class1.equals(float.class)) { object = DataUtil.floatValue(object); } else if (class1.equals(Double.class) || class1.equals(double.class)) { object = DataUtil.doubleValue(object); } else if (class1.equals(Date.class)) { object = DataUtil.dateValue(object); } else if (class1.equals(String.class)) { object = DataUtil.stringValue(object); } else if (class1.equals(Short.class) || class1.equals(short.class)) { object = DataUtil.shortValue(object); } else if (class1.equals(Byte.class) || class1.equals(byte.class)) { object = DataUtil.byteValue(object); } return (T) object; } public Map<String, Object> getDatas() { return rootDatas; } public String getString(String express) { Object object = getData(express); if (object != null) { return object.toString(); } return null; } public void setData(String name, Object object) { if (name.startsWith("request.")) { name = name.substring(8); setRequestData(name, object); } else if (name.startsWith("session.")) { name = name.substring(8); setSessionData(name, object); } else if (name.startsWith("param.")) { name = name.substring(6); setParamData(name, object); } else if (name.startsWith("outParam.")) { name = name.substring(9); setOutParamData(name, object); } else if (name.equals("param") || name.equals("outParam") || name.equals("request") || name.equals("session")) { throw new DBFoundRuntimeException("context inner object (param,request,session,outParam) can not set"); } else { setRootData(name, object); } } /** * 放参数到root集 * * @param name * @param object */ private void setRootData(String name, Object object) { if (name.indexOf(".") > -1) { throw new DBFoundRuntimeException("param name can not be cotain '.' :" + name); } if (request != null) { request.setAttribute(name, object); } rootDatas.put(name, object); } /** * 放参数到param集 * * @param name * @param value */ public void setParamData(String name, Object value) { if (name.indexOf(".") > -1) { throw new DBFoundRuntimeException("param name can not be cotain '.' :" + name); } if (paramDatas == null) { Object o = rootDatas.get("param"); if (o != null && o instanceof Map) { paramDatas = (Map) o; } else { paramDatas = new HashMap<String, Object>(); rootDatas.put("param", paramDatas); } } if (request != null) { request.setAttribute(name, value); } paramDatas.put(name, value); } /** * 放参数到outParam集 * * @param name * @param object */ public void setOutParamData(String name, Object object) { if (name.indexOf(".") > -1) { throw new DBFoundRuntimeException("param name can not be cotain '.' :" + name); } if (outParamDatas == null) { Object o = rootDatas.get("outParam"); if (o != null && o instanceof Map) { outParamDatas = (Map) o; } else { outParamDatas = new HashMap<String, Object>(); rootDatas.put("outParam", outParamDatas); } } outParamDatas.put(name, object); } /** * 放参数到request集 * * @param name * @param object */ public void setRequestData(String name, Object object) { if (name.indexOf(".") > -1) { throw new DBFoundRuntimeException("param name can not be cotain '.' :" + name); } if (requestDatas == null) { Object o = rootDatas.get("request"); if (o != null && o instanceof Map) { requestDatas = (Map) o; } else { requestDatas = new HashMap<String, Object>(); rootDatas.put("request", requestDatas); } } if (request != null) { request.setAttribute(name, object); } requestDatas.put(name, object); } /** * 放参数到session集 * * @param name * @param object */ public void setSessionData(String name, Object object) { if (name.indexOf(".") > -1) { throw new DBFoundRuntimeException("param name can not be cotain '.' :" + name); } if (sessionDatas == null) { Object o = rootDatas.get("session"); if (o != null && o instanceof Map) { sessionDatas = (Map) o; } else { sessionDatas = new HashMap<String, Object>(); rootDatas.put("session", sessionDatas); } } if (request != null) { request.getSession().setAttribute(name, object); } sessionDatas.put(name, object); } /** * 获取model * * @param modelName * @return */ public Model getModel(String modelName) { Model model = ModelCache.get(modelName); File file = new File(model.getFileLocation()); long newFileLastModify = file.lastModified(); if (newFileLastModify > model.getFileLastModify()) { ModelCache.remove(modelName); model = ModelCache.get(modelName); } return model; } /** * 得到数据库连接 * @param provideName * @return */ public Connection getConn(String provideName) { // 校验是否夸线程 String runName = Thread.currentThread().getName(); if (createThreadName.equals(runName) == false) { throw new DBFoundRuntimeException(String .format("Context transaction can not user by diffrent thread,create thread:%s, run thread:%s", createThreadName, runName)); } if (transaction.isOpen()) { if (transaction.connMap == null) { transaction.connMap = new HashMap<String, ConnObject>(); } ConnObject connObject = transaction.connMap.get(provideName); if (connObject == null) { ConnectionProvide provide = ConnectionProvideManager.getConnectionProvide(provideName); Connection conn = provide.getConnection(); provide.closeAutoCommit(conn); connObject = new ConnObject(provide, conn); transaction.connMap.put(provideName, connObject); } return connObject.connection; } else { if (connMap == null) { connMap = new HashMap<String, ConnObject>(); } ConnObject connObject = connMap.get(provideName); if (connObject == null) { ConnectionProvide provide = ConnectionProvideManager.getConnectionProvide(provideName); Connection conn = provide.getConnection(); connObject = new ConnObject(provide, conn); connMap.put(provideName, connObject); } return connObject.connection; } } /** * 得到默认数据库连接 * @return * @throws SQLException */ public Connection getConn() throws SQLException { return getConn("_default"); } public SqlDialect getConnDialect(String provideName) { if (transaction.isOpen()) { ConnectionProvide provide = transaction.connMap.get(provideName).provide; return provide.getSqlDialect(); } else { ConnectionProvide provide = connMap.get(provideName).provide; return provide.getSqlDialect(); } } /** * 关闭连接 */ public void closeConns() { if (connMap == null || connMap.isEmpty()) { return; } Collection<ConnObject> connObjects = connMap.values(); for (ConnObject connObject : connObjects) { try { ConnectionProvide provide = connObject.provide; Connection connection = connObject.connection; provide.closeConnection(connection); } catch (Exception e) { LogUtil.error("database connection close exception:" + e.getMessage(), e); } } connMap.clear(); } public String getCurrentPath() { return currentPath; } public void setCurrentPath(String currentPath) { this.currentPath = currentPath; } public String getCurrentModel() { return currentModel; } public void setCurrentModel(String currentModel) { this.currentModel = currentModel; } public Map<String, Object> getOutParamDatas() { return outParamDatas; } public boolean isInWebContainer() { return inWebContainer; } public String getCreateThreadName() { return createThreadName; } static { DBFoundConfig.init(); } class ConnObject { Connection connection; ConnectionProvide provide; ConnObject(ConnectionProvide provide, Connection connection) { this.connection = connection; this.provide = provide; } } }