/* * Copyright 2008 biaoping.yin * * 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.frameworkset.persitent.util; import java.io.StringWriter; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.frameworkset.spi.BaseApplicationContext; import org.frameworkset.spi.assemble.Pro; import bboss.org.apache.velocity.VelocityContext; import com.frameworkset.common.poolman.sql.PoolManResultSetMetaData; import com.frameworkset.common.poolman.util.SQLManager; import com.frameworkset.util.DaemonThread; import com.frameworkset.util.ResourceInitial; import com.frameworkset.util.VariableHandler.SQLStruction; import com.frameworkset.velocity.BBossVelocityUtil; /** * <p> * Title: SQLUtil.java * </p> * <p> * Description: * </p> * <p> * bboss workgroup * </p> * <p> * Copyright (c) 2007 * </p> * * @Date 2010-7-12 下午07:38:55 * @author biaoping.yin * @version 1.0 */ public class SQLUtil { protected BaseApplicationContext sqlcontext; private static Logger log = Logger.getLogger(SQLUtil.class); protected static Map<String,SQLUtil> sqlutils = new HashMap<String,SQLUtil>(); protected SQLCache cache = new SQLCache(); protected static long refresh_interval = 5000; protected String defaultDBName = null; protected Map<String,SQLInfo> sqls; protected Map<String,SQLRef> sqlrefs; protected boolean hasrefs; public static class SQLRef { public SQLRef(String sqlname, String sqlfile, String name) { super(); this.sqlname = sqlname; this.sqlfile = sqlfile; this.name = name; } private SQLUtil sqlutil; private String sqlname; private String sqlfile; private String name; public String getSqlname() { return sqlname; } public String getSqlfile() { return sqlfile; } public String getName() { return name; } public SQLInfo getSQLInfo(String dbname) { if(sqlutil == null) { init(); } return this.sqlutil.getSQLInfo(dbname, sqlname); } private synchronized void init() { if(sqlutil == null) { this.sqlutil = SQLUtil.getInstance(sqlfile); } } public String getSQL(String dbname) { if(sqlutil == null) { init(); } return this.sqlutil.getSQL(dbname, sqlname); } public String getSQL(String dbname, Map variablevalues) { if(sqlutil == null) { init(); } return this.sqlutil.getSQL(dbname, sqlname, variablevalues); } } public Map<String,SQLRef> getSQLRefers() { return this.sqlrefs; } /** * 默认的sql结构缓存器 */ private static GloableSQLUtil globalSQLUtil = new GloableSQLUtil(); // /** // * sql语句velocity模板索引表,以sql语句的名称为索引 // * 当sql文件重新加载时,这些模板也会被重置 // */ // private Map<String,SQLTemplate> sqlVelocityTemplates; // private static DaemonThread damon = null; /** * */ private void trimValues() { if(sqlcontext == null) return; sqls = null; sqlrefs = null; sqls = new HashMap<String,SQLInfo>(); sqlrefs = new HashMap<String,SQLRef> (); Set keys = this.sqlcontext.getPropertyKeys(); if(keys != null && keys.size() > 0) { Iterator<String> keys_it = keys.iterator(); while(keys_it.hasNext()) { String key = keys_it.next(); Pro pro = this.sqlcontext.getProBean(key); String sqlfile = (String)pro.getExtendAttribute("sqlfile"); if(sqlfile == null) { Object o = pro.getObject(); if(o instanceof String) { String value = (String)o; if(value != null) { boolean istpl = pro.getBooleanExtendAttribute("istpl",true);//标识sql语句是否为velocity模板 boolean multiparser = pro.getBooleanExtendAttribute("multiparser",istpl);//如果sql语句为velocity模板,则在批处理时是否需要每条记录都需要分析sql语句 SQLTemplate sqltpl = null; value = value.trim(); SQLInfo sqlinfo = new SQLInfo(key, value, istpl,multiparser); sqlinfo.setSqlutil(this); if(istpl) { sqltpl = new SQLTemplate(sqlinfo); sqlinfo.setSqltpl(sqltpl); BBossVelocityUtil.initTemplate(sqltpl); sqltpl.process(); } sqls.put(key, sqlinfo); } } } else { String sqlname = (String)pro.getExtendAttribute("sqlname"); if(sqlname == null) { log.warn(sqlcontext.getConfigfile()+"中name="+key+"的sql被配置为对"+sqlfile+"中的sql引用,但是没有通过sqlname设置要引用的sql语句!"); } else { sqlrefs.put(key, new SQLRef(sqlname,sqlfile,key)); hasrefs = true; } } } } } public boolean hasrefs() { return this.hasrefs; } void _destroy() { if(sqls != null) { this.sqls.clear(); sqls = null; } if(sqlrefs != null) { this.sqlrefs.clear(); sqlrefs = null; } this.cache.clear(); if(sqlcontext != null) sqlcontext.destroy(true); defaultDBName = null; } void reinit() { if(sqls != null) { this.sqls.clear(); sqls = null; } if(sqlrefs != null) { this.sqlrefs.clear(); sqlrefs = null; } this.cache.clear(); String file = sqlcontext.getConfigfile(); sqlcontext.destroy(true); sqlcontext = new SQLSOAFileApplicationContext(file); defaultDBName = sqlcontext.getProperty("default.dbname"); trimValues(); // if(refresh_interval > 0 ) // { // if(damon == null) // { // damon = new DaemonThread(file,refresh_interval,new ResourceSQLRefresh(this)); // damon.start(); // } // } // else // { // if(damon != null) // { // // try // { // damon.interrupt(); // } // catch(Exception e) // { // try { // damon.stop(); // } catch (Exception e2) { // damon.stopped(); // } // } // damon = null; // } // } } public SQLStruction getSQLStruction(SQLInfo sqlinfo,String newsql) { return this.cache.getSQLStruction(sqlinfo,newsql); } public SQLStruction getTotalsizeSQLStruction(SQLInfo totalsizesqlinfo,String totalsizesql) { return this.cache.getTotalsizeSQLStruction(totalsizesqlinfo,totalsizesql); } static class ResourceSQLRefresh implements ResourceInitial { private SQLUtil sqlutil ; public ResourceSQLRefresh(SQLUtil sqlutil) { this.sqlutil = sqlutil; } public void reinit() { sqlutil.reinit(); } } public static void stopmonitor() { try { if(SQLUtil.damon != null) { SQLUtil.damon.stopped(); damon = null; } } catch (Throwable e) { // // TODO Auto-generated catch block // e.printStackTrace(); } } public String getSQLFile() { return this.sqlcontext.getConfigfile(); } static { BaseApplicationContext.addShutdownHook(new Runnable(){ public void run() { SQLUtil.stopmonitor(); destory(); globalSQLUtil._destroy(); globalSQLUtil = null; }}); } private static Object lock = new Object(); private static void checkSQLUtil(String sqlfile,SQLUtil sqlutil){ refresh_interval = BaseApplicationContext.getSQLFileRefreshInterval(); if(refresh_interval > 0) { if(damon == null) { synchronized(lock) { if(damon == null) { damon = new DaemonThread(refresh_interval,"SQL files Refresh Worker"); damon.start(); } } } damon.addFile(sqlfile, new ResourceSQLRefresh(sqlutil)); } } private SQLUtil(String sqlfile) { sqlcontext = new SQLSOAFileApplicationContext(sqlfile); this.trimValues(); defaultDBName = sqlcontext.getProperty("default.dbname"); // refresh_interval = ApplicationContext.getApplicationContext().getLongProperty("sqlfile.refresh_interval", -1); checkSQLUtil(sqlfile,this); // if(refresh_interval > 0) // { // damon = new DaemonThread(sqlfile,refresh_interval,new ResourceSQLRefresh(this)); // damon.start(); // } } public SQLUtil() { // TODO Auto-generated constructor stub } public static SQLUtil getInstance(String sqlfile) { SQLUtil sqlUtil = sqlutils.get(sqlfile); if(sqlUtil != null) return sqlUtil; synchronized(sqlutils) { sqlUtil = sqlutils.get(sqlfile); if(sqlUtil != null) return sqlUtil; sqlUtil = new SQLUtil(sqlfile); sqlutils.put(sqlfile, sqlUtil); } return sqlUtil; } static void destory() { if(sqlutils != null) { Iterator<Map.Entry<String,SQLUtil>> it = sqlutils.entrySet().iterator(); while(it.hasNext()) { Map.Entry<String,SQLUtil> entry = it.next(); entry.getValue()._destroy(); } sqlutils.clear(); sqlutils = null; } } private SQLInfo getReferSQLInfo(String dbname, String sqlname) { SQLRef ref = this.sqlrefs.get(sqlname); if(ref != null) return ref.getSQLInfo(dbname); else return null; } public SQLInfo getSQLInfo(String dbname, String sqlname) { SQLInfo sql = null; if(this.hasrefs) { sql = this.getReferSQLInfo(dbname, sqlname); if(sql != null) return sql; } String dbtype = SQLManager.getInstance().getDBAdapter(dbname) .getDBTYPE(); if(dbtype != null) // sql = sqlcontext.getProperty(sqlname + "-" + dbtype.toLowerCase()); sql = sqls.get(sqlname + "-" + dbtype.toLowerCase()); if (sql == null) { // sql = sqlcontext.getProperty(sqlname); sql = sqls.get(sqlname); } if (sql == null) { // sql = sqlcontext.getProperty(sqlname + "-default"); sql = sqls.get(sqlname + "-default"); } return sql; } public String getPlainSQL(String dbname, String sqlname) { SQLInfo sql = null; if(this.hasrefs) { sql = this.getReferSQLInfo(dbname, sqlname); if(sql != null) return sql.getSql(); } String dbtype = SQLManager.getInstance().getDBAdapter(dbname) .getDBTYPE(); if(dbtype != null) // sql = sqlcontext.getProperty(sqlname + "-" + dbtype.toLowerCase()); sql = sqls.get(sqlname + "-" + dbtype.toLowerCase()); if (sql == null) { // sql = sqlcontext.getProperty(sqlname); sql = sqls.get(sqlname); } if (sql == null) { // sql = sqlcontext.getProperty(sqlname + "-default"); sql = sqls.get(sqlname + "-default"); } if(sql != null) return sql.getSql(); else return null; } private String getReferSQL(String dbname, String sqlname) { SQLRef ref = this.sqlrefs.get(sqlname); if(ref != null) return ref.getSQL(dbname); else return null; } public String getSQL(String dbname, String sqlname) { if(this.hasrefs) { String sql = this.getReferSQL(dbname, sqlname); if(sql != null) return sql; } String dbtype = SQLManager.getInstance().getDBAdapter(dbname) .getDBTYPE(); SQLInfo sql = null; if(dbtype != null) // sql = sqlcontext.getProperty(sqlname + "-" + dbtype.toLowerCase()); sql = sqls.get(sqlname + "-" + dbtype.toLowerCase()); if (sql == null) { // sql = sqlcontext.getProperty(sqlname); sql = sqls.get(sqlname); } if (sql == null) { // sql = sqlcontext.getProperty(sqlname + "-default"); sql = sqls.get(sqlname + "-default"); } return sql != null?sql.getSql():null; } private String getReferSQL(String dbname, String sqlname,Map variablevalues) { SQLRef ref = this.sqlrefs.get(sqlname); if(ref != null) return ref.getSQL(dbname,variablevalues); else return null; } public String getSQL(String dbname, String sqlname,Map variablevalues) { if(this.hasrefs) { String sql = this.getReferSQL(dbname, sqlname,variablevalues); if(sql != null) return sql; } String dbtype = SQLManager.getInstance().getDBAdapter(dbname) .getDBTYPE(); String newsql = null; SQLInfo sql = null; if(dbtype != null) // sql = sqlcontext.getProperty(sqlname + "-" + dbtype.toLowerCase()); sql = sqls.get(sqlname + "-" + dbtype.toLowerCase()); if (sql == null) { // sql = sqlcontext.getProperty(sqlname); sql = sqls.get(sqlname); } if (sql == null) { // sql = sqlcontext.getProperty(sqlname + "-default"); sql = sqls.get(sqlname + "-default"); } if(sql != null ) { newsql = _getSQL(sql,variablevalues); } return newsql; } public static String _getSQL(SQLInfo sqlinfo,Map variablevalues) { // String newsql = null; // if(sqlinfo.istpl() ) // { // StringWriter sw = new StringWriter(); // sqlinfo.getSqltpl().merge(BBossVelocityUtil.buildVelocityContext(variablevalues),sw); // newsql = sw.toString(); // } // else // newsql = sqlinfo.getSql(); // return newsql; String sql = null; VelocityContext vcontext = null; if(sqlinfo.istpl()) { sqlinfo.getSqltpl().process();//识别sql语句是不是真正的velocity sql模板 if(sqlinfo.istpl()) { vcontext = BBossVelocityUtil.buildVelocityContext(variablevalues);//一个context是否可以被同时用于多次运算呢? StringWriter sw = new StringWriter(); sqlinfo.getSqltpl().merge(vcontext,sw); sql = sw.toString(); } else { sql = sqlinfo.getSql(); } } else { sql = sqlinfo.getSql(); } return sql; } /** * mark 1 * @param name * @param sql * @param variablevalues * @return */ public String evaluateSQL(String name,String sql,Map variablevalues) { if(sql != null && variablevalues != null && variablevalues.size() > 0) { sql = BBossVelocityUtil.evaluate(variablevalues, sqlcontext.getConfigfile()+"|"+name, sql); } return sql; } public String getSQL(String sqlname,Map variablevalues) { return getSQL(null, sqlname,variablevalues) ; } public String getDBName(String sqlname) { Pro pro = sqlcontext.getProBean(sqlname); if (pro == null) { return defaultDBName; } return pro.getStringExtendAttribute("dbname"); } public String[] getPropertyKeys() { Set<String> keys = this.sqlcontext.getPropertyKeys(); if(keys == null ) return new String[]{}; String[] rets = new String[keys.size()]; Iterator<String> its = keys.iterator(); int i = 0; while(its.hasNext()) { rets[i] = its.next(); i ++; } return rets; } public SQLInfo getSQLInfo(String sqlname) { return getSQLInfo(null, sqlname); } public String getSQL(String sqlname) { return getSQL(null, sqlname); } public Map getMapSQLs(String sqlname) { return getMapSQLs(getDBName(sqlname), sqlname); } public Map getMapSQLs(String dbname, String sqlname) { Map sqls = sqlcontext.getMapProperty(sqlname); if (sqls == null) { String dbtype = SQLManager.getInstance().getDBAdapter(dbname) .getDBTYPE(); sqls = sqlcontext.getMapProperty(sqlname + "-" + dbtype.toLowerCase()); } if (sqls == null) { sqls = sqlcontext.getMapProperty(sqlname + "-default"); } return sqls; } /** * * @param dbname * @param sqlkey * @param rsmetadata * @return * @throws SQLException */ public PoolManResultSetMetaData getPoolManResultSetMetaData(com.frameworkset.orm.adapter.DB db,String dbname,String sqlkey,ResultSetMetaData rsmetadata) throws SQLException { return this.cache.getPoolManResultSetMetaData(db,dbname, sqlkey, rsmetadata); } public List getListSQLs(String sqlname) { return getListSQLs(getDBName(sqlname), sqlname); } public List getListSQLs(String dbname, String sqlname) { List sqls = sqlcontext.getListProperty(sqlname); if (sqls == null) { String dbtype = SQLManager.getInstance().getDBAdapter(dbname) .getDBTYPE(); sqls = sqlcontext.getListProperty(sqlname + "-" + dbtype.toLowerCase()); } if (sqls == null) { sqls = sqlcontext.getListProperty(sqlname + "-default"); } return sqls; } public Set getSetSQLs(String sqlname) { return getSetSQLs(getDBName(sqlname), sqlname); } public Set getSetSQLs(String dbname, String sqlname) { Set sqls = sqlcontext.getSetProperty(sqlname); if (sqls == null) { String dbtype = SQLManager.getInstance().getDBAdapter(dbname) .getDBTYPE(); sqls = sqlcontext.getSetProperty(sqlname + "-" + dbtype.toLowerCase()); } if (sqls == null) { sqls = sqlcontext.getSetProperty(sqlname + "-default"); } return sqls; } /** * @return the sqlcontext */ public BaseApplicationContext getSqlcontext() { return sqlcontext; } /** * @return the refresh_interval */ public long getRefresh_interval() { return refresh_interval; } public static List<String> getSQLFiles() { Iterator<String> it = sqlutils.keySet().iterator(); List<String> files = new ArrayList<String>(); while(it.hasNext()) files.add(it.next()); return files; } public static GloableSQLUtil getGlobalSQLUtil() { return globalSQLUtil; } public boolean fromConfig() { return this.sqlcontext != null; } }