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); + } + } +}