From e08cb56e4adc2b2d7014cdf52a6b106d21b43308 Mon Sep 17 00:00:00 2001 From: septer Date: Sun, 12 Aug 2012 11:02:41 +0800 Subject: [PATCH 1/3] relector DruidDataSourceStatJNDIStatStrategy.java. --- .../DruidDataSourceStatJNDIStatStrategy.java | 178 ------------------ .../druid/stat/DruidStatManagerFacade.java | 2 +- 2 files changed, 1 insertion(+), 179 deletions(-) delete mode 100644 src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java diff --git a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java deleted file mode 100644 index f815aa9b97..0000000000 --- a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.alibaba.druid.stat; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.alibaba.druid.support.logging.Log; -import com.alibaba.druid.support.logging.LogFactory; -import com.alibaba.druid.util.ReflectionUtils; - -public class DruidDataSourceStatJNDIStatStrategy implements DruidDataSourceStatStrategy { - - private final static Log LOG = LogFactory.getLog(DruidDataSourceStatJNDIStatStrategy.class); - - private final static List strategyList = new ArrayList(); - - private final static HashMap> classMethodHM = new HashMap>(); - - public DruidDataSourceStatJNDIStatStrategy(){ - init(); - } - - private void init() { - try { - // cache the class - String className = "com.alibaba.druid.stat.DruidDataSourceStatDefaultStrategy"; - Class clazzFromWebContainer = ReflectionUtils.getClassFromWebContainer(className); - Class clazzFromCurClassLoader = ReflectionUtils.getClassFromCurrentClassLoader(className); - if (clazzFromCurClassLoader != null) { - Object clazzFromCurClassLoaderInstance = clazzFromCurClassLoader.newInstance(); - if (!strategyList.contains(clazzFromCurClassLoaderInstance)) { - strategyList.add(clazzFromCurClassLoaderInstance); - } - } - if (clazzFromWebContainer != null) { - Object clazzFromWebContainerInstance = clazzFromWebContainer.newInstance(); - if (!strategyList.contains(clazzFromWebContainerInstance)) { - if (clazzFromCurClassLoader != null && clazzFromWebContainer != clazzFromCurClassLoader) { - strategyList.add(clazzFromWebContainerInstance); - } - } - } - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - } - - private Object invoke(String methodName, Integer id) { - Object result = null; - try { - HashMap hm = null; - Object invokeRes = null; - Object obj = null; - Method method = null; - for (int i = 0; i < strategyList.size(); i++) { - obj = strategyList.get(i); - hm = classMethodHM.get(obj); - if (hm != null) { - if (hm.containsKey(methodName)) { - method = hm.get(methodName); - if (id == null) { - invokeRes = ReflectionUtils.callObjectMethod(obj, method); - } else { - invokeRes = ReflectionUtils.callObjectMethod(obj, method, id); - } - result = invokeMapResHandler(result, invokeRes); - } else { - result = cacheMethodAndRtnInvodeRes(hm, obj, methodName, id); - } - } else { - hm = new HashMap(); - result = cacheMethodAndRtnInvodeRes(hm, obj, methodName, id); - } - } - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - return result; - } - - private Object cacheMethodAndRtnInvodeRes(HashMap methodHM, Object obj, String methodName, - Integer id) throws Exception { - Method method = null; - Object invokeRes = null; - if (id == null) { - method = ReflectionUtils.getObjectMethod(obj, methodName); - invokeRes = ReflectionUtils.callObjectMethod(obj, method); - } else { - method = ReflectionUtils.getObjectMethod(obj, methodName, id); - invokeRes = ReflectionUtils.callObjectMethod(obj, method, id); - } - methodHM.put(methodName, method); - classMethodHM.put(obj, methodHM); - return invokeRes; - } - - @SuppressWarnings("unchecked") - private Object invokeMapResHandler(Object finalRs, Object invokeRes) { - Object res = null; - if (finalRs == null) { - if (invokeRes instanceof Map) { - res = (Map) invokeRes; - } else if (invokeRes instanceof List) { - res = (List>) invokeRes; - } else { - res = invokeRes; - } - } else { - if (invokeRes instanceof Map) { - Map finalRs_ = (Map) finalRs; - Map invokeRes_ = (Map) invokeRes; - if (invokeRes != null) finalRs_.putAll(invokeRes_); - res = finalRs_; - } else if (invokeRes instanceof List) { - List> finalRs_ = (List>) finalRs; - List> invokeRes_ = (List>) invokeRes; - if (invokeRes != null) finalRs_.addAll(invokeRes_); - res = finalRs_; - } else { - final List list = new ArrayList(); - list.add(finalRs); - list.add(invokeRes); - res = list;// merge the others class type,but in this - } - } - return res; - } - - @SuppressWarnings("unchecked") - public Map getSqlStatData(Integer id) { - return (Map) invoke("getSqlStatData", id); - } - - @SuppressWarnings("unchecked") - public Map getDataSourceStatData(Integer id) { - return (Map) invoke("getDataSourceStatData", id); - } - - @SuppressWarnings("unchecked") - public Map returnJSONBasicStat() { - return (Map) invoke("returnJSONBasicStat", null); - } - - @SuppressWarnings("unchecked") - public List> getSqlStatDataList() { - return (List>) invoke("getSqlStatDataList", null); - } - - @SuppressWarnings("unchecked") - public List getActiveConnectionStackTraceByDataSourceId(Integer id) { - return (List) invoke("getActiveConnectionStackTraceByDataSourceId", id); - } - - @SuppressWarnings("unchecked") - public List getDataSourceStatList() { - return (List) invoke("getDataSourceStatList", null); - } - - @SuppressWarnings("unchecked") - public List> getPoolingConnectionInfoByDataSourceId(Integer id) { - return (List>) invoke("getPoolingConnectionInfoByDataSourceId", id); - } - - public Object getDruidDataSourceById(Integer id) { - return invoke("getDruidDataSourceById", id); - } - - public Object getSqlStatById(Integer id) { - return invoke("getSqlStatById", id); - } - - public void resetAll() { - invoke("resetAll", null); - } - -} diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java index efa89be2a2..864e6d8a09 100644 --- a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java +++ b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java @@ -22,7 +22,7 @@ public class DruidStatManagerFacade { private static DruidDataSourceStatStrategy strategy = null; static { - strategy = new DruidDataSourceStatJNDIStatStrategy(); + strategy = new DruidDataSourceStatReflectStatStrategy(); ctx = new DruidDataSourceStatStrategyContext(strategy); } From a9d7ca7e0f47e90e09598dc103f54d38ac472dce Mon Sep 17 00:00:00 2001 From: septer Date: Sun, 12 Aug 2012 11:02:56 +0800 Subject: [PATCH 2/3] relector DruidDataSourceStatJNDIStatStrategy.java. --- ...ruidDataSourceStatReflectStatStrategy.java | 144 ++++++++++++++++++ .../com/alibaba/druid/stat/ReflectHelper.java | 46 ++++++ .../druid/stat/ReflectStatStrategy.java | 11 ++ .../druid/stat/WebAppReflectStatStrategy.java | 26 ++++ .../stat/WebContainerReflectStatStrategy.java | 25 +++ 5 files changed, 252 insertions(+) create mode 100644 src/main/java/com/alibaba/druid/stat/DruidDataSourceStatReflectStatStrategy.java create mode 100644 src/main/java/com/alibaba/druid/stat/ReflectHelper.java create mode 100644 src/main/java/com/alibaba/druid/stat/ReflectStatStrategy.java create mode 100644 src/main/java/com/alibaba/druid/stat/WebAppReflectStatStrategy.java create mode 100644 src/main/java/com/alibaba/druid/stat/WebContainerReflectStatStrategy.java diff --git a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatReflectStatStrategy.java b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatReflectStatStrategy.java new file mode 100644 index 0000000000..bd1ffbd644 --- /dev/null +++ b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatReflectStatStrategy.java @@ -0,0 +1,144 @@ +package com.alibaba.druid.stat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.alibaba.druid.support.logging.Log; +import com.alibaba.druid.support.logging.LogFactory; +import com.alibaba.druid.util.ReflectionUtils; + +/** + * JNDI数据源通过反射调用Druid相关对象获得相关统计数据, 并处理了WebApp与WebContainer两种数据源同时存在场景的数据合并 + * + * @author septer + */ +public class DruidDataSourceStatReflectStatStrategy implements DruidDataSourceStatStrategy { + + private final static Log LOG = LogFactory.getLog(DruidDataSourceStatReflectStatStrategy.class); + + private static Object clazzFromWebContainer_instacne = null; + private static Object clazzFromCurClassLoader_instacne = null; + + public DruidDataSourceStatReflectStatStrategy(){ + init(); + } + + private void init() { + try { + // cache the class + String className = "com.alibaba.druid.stat.DruidDataSourceStatDefaultStrategy"; + Class clazzFromWebContainer = ReflectionUtils.getClassFromWebContainer(className); + Class clazzFromCurClassLoader = ReflectionUtils.getClassFromCurrentClassLoader(className); + + if (clazzFromWebContainer != null) clazzFromWebContainer_instacne = clazzFromCurClassLoader.newInstance(); + if (clazzFromCurClassLoader != null && clazzFromCurClassLoader != clazzFromWebContainer) { + clazzFromCurClassLoader_instacne = clazzFromCurClassLoader.newInstance(); + } + + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + } + + @SuppressWarnings("unchecked") + private Object invokeMapResHandler(Object finalRs, Object invokeRes) { + Object res = null; + if (finalRs == null) { + if (invokeRes instanceof Map) { + res = (Map) invokeRes; + } else if (invokeRes instanceof List) { + res = (List>) invokeRes; + } else { + res = invokeRes; + } + } else { + if (invokeRes instanceof Map) { + Map finalRs_ = (Map) finalRs; + Map invokeRes_ = (Map) invokeRes; + if (invokeRes != null) finalRs_.putAll(invokeRes_); + res = finalRs_; + } else if (invokeRes instanceof List) { + List> finalRs_ = (List>) finalRs; + List> invokeRes_ = (List>) invokeRes; + if (invokeRes != null) finalRs_.addAll(invokeRes_); + res = finalRs_; + } else { + final List list = new ArrayList(); + list.add(finalRs); + list.add(invokeRes); + res = list;// merge the others class type,but in this + } + } + return res; + } + + private Object mergeStatData(String methodName, Integer methodParam) { + Object result = null; + if (clazzFromWebContainer_instacne != null) { + /*ReflectStatStrategy strategy = new WebAppReflectStatStrategy(); + result = invokeMapResHandler(result, strategy.invoke(clazzFromWebContainer_instacne, methodName, + methodParam)); +*/ + result = invokeMapResHandler(result, ReflectHelper.getInstance().invoke(clazzFromWebContainer_instacne, + methodName, methodParam)); + } + if (clazzFromCurClassLoader_instacne != null) { + /*ReflectStatStrategy strategy = new WebContainerReflectStatStrategy(); + result = invokeMapResHandler(result, strategy.invoke(clazzFromWebContainer_instacne, methodName, + methodParam));*/ + + result = invokeMapResHandler(result, ReflectHelper.getInstance().invoke(clazzFromCurClassLoader_instacne, + methodName, methodParam)); + } + return result; + } + + @SuppressWarnings("unchecked") + public Map getSqlStatData(Integer id) { + return (Map) mergeStatData("getSqlStatData", id); + } + + @SuppressWarnings("unchecked") + public Map getDataSourceStatData(Integer id) { + return (Map) mergeStatData("getDataSourceStatData", id); + } + + @SuppressWarnings("unchecked") + public Map returnJSONBasicStat() { + return (Map) mergeStatData("returnJSONBasicStat", null); + } + + @SuppressWarnings("unchecked") + public List> getSqlStatDataList() { + return (List>) mergeStatData("getSqlStatDataList", null); + } + + @SuppressWarnings("unchecked") + public List getActiveConnectionStackTraceByDataSourceId(Integer id) { + return (List) mergeStatData("getActiveConnectionStackTraceByDataSourceId", id); + } + + @SuppressWarnings("unchecked") + public List getDataSourceStatList() { + return (List) mergeStatData("getDataSourceStatList", null); + } + + @SuppressWarnings("unchecked") + public List> getPoolingConnectionInfoByDataSourceId(Integer id) { + return (List>) mergeStatData("getPoolingConnectionInfoByDataSourceId", id); + } + + public Object getDruidDataSourceById(Integer id) { + return mergeStatData("getDruidDataSourceById", id); + } + + public Object getSqlStatById(Integer id) { + return mergeStatData("getSqlStatById", id); + } + + public void resetAll() { + mergeStatData("resetAll", null); + } + +} diff --git a/src/main/java/com/alibaba/druid/stat/ReflectHelper.java b/src/main/java/com/alibaba/druid/stat/ReflectHelper.java new file mode 100644 index 0000000000..52d5f7f06c --- /dev/null +++ b/src/main/java/com/alibaba/druid/stat/ReflectHelper.java @@ -0,0 +1,46 @@ +package com.alibaba.druid.stat; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import com.alibaba.druid.util.ReflectionUtils; + +public class ReflectHelper { + + private final static List list = new ArrayList(); + private final static HashMap> methodHM = new HashMap>(); + + private ReflectHelper(){ + }; + + private static ReflectHelper instance = new ReflectHelper(); + + public static ReflectHelper getInstance() { + return instance; + } + + public Object invoke(Object obj, String methodName, Integer id) { + Object target = null; + int objIndex = list.indexOf(obj); + if (objIndex != -1) { + target = list.get(objIndex); + } else { + target = obj; + } + HashMap h = methodHM.get(target); + boolean existsMethod = h.containsKey(methodName); + Method method = null; + if (existsMethod) { + method = h.get(methodName); + return ReflectionUtils.callObjectMethod(target, method, id); + } else { + method = ReflectionUtils.getObjectMethod(target, methodName, id); + final HashMap hm = new HashMap(); + hm.put(methodName, method); + methodHM.put(target, hm); + return ReflectionUtils.callObjectMethod(target, method, id); + } + } +} diff --git a/src/main/java/com/alibaba/druid/stat/ReflectStatStrategy.java b/src/main/java/com/alibaba/druid/stat/ReflectStatStrategy.java new file mode 100644 index 0000000000..c42c922998 --- /dev/null +++ b/src/main/java/com/alibaba/druid/stat/ReflectStatStrategy.java @@ -0,0 +1,11 @@ +package com.alibaba.druid.stat; + +import java.lang.reflect.Method; +import java.util.HashMap; + +public abstract class ReflectStatStrategy { + + public final static HashMap> methodHM = new HashMap>(); + + public abstract Object invoke(Object obj, String methodName, Integer id); +} diff --git a/src/main/java/com/alibaba/druid/stat/WebAppReflectStatStrategy.java b/src/main/java/com/alibaba/druid/stat/WebAppReflectStatStrategy.java new file mode 100644 index 0000000000..4cfdf05962 --- /dev/null +++ b/src/main/java/com/alibaba/druid/stat/WebAppReflectStatStrategy.java @@ -0,0 +1,26 @@ +package com.alibaba.druid.stat; + +import java.lang.reflect.Method; +import java.util.HashMap; + +import com.alibaba.druid.util.ReflectionUtils; + +public class WebAppReflectStatStrategy extends ReflectStatStrategy { + + public Object invoke(Object target, String methodName, Integer id) { + HashMap h = methodHM.get(target); + boolean existsMethod = h.containsKey(methodName); + Method method = null; + if (existsMethod) { + method = h.get(methodName); + return ReflectionUtils.callObjectMethod(target, method, id); + } else { + method = ReflectionUtils.getObjectMethod(target, methodName, id); + final HashMap hm = new HashMap(); + hm.put(methodName, method); + methodHM.put(target, hm); + return ReflectionUtils.callObjectMethod(target, method, id); + } + } + +} diff --git a/src/main/java/com/alibaba/druid/stat/WebContainerReflectStatStrategy.java b/src/main/java/com/alibaba/druid/stat/WebContainerReflectStatStrategy.java new file mode 100644 index 0000000000..06a8645d90 --- /dev/null +++ b/src/main/java/com/alibaba/druid/stat/WebContainerReflectStatStrategy.java @@ -0,0 +1,25 @@ +package com.alibaba.druid.stat; + +import java.lang.reflect.Method; +import java.util.HashMap; + +import com.alibaba.druid.util.ReflectionUtils; + +public class WebContainerReflectStatStrategy extends ReflectStatStrategy { + + public Object invoke(Object target, String methodName, Integer id) { + HashMap h = methodHM.get(target); + boolean existsMethod = h.containsKey(methodName); + Method method = null; + if (existsMethod) { + method = h.get(methodName); + return ReflectionUtils.callObjectMethod(target, method, id); + } else { + method = ReflectionUtils.getObjectMethod(target, methodName, id); + final HashMap hm = new HashMap(); + hm.put(methodName, method); + methodHM.put(target, hm); + return ReflectionUtils.callObjectMethod(target, method, id); + } + } +} From 95f7ab01c85a1867f864192c52b088b23d080091 Mon Sep 17 00:00:00 2001 From: septer Date: Sun, 12 Aug 2012 12:05:36 +0800 Subject: [PATCH 3/3] wenshao committed. --- .../DruidStatManagerFacade.java.BASE.java | 75 ++++++++ .../DruidStatManagerFacade.java.LOCAL.java | 75 ++++++++ .../DruidStatManagerFacade.java.REMOTE.java | 168 ++++++++++++++++++ 3 files changed, 318 insertions(+) create mode 100644 src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.BASE.java create mode 100644 src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.LOCAL.java create mode 100644 src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.REMOTE.java diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.BASE.java b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.BASE.java new file mode 100644 index 0000000000..efa89be2a2 --- /dev/null +++ b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.BASE.java @@ -0,0 +1,75 @@ +package com.alibaba.druid.stat; + +import java.util.List; +import java.util.Map; + +/** + * 监控相关的对外数据暴露 + * + *
+ * 1. 为了支持jndi数据源本类内部调用druid相关对象均需要反射调用,返回值也应该是Object,List,Map等无关于druid的类型
+ * 2. 对外暴露的public方法都应该先调用init(),应该有更好的方式,暂时没想到
+ * 
+ * 
+ * @author sandzhang
+ */
+public class DruidStatManagerFacade {
+
+    private final static DruidStatManagerFacade       instance = new DruidStatManagerFacade();
+
+    private static DruidDataSourceStatStrategyContext ctx      = null;
+
+    private static DruidDataSourceStatStrategy        strategy = null;
+
+    static {
+        strategy = new DruidDataSourceStatJNDIStatStrategy();
+        ctx = new DruidDataSourceStatStrategyContext(strategy);
+    }
+
+    private DruidStatManagerFacade(){
+    }
+
+    public static DruidStatManagerFacade getInstance() {
+        return instance;
+    }
+
+    public Map getSqlStatData(Integer id) {
+        return ctx.getSqlStatData(id);
+    }
+
+    public List> getSqlStatDataList() {
+        return ctx.getSqlStatDataList();
+    }
+
+    public List getActiveConnectionStackTraceByDataSourceId(Integer id) {
+        return ctx.getActiveConnectionStackTraceByDataSourceId(id);
+    }
+
+    public Map returnJSONBasicStat() {
+        return ctx.returnJSONBasicStat();
+    }
+
+    public List getDataSourceStatList() {
+        return ctx.getDataSourceStatList();
+    }
+
+    public Map getDataSourceStatData(Integer id) {
+        return ctx.getDataSourceStatData(id);
+    }
+
+    public List> getPoolingConnectionInfoByDataSourceId(Integer id) {
+        return ctx.getPoolingConnectionInfoByDataSourceId(id);
+    }
+
+    public void resetAll() {
+        ctx.resetAll();
+    }
+
+    public Object getDruidDataSourceById(Integer id) {
+        return ctx.getDruidDataSourceById(id);
+    }
+
+    public Object getSqlStatById(Integer id) {
+        return ctx.getSqlStatById(id);
+    }
+}
diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.LOCAL.java b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.LOCAL.java
new file mode 100644
index 0000000000..864e6d8a09
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.LOCAL.java
@@ -0,0 +1,75 @@
+package com.alibaba.druid.stat;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 监控相关的对外数据暴露
+ * 
+ * 
+ * 1. 为了支持jndi数据源本类内部调用druid相关对象均需要反射调用,返回值也应该是Object,List,Map等无关于druid的类型
+ * 2. 对外暴露的public方法都应该先调用init(),应该有更好的方式,暂时没想到
+ * 
+ * 
+ * @author sandzhang
+ */
+public class DruidStatManagerFacade {
+
+    private final static DruidStatManagerFacade       instance = new DruidStatManagerFacade();
+
+    private static DruidDataSourceStatStrategyContext ctx      = null;
+
+    private static DruidDataSourceStatStrategy        strategy = null;
+
+    static {
+        strategy = new DruidDataSourceStatReflectStatStrategy();
+        ctx = new DruidDataSourceStatStrategyContext(strategy);
+    }
+
+    private DruidStatManagerFacade(){
+    }
+
+    public static DruidStatManagerFacade getInstance() {
+        return instance;
+    }
+
+    public Map getSqlStatData(Integer id) {
+        return ctx.getSqlStatData(id);
+    }
+
+    public List> getSqlStatDataList() {
+        return ctx.getSqlStatDataList();
+    }
+
+    public List getActiveConnectionStackTraceByDataSourceId(Integer id) {
+        return ctx.getActiveConnectionStackTraceByDataSourceId(id);
+    }
+
+    public Map returnJSONBasicStat() {
+        return ctx.returnJSONBasicStat();
+    }
+
+    public List getDataSourceStatList() {
+        return ctx.getDataSourceStatList();
+    }
+
+    public Map getDataSourceStatData(Integer id) {
+        return ctx.getDataSourceStatData(id);
+    }
+
+    public List> getPoolingConnectionInfoByDataSourceId(Integer id) {
+        return ctx.getPoolingConnectionInfoByDataSourceId(id);
+    }
+
+    public void resetAll() {
+        ctx.resetAll();
+    }
+
+    public Object getDruidDataSourceById(Integer id) {
+        return ctx.getDruidDataSourceById(id);
+    }
+
+    public Object getSqlStatById(Integer id) {
+        return ctx.getSqlStatById(id);
+    }
+}
diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.REMOTE.java b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.REMOTE.java
new file mode 100644
index 0000000000..c84ba7d3d7
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java.REMOTE.java
@@ -0,0 +1,168 @@
+package com.alibaba.druid.stat;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.alibaba.druid.VERSION;
+import com.alibaba.druid.util.DruidDataSourceUtils;
+import com.alibaba.druid.util.JdbcSqlStatUtils;
+
+/**
+ * 监控相关的对外数据暴露
+ * 
+ * 
+ * 1. 为了支持jndi数据源本类内部调用druid相关对象均需要反射调用,返回值也应该是Object,List,Map等无关于druid的类型
+ * 2. 对外暴露的public方法都应该先调用init(),应该有更好的方式,暂时没想到
+ * 
+ * 
+ * @author sandzhang
+ */
+public class DruidStatManagerFacade {
+
+    private final static DruidStatManagerFacade instance = new DruidStatManagerFacade();
+
+    private DruidStatManagerFacade(){
+    }
+
+    public static DruidStatManagerFacade getInstance() {
+        return instance;
+    }
+
+    private Set getDruidDataSourceInstances() {
+        return DruidDataSourceStatManager.getInstances().keySet();
+    }
+
+    public void resetDataSourceStat() {
+        DruidDataSourceStatManager.getInstance().reset();
+    }
+
+    public void resetSqlStat() {
+        JdbcStatManager.getInstance().reset();
+    }
+
+    public void resetAll() {
+        resetSqlStat();
+        resetDataSourceStat();
+    }
+
+    public Object getSqlStatById(Integer id) {
+        for (Object ds : getDruidDataSourceInstances()) {
+            Object sqlStat = DruidDataSourceUtils.getSqlStat(ds, id);
+            if (sqlStat != null) {
+                return sqlStat;
+            }
+        }
+        return null;
+    }
+
+    public Map getDataSourceStatData(Integer id) {
+        if (id == null) {
+            return null;
+        }
+
+        Object datasource = getDruidDataSourceById(id);
+        return datasource == null ? null : dataSourceToMapData(datasource);
+    }
+
+    public Object getDruidDataSourceById(Integer identity) {
+        if (identity == null) {
+            return null;
+        }
+
+        for (Object datasource : getDruidDataSourceInstances()) {
+            if (System.identityHashCode(datasource) == identity) {
+                return datasource;
+            }
+        }
+        return null;
+    }
+
+    public List> getSqlStatDataList() {
+        List> result = new ArrayList>();
+        for (Object datasource : getDruidDataSourceInstances()) {
+            for (Object sqlStat : DruidDataSourceUtils.getSqlStatMap(datasource).values()) {
+
+                Map data = JdbcSqlStatUtils.getData(sqlStat);
+
+                long executeCount = (Long) data.get("ExecuteCount");
+                long runningCount = (Long) data.get("RunningCount");
+
+                if (executeCount == 0 && runningCount == 0) {
+                    continue;
+                }
+
+                result.add(data);
+            }
+        }
+        return result;
+    }
+
+    public Map getSqlStatData(Integer id) {
+        if (id == null) {
+            return null;
+        }
+
+        Object sqlStat = getSqlStatById(id);
+
+        if (sqlStat == null) {
+            return null;
+        }
+
+        return JdbcSqlStatUtils.getData(sqlStat);
+    }
+
+    public List getDataSourceStatList() {
+        List datasourceList = new ArrayList();
+        for (Object dataSource : getDruidDataSourceInstances()) {
+            datasourceList.add(dataSourceToMapData(dataSource));
+        }
+        return datasourceList;
+    }
+
+    public Map returnJSONBasicStat() {
+        Map dataMap = new LinkedHashMap();
+        dataMap.put("Version", VERSION.getVersionNumber());
+        dataMap.put("Drivers", getDriversData());
+        return dataMap;
+    }
+
+    private List getDriversData() {
+        List drivers = new ArrayList();
+        for (Enumeration e = DriverManager.getDrivers(); e.hasMoreElements();) {
+            Driver driver = e.nextElement();
+            drivers.add(driver.getClass().getName());
+        }
+        return drivers;
+    }
+
+    public List> getPoolingConnectionInfoByDataSourceId(Integer id) {
+        Object datasource = getDruidDataSourceById(id);
+
+        if (datasource == null) {
+            return null;
+        }
+
+        return DruidDataSourceUtils.getPoolingConnectionInfo(datasource);
+    }
+
+    public List getActiveConnectionStackTraceByDataSourceId(Integer id) {
+        Object datasource = getDruidDataSourceById(id);
+
+        if (datasource == null || DruidDataSourceUtils.isRemoveAbandoned(datasource)) {
+            return null;
+        }
+
+        return DruidDataSourceUtils.getActiveConnectionStackTrace(datasource);
+    }
+
+    private Map dataSourceToMapData(Object dataSource) {
+
+        return DruidDataSourceUtils.getStatData(dataSource);
+    }
+}