From aea998cc03d8b049add66ce0abc7ce41e7729cef Mon Sep 17 00:00:00 2001 From: Woonduk Kang Date: Tue, 11 Sep 2012 10:20:52 +0000 Subject: [PATCH] =?UTF-8?q?[=EA=B0=95=EC=9A=B4=EB=8D=95]=20[LUCYSUS-1744]?= =?UTF-8?q?=20=EB=B0=94=EC=9D=B8=EB=94=A9=20=EB=B3=80=EC=88=98=20api=20?= =?UTF-8?q?=ED=95=A0=EB=8B=B9=20api=EC=9D=98=20=EC=95=84=EA=B7=9C=EB=A8=BC?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EB=AC=B8=EC=9E=90=EC=97=B4=EB=A1=9C=20?= =?UTF-8?q?=EC=B9=98=ED=99=98=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EA=B0=9C=EB=B0=9C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@626 84d0f5b1-2673-498c-a247-62c4ff18d310 --- .../mysql/MySQLPreparedStatementModifier.java | 16 ++- ...paredStatementBindVariableInterceptor.java | 14 ++- .../PreparedStatementMethodInterceptor.java | 17 +++- .../java/com/profiler/util/ArrayUtils.java | 53 ++++++++++ .../java/com/profiler/util/NumberUtils.java | 11 +++ .../java/com/profiler/util/StringUtils.java | 20 ++++ .../util/bindvalue/BindValueConverter.java | 99 ++++++++++++++----- .../bindvalue/converter/BytesConverter.java | 23 +++++ .../converter/ClassNameConverter.java | 28 ++++++ .../util/bindvalue/converter/Converter.java | 5 + .../converter/NullTypeConterver.java | 9 ++ .../converter/SimpleTypeConverter.java | 21 ++++ .../com/profiler/util/ArrayUtilsTest.java | 31 ++++++ .../bindvalue/BindValueConverterTest.java | 18 ++++ 14 files changed, 325 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/profiler/util/ArrayUtils.java create mode 100644 src/main/java/com/profiler/util/bindvalue/converter/BytesConverter.java create mode 100644 src/main/java/com/profiler/util/bindvalue/converter/ClassNameConverter.java create mode 100644 src/main/java/com/profiler/util/bindvalue/converter/Converter.java create mode 100644 src/main/java/com/profiler/util/bindvalue/converter/NullTypeConterver.java create mode 100644 src/main/java/com/profiler/util/bindvalue/converter/SimpleTypeConverter.java create mode 100644 src/test/java/com/profiler/util/ArrayUtilsTest.java create mode 100644 src/test/java/com/profiler/util/bindvalue/BindValueConverterTest.java diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java index 1ebfdc57a..76065b0c2 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java @@ -4,10 +4,7 @@ import java.lang.reflect.Method; import java.security.ProtectionDomain; import java.sql.Connection; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListSet; import java.util.logging.Level; @@ -57,7 +54,7 @@ public class MySQLPreparedStatementModifier extends AbstractModifier { preparedStatement.addTraceVariable("__url", "__setUrl", "__getUrl", "java.lang.String"); preparedStatement.addTraceVariable("__sql", "__setSql", "__getSql", "java.lang.String"); - preparedStatement.addTraceVariable("__bindValue", "__setBindValue", "__getBindValue", "java.util.List", "java.util.Collections.synchronizedList(new java.util.LinkedList());"); + preparedStatement.addTraceVariable("__bindValue", "__setBindValue", "__getBindValue", "java.util.Map", "java.util.Collections.synchronizedMap(new java.util.HashMap());"); bindVariableIntercept(preparedStatement, classLoader, protectedDomain); return preparedStatement.toBytecode(); @@ -90,14 +87,15 @@ public class MySQLPreparedStatementModifier extends AbstractModifier { String methodName = method.getName(); String[] parameterType = JavaAssistUtils.getParameterType(method.getParameterTypes()); try { - preparedStatement.addInterceptor(methodName, parameterType , interceptor); + preparedStatement.addInterceptor(methodName, parameterType, interceptor); } catch (NotFoundInstrumentException e) { - // bind variable setter메소드를 못찾을 경우는 그냥 경고만 표시 - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, "bindVariable api modify fail. Cause:" + e.getMessage(), e); + // bind variable setter메소드를 못찾을 경우는 그냥 경고만 표시, 에러 아님. + if (logger.isLoggable(Level.INFO)) { + logger.log(Level.INFO, "bindVariable api not found. Cause:" + e.getMessage(), e); } } } + } diff --git a/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementBindVariableInterceptor.java b/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementBindVariableInterceptor.java index 3f7fbf9ae..251e5f1a6 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementBindVariableInterceptor.java +++ b/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementBindVariableInterceptor.java @@ -3,17 +3,19 @@ package com.profiler.modifier.db.mysql.interceptors; import com.profiler.context.Trace; import com.profiler.interceptor.StaticAfterInterceptor; import com.profiler.util.MetaObject; +import com.profiler.util.NumberUtils; import com.profiler.util.StringUtils; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; public class PreparedStatementBindVariableInterceptor implements StaticAfterInterceptor { private final Logger logger = Logger.getLogger(PreparedStatementBindVariableInterceptor.class.getName()); - private final MetaObject getBindValue = new MetaObject("__getBindValue"); + private final MetaObject getBindValue = new MetaObject("__getBindValue"); @Override public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { @@ -23,9 +25,13 @@ public class PreparedStatementBindVariableInterceptor implements StaticAfterInte if (Trace.getCurrentTraceId() == null) { return; } - List bindList = getBindValue.invoke(target); - String index = StringUtils.toString(args[0]); + Map bindList = getBindValue.invoke(target); + Integer index = NumberUtils.toInteger(args[0]); + if(index == null) { + // 어딘가 잘못됨. + return; + } String value = StringUtils.toString(args[1]); - bindList.add(index + ":" + value); + bindList.put(index, value); } } diff --git a/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementMethodInterceptor.java b/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementMethodInterceptor.java index d0a6929bb..e71c75fac 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementMethodInterceptor.java +++ b/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementMethodInterceptor.java @@ -1,9 +1,7 @@ package com.profiler.modifier.db.mysql.interceptors; -import com.mysql.jdbc.PreparedStatement; import com.profiler.context.Annotation; import com.profiler.context.Trace; -import com.profiler.interceptor.StaticAfterInterceptor; import com.profiler.interceptor.StaticAroundInterceptor; import com.profiler.util.InterceptorUtils; import com.profiler.util.MetaObject; @@ -19,8 +17,8 @@ public class PreparedStatementMethodInterceptor implements StaticAroundIntercept private final MetaObject getSql = new MetaObject("__getSql"); private final MetaObject getUrl = new MetaObject("__getUrl"); - private final MetaObject> getBindValue = new MetaObject("__getBindValue"); - private final MetaObject> setBindValue = new MetaObject("__setBindValue"); + private final MetaObject getBindValue = new MetaObject("__getBindValue"); + private final MetaObject setBindValue = new MetaObject("__setBindValue"); @Override @@ -39,7 +37,8 @@ public class PreparedStatementMethodInterceptor implements StaticAroundIntercept String sql = getSql.invoke(target); Trace.recordAttibute("PreparedStatement", sql); - List bindValue = getBindValue.invoke(target); + Map bindValue = getBindValue.invoke(target); + String bindString = toBindVariable(bindValue); Trace.recordAttibute("BindValue", bindValue.toString()); setBindValue.invoke(target, Collections.synchronizedList(new LinkedList())); @@ -52,6 +51,14 @@ public class PreparedStatementMethodInterceptor implements StaticAroundIntercept } + private String toBindVariable(Map bindValue) { + StringBuilder sb = new StringBuilder(); + for(int i =0; i iLimit) { + iMax = iLimit; + } + if (iMax == -1) { + if (bytes.length == 0) { + return "[]"; + } else { + return "[...(" + bytes.length + ")]"; + } + } + + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; ; i++) { + sb.append(bytes[i]); + if (i == iMax) { + if (iMax < iLimit) { + return sb.append(']').toString(); + } else { + if (i > 0) { + + } + sb.append(", "); + sb.append("...("); + sb.append(bytes.length); + sb.append(")]"); + return sb.toString(); + } + } + sb.append(", "); + } + } + + +} diff --git a/src/main/java/com/profiler/util/NumberUtils.java b/src/main/java/com/profiler/util/NumberUtils.java index 2ed62066e..01dc62d8d 100644 --- a/src/main/java/com/profiler/util/NumberUtils.java +++ b/src/main/java/com/profiler/util/NumberUtils.java @@ -23,4 +23,15 @@ public class NumberUtils { } } + public static Integer toInteger(Object integer) { + if(integer == null) { + return null; + } + if (integer instanceof Integer) { + return (Integer)integer; + } else { + return null; + } + } + } diff --git a/src/main/java/com/profiler/util/StringUtils.java b/src/main/java/com/profiler/util/StringUtils.java index b7f5e9563..380279a54 100644 --- a/src/main/java/com/profiler/util/StringUtils.java +++ b/src/main/java/com/profiler/util/StringUtils.java @@ -12,4 +12,24 @@ public class StringUtils { } return object.toString(); } + + public static String drop(String str) { + return drop(str, 20, getDropString(str)); + } + + public static String getDropString(String str) { + return "...(" + str.length() + ")"; + } + + public static String drop(String str, int length, String padding) { + if (str == null) { + return "null"; + } + StringBuilder buffer = new StringBuilder(length + 10); + if(str.length() > length) { + buffer.append(str.substring(0, length)); + buffer.append(padding); + } + return buffer.toString(); + } } diff --git a/src/main/java/com/profiler/util/bindvalue/BindValueConverter.java b/src/main/java/com/profiler/util/bindvalue/BindValueConverter.java index 753604a69..7d5c7d502 100644 --- a/src/main/java/com/profiler/util/bindvalue/BindValueConverter.java +++ b/src/main/java/com/profiler/util/bindvalue/BindValueConverter.java @@ -1,6 +1,6 @@ package com.profiler.util.bindvalue; -import com.profiler.util.StringUtils; +import com.profiler.util.bindvalue.converter.*; import java.util.HashMap; import java.util.Map; @@ -8,6 +8,81 @@ import java.util.Map; public class BindValueConverter { public static final Map convertermap = new HashMap() ; + private void register() { + simpleType(); + classNameType(); + + // null argument 가 3개인것도 있음. + convertermap.put("setNull", new NullTypeConterver()); + + BytesConverter bytesConverter = new BytesConverter(); + convertermap.put("setBytes", bytesConverter); + + + // setObject + convertermap.put("setObject", null); + } + + private void classNameType() { + // className 데이터를 까볼수 없는 객체의 경우 class명으로 치환 + ClassNameConverter classNameConverter = new ClassNameConverter(); + // 3개짜리 존재 + convertermap.put("setAsciiStream", classNameConverter); + convertermap.put("setUnicodeStream", classNameConverter); + convertermap.put("setBinaryStream", classNameConverter); + + //3개 짜리 존재 + convertermap.put("setBlob", classNameConverter); + //3개 짜리 존재 + convertermap.put("setClob", classNameConverter); + convertermap.put("setArray", classNameConverter); + convertermap.put("setNCharacterStream", classNameConverter); + + // 3개 짜리 존재 + convertermap.put("setNClob", classNameConverter); + + + convertermap.put("setCharacterStream", classNameConverter); + convertermap.put("setSQLXML", classNameConverter); + convertermap.put("setSQLXML", classNameConverter); + convertermap.put("setSQLXML", classNameConverter); + convertermap.put("setSQLXML", classNameConverter); + + } + + private void simpleType() { + + SimpleTypeConverter simpleTypeConverter = new SimpleTypeConverter(); + convertermap.put("setByte", simpleTypeConverter); + convertermap.put("setShort", simpleTypeConverter); + convertermap.put("setInt", simpleTypeConverter); + convertermap.put("setLong", simpleTypeConverter); + convertermap.put("setFloat", simpleTypeConverter); + convertermap.put("setDouble", simpleTypeConverter); + convertermap.put("setBigDecimal", simpleTypeConverter); + convertermap.put("setString", simpleTypeConverter); + convertermap.put("setDate", simpleTypeConverter); + + // argument 가 3개 가능. + convertermap.put("setTime", simpleTypeConverter); + //convertermap.put("setTime", simpleTypeConverter); + + // argument 가 3개 가능 + convertermap.put("setTimestamp", simpleTypeConverter); + //convertermap.put("setTimestamp", simpleTypeConverter); + + + // 문자열로 치환 가능할것으로 보임. + convertermap.put("setURL", simpleTypeConverter); + // ref도 문자열로 치환 가능할것으로 보임 + convertermap.put("setRef", simpleTypeConverter); + convertermap.put("setNString", simpleTypeConverter); + + + + } + + public String bindValueToString(String methodName, Object[] args) { Converter converter = convertermap.get(methodName); if (converter == null) { @@ -16,26 +91,6 @@ public class BindValueConverter { return converter.convert(args); } - interface Converter { - String convert(Object[] args); - } - class CommonConverter implements Converter { - @Override - public String convert(Object[] args) { - if(args == null) { - return "null"; - } - if (args.length == 1) { - return StringUtils.toString(args[1]); - } - else if(args.length == 2) { - return StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]); - } - else if(args.length == 3) { - return StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]); - } - return "error"; - } - } + } diff --git a/src/main/java/com/profiler/util/bindvalue/converter/BytesConverter.java b/src/main/java/com/profiler/util/bindvalue/converter/BytesConverter.java new file mode 100644 index 000000000..8886e41bc --- /dev/null +++ b/src/main/java/com/profiler/util/bindvalue/converter/BytesConverter.java @@ -0,0 +1,23 @@ +package com.profiler.util.bindvalue.converter; + +import com.profiler.util.ArrayUtils; +import com.profiler.util.StringUtils; + + +public class BytesConverter implements Converter { + @Override + public String convert(Object[] args) { + if (args == null) { + return "null"; + } + if (args.length == 2) { + byte[] bytes = (byte[]) args[1]; + if (bytes == null) { + return "null"; + } else { + return StringUtils.drop(ArrayUtils.dropToString(bytes)); + } + } + return "error"; + } +} diff --git a/src/main/java/com/profiler/util/bindvalue/converter/ClassNameConverter.java b/src/main/java/com/profiler/util/bindvalue/converter/ClassNameConverter.java new file mode 100644 index 000000000..1187df1bd --- /dev/null +++ b/src/main/java/com/profiler/util/bindvalue/converter/ClassNameConverter.java @@ -0,0 +1,28 @@ +package com.profiler.util.bindvalue.converter; + +import com.profiler.util.StringUtils; + +public class ClassNameConverter implements Converter { + @Override + public String convert(Object[] args) { + if (args == null) { + return "null"; + } + if (args.length == 2) { + String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(getClassName(args[1])); + return StringUtils.drop(str); + } else if (args.length == 3) { + // TODO 3일때 추가 처리? + String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(getClassName(args[1])); + return StringUtils.drop(str); + } + return "error"; + } + + private Object getClassName(Object args) { + if (args == null) { + return "null"; + } + return args.getClass().getName(); + } +} diff --git a/src/main/java/com/profiler/util/bindvalue/converter/Converter.java b/src/main/java/com/profiler/util/bindvalue/converter/Converter.java new file mode 100644 index 000000000..07310212a --- /dev/null +++ b/src/main/java/com/profiler/util/bindvalue/converter/Converter.java @@ -0,0 +1,5 @@ +package com.profiler.util.bindvalue.converter; + +public interface Converter { + String convert(Object[] args); +} diff --git a/src/main/java/com/profiler/util/bindvalue/converter/NullTypeConterver.java b/src/main/java/com/profiler/util/bindvalue/converter/NullTypeConterver.java new file mode 100644 index 000000000..f4b7e10d7 --- /dev/null +++ b/src/main/java/com/profiler/util/bindvalue/converter/NullTypeConterver.java @@ -0,0 +1,9 @@ +package com.profiler.util.bindvalue.converter; + +public class NullTypeConterver implements Converter { + + @Override + public String convert(Object[] args) { + return "null"; + } +} diff --git a/src/main/java/com/profiler/util/bindvalue/converter/SimpleTypeConverter.java b/src/main/java/com/profiler/util/bindvalue/converter/SimpleTypeConverter.java new file mode 100644 index 000000000..194764a30 --- /dev/null +++ b/src/main/java/com/profiler/util/bindvalue/converter/SimpleTypeConverter.java @@ -0,0 +1,21 @@ +package com.profiler.util.bindvalue.converter; + +import com.profiler.util.StringUtils; + +public class SimpleTypeConverter implements Converter { + @Override + public String convert(Object[] args) { + if (args == null) { + return "null"; + } + if (args.length == 2) { + String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]); + return StringUtils.drop(str); + } else if (args.length == 3) { + // TODO 3일때 추가 처리? + String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]); + return StringUtils.drop(str); + } + return "error"; + } +} diff --git a/src/test/java/com/profiler/util/ArrayUtilsTest.java b/src/test/java/com/profiler/util/ArrayUtilsTest.java new file mode 100644 index 000000000..c58503999 --- /dev/null +++ b/src/test/java/com/profiler/util/ArrayUtilsTest.java @@ -0,0 +1,31 @@ +package com.profiler.util; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.logging.Logger; + +public class ArrayUtilsTest { + private final Logger logger = Logger.getLogger(ArrayUtilsTest.class.getName()); + @Test + public void toStringTest() { + byte[] bytes = new byte[] {1, 2, 3, 4}; + + String small = ArrayUtils.dropToString(bytes, 3); + logger.info(small); + Assert.assertEquals("[1, 2, 3, ...(4)]", small); + + String large = ArrayUtils.dropToString(bytes, 11); + logger.info(large); + Assert.assertEquals("[1, 2, 3, 4]", large); + + String one = ArrayUtils.dropToString(bytes, 1); + logger.info(one); + Assert.assertEquals("[1, ...(4)]", one); + + String zero = ArrayUtils.dropToString(bytes, 0); + logger.info(zero); + Assert.assertEquals("[...(4)]", zero); + } +} diff --git a/src/test/java/com/profiler/util/bindvalue/BindValueConverterTest.java b/src/test/java/com/profiler/util/bindvalue/BindValueConverterTest.java new file mode 100644 index 000000000..f957bbf48 --- /dev/null +++ b/src/test/java/com/profiler/util/bindvalue/BindValueConverterTest.java @@ -0,0 +1,18 @@ +package com.profiler.util.bindvalue; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Date; + +public class BindValueConverterTest { + @Test + public void testBindValueToString() throws Exception { + Date d = new Date(); + System.out.println(d); + + byte[] bytes = new byte[] {1, 2, 4}; + String s = Arrays.toString(bytes); + System.out.println(s); + } +}