From b8c73bfdef437aaee5a8a674f87c51af0f8dfd23 Mon Sep 17 00:00:00 2001 From: Woonduk Kang Date: Fri, 16 Nov 2012 13:03:57 +0000 Subject: [PATCH] =?UTF-8?q?[=EA=B0=95=EC=9A=B4=EB=8D=95]=20[LUCYSUS-1744]?= =?UTF-8?q?=20span=EC=9D=98=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20api?= =?UTF-8?q?=20=EB=A5=BC=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=B4=201=EC=B0=A8?= =?UTF-8?q?=20=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EC=A0=95=EC=A0=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20api=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=88=98=EC=A7=91?= =?UTF-8?q?=EB=B0=9B=EC=9D=84=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=ED=95=A8.=20=20method=EC=9D=98=20parameter?= =?UTF-8?q?=EC=9D=98=20variablename=EC=9D=84=20=ED=9A=8D=EB=93=9D=ED=95=A0?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=95=A8.=20=EB=8B=A8=20=EB=94=94=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=BB=B4=ED=8C=8C=EC=9D=BC=20=EC=8B=9C=EB=A7=8C=20=EA=B0=84?= =?UTF-8?q?=EB=8A=A5=ED=95=A8.?= 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@871 84d0f5b1-2673-498c-a247-62c4ff18d310 --- src/main/java/com/profiler/SystemMonitor.java | 3 +- .../java/com/profiler/context/StackFrame.java | 11 + src/main/java/com/profiler/context/Trace.java | 9 +- .../ByteCodeMethodDescriptorSupport.java | 8 + .../interceptor/DefaultMethodDescriptor.java | 106 ++++ .../interceptor/MethodDescriptor.java | 27 + .../interceptor/bci/JavaAssistClass.java | 509 +++++++++--------- ...paredStatementExecuteQueryInterceptor.java | 11 +- .../mysql/MySQLPreparedStatementModifier.java | 9 +- .../modifier/db/util/DatabaseInfo.java | 18 +- .../modifier/db/util/JDBCUrlParser.java | 17 +- .../com/profiler/util/JavaAssistUtils.java | 165 +++++- .../modifier/db/util/JDBCUrlParserTest.java | 14 +- .../profiler/util/JavaAssistUtilsTest.java | 41 +- 14 files changed, 657 insertions(+), 291 deletions(-) create mode 100644 src/main/java/com/profiler/interceptor/ByteCodeMethodDescriptorSupport.java create mode 100644 src/main/java/com/profiler/interceptor/DefaultMethodDescriptor.java create mode 100644 src/main/java/com/profiler/interceptor/MethodDescriptor.java diff --git a/src/main/java/com/profiler/SystemMonitor.java b/src/main/java/com/profiler/SystemMonitor.java index 973a74212..f27efb59c 100644 --- a/src/main/java/com/profiler/SystemMonitor.java +++ b/src/main/java/com/profiler/SystemMonitor.java @@ -68,9 +68,8 @@ public class SystemMonitor { } public void run() { - JVMInfoThriftDTO jvmInfo = new JVMInfoThriftDTO(); try { - jvmInfo = new JVMInfoThriftDTO(); + JVMInfoThriftDTO jvmInfo = new JVMInfoThriftDTO(); jvmInfo.setAgentId(Agent.getInstance().getAgentId()); jvmInfo.setDataTime(System.currentTimeMillis()); diff --git a/src/main/java/com/profiler/context/StackFrame.java b/src/main/java/com/profiler/context/StackFrame.java index 33dc0028c..04462d694 100644 --- a/src/main/java/com/profiler/context/StackFrame.java +++ b/src/main/java/com/profiler/context/StackFrame.java @@ -49,4 +49,15 @@ public class StackFrame { public Span getSpan() { return span; } + + public void attachObject(Object object) { + } + + public Object getAttachObject(Object object) { + return null; + } + + public Object detachObject() { + return null; + } } diff --git a/src/main/java/com/profiler/context/Trace.java b/src/main/java/com/profiler/context/Trace.java index 4c8707506..b44d76506 100644 --- a/src/main/java/com/profiler/context/Trace.java +++ b/src/main/java/com/profiler/context/Trace.java @@ -90,10 +90,15 @@ public final class Trace { } public void markBeforeTime() { - StackFrame context = getCurrentStackFrame(); - context.markBeforeTime(); + StackFrame stackFrame = getCurrentStackFrame(); + stackFrame.markBeforeTime(); } +// public void attachObject(Object object) { +// StackFrame stackFrame = getCurrentStackFrame(); +// stackFrame.attachObject(object); +// } + public long afterTime() { StackFrame context = getCurrentStackFrame(); return context.afterTime(); diff --git a/src/main/java/com/profiler/interceptor/ByteCodeMethodDescriptorSupport.java b/src/main/java/com/profiler/interceptor/ByteCodeMethodDescriptorSupport.java new file mode 100644 index 000000000..90428cea5 --- /dev/null +++ b/src/main/java/com/profiler/interceptor/ByteCodeMethodDescriptorSupport.java @@ -0,0 +1,8 @@ +package com.profiler.interceptor; + +/** + * precompile level의 methodDescriptor를 setting 받을수 있게 한다. + */ +public interface ByteCodeMethodDescriptorSupport { + void setMethodDescriptor(MethodDescriptor descriptor); +} diff --git a/src/main/java/com/profiler/interceptor/DefaultMethodDescriptor.java b/src/main/java/com/profiler/interceptor/DefaultMethodDescriptor.java new file mode 100644 index 000000000..855d409e1 --- /dev/null +++ b/src/main/java/com/profiler/interceptor/DefaultMethodDescriptor.java @@ -0,0 +1,106 @@ +package com.profiler.interceptor; + +/** + * + */ +public class DefaultMethodDescriptor implements MethodDescriptor { + private String className; + private String simpleClassName; + + private String methodName; + + private String[] parameterTypes; + private String[] simpleParameterTypes; + + private String[] parameterVariableName; + + + private String parameterDescriptor; + + + private String simpleParameterDescriptor; + + private int lineNumber; + + + public DefaultMethodDescriptor() { + } + + public String getParameterDescriptor() { + return parameterDescriptor; + } + + public void setParameterDescriptor(String parameterDescriptor) { + this.parameterDescriptor = parameterDescriptor; + } + + public String getSimpleParameterDescriptor() { + return simpleParameterDescriptor; + } + + public void setSimpleParameterDescriptor(String simpleParameterDescriptor) { + this.simpleParameterDescriptor = simpleParameterDescriptor; + } + + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public void setParameterTypes(String[] parameterTypes) { + this.parameterTypes = parameterTypes; + } + + public void setParameterVariableName(String[] parameterVariableName) { + this.parameterVariableName = parameterVariableName; + } + + public void setLineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + + @Override + public String getMethodName() { + return methodName; + } + + @Override + public String getClassName() { + return className; + } + + @Override + public String getSimpleClassName() { + return simpleClassName; + } + + public void setSimpleClassName(String simpleClassName) { + this.simpleClassName = simpleClassName; + } + + public void setClassName(String className) { + this.className = className; + } + + @Override + public String[] getParameterTypes() { + return parameterTypes; + } + + @Override + public String[] getParameterVariableName() { + return parameterVariableName; + } + + public String[] getSimpleParameterTypes() { + return simpleParameterTypes; + } + + public void setSimpleParameterTypes(String[] simpleParameterTypes) { + this.simpleParameterTypes = simpleParameterTypes; + } + + public int getLineNumber() { + return lineNumber; + } +} diff --git a/src/main/java/com/profiler/interceptor/MethodDescriptor.java b/src/main/java/com/profiler/interceptor/MethodDescriptor.java new file mode 100644 index 000000000..51ea3bdef --- /dev/null +++ b/src/main/java/com/profiler/interceptor/MethodDescriptor.java @@ -0,0 +1,27 @@ +package com.profiler.interceptor; + +import java.lang.reflect.Method; + +/** + * + */ +public interface MethodDescriptor { + String getMethodName(); + + String getClassName(); + + String getSimpleClassName(); + + String[] getParameterTypes(); + + String[] getSimpleParameterTypes(); + + String[] getParameterVariableName(); + + + String getParameterDescriptor(); + + String getSimpleParameterDescriptor(); + + int getLineNumber(); +} diff --git a/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java b/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java index 262a653fa..de81fb112 100644 --- a/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java +++ b/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java @@ -4,87 +4,81 @@ import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.interceptor.*; import com.profiler.util.JavaAssistUtils; import javassist.*; -import com.profiler.interceptor.Interceptor; -import com.profiler.interceptor.InterceptorRegistry; -import com.profiler.interceptor.LoggingInterceptor; -import com.profiler.interceptor.StaticAfterInterceptor; -import com.profiler.interceptor.StaticAroundInterceptor; -import com.profiler.interceptor.StaticBeforeInterceptor; - public class JavaAssistClass implements InstrumentClass { - private final Logger logger = Logger.getLogger(this.getClass().getName()); + private final Logger logger = Logger.getLogger(this.getClass().getName()); - private JavaAssistByteCodeInstrumentor instrumentor; - private CtClass ctClass; + private JavaAssistByteCodeInstrumentor instrumentor; + private CtClass ctClass; - public JavaAssistClass(JavaAssistByteCodeInstrumentor instrumentor, CtClass ctClass) { - this.instrumentor = instrumentor; - this.ctClass = ctClass; - } + public JavaAssistClass(JavaAssistByteCodeInstrumentor instrumentor, CtClass ctClass) { + this.instrumentor = instrumentor; + this.ctClass = ctClass; + } - public CtClass getCtClass() { - return ctClass; - } + public CtClass getCtClass() { + return ctClass; + } - @Override - public boolean insertCodeBeforeConstructor(String[] args, String code) { - try { - CtConstructor constructor = getConstructor(args); - constructor.insertBefore(code); - return true; - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return false; - } - } + @Override + public boolean insertCodeBeforeConstructor(String[] args, String code) { + try { + CtConstructor constructor = getConstructor(args); + constructor.insertBefore(code); + return true; + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return false; + } + } - @Override - public boolean insertCodeAfterConstructor(String[] args, String code) { - try { - CtConstructor constructor = getConstructor(args); - constructor.insertAfter(code); - return true; - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return false; - } - } + @Override + public boolean insertCodeAfterConstructor(String[] args, String code) { + try { + CtConstructor constructor = getConstructor(args); + constructor.insertAfter(code); + return true; + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return false; + } + } - @Override - public boolean insertCodeBeforeMethod(String methodName, String[] args, String code) { - try { - CtMethod method = getMethod(methodName, args); - method.insertBefore(code); - return true; - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return false; - } - } + @Override + public boolean insertCodeBeforeMethod(String methodName, String[] args, String code) { + try { + CtMethod method = getMethod(methodName, args); + method.insertBefore(code); + return true; + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return false; + } + } - @Override - public boolean insertCodeAfterMethod(String methodName, String[] args, String code) { - try { - CtMethod method = getMethod(methodName, args); - method.insertAfter(code); - return true; - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return false; - } - } + @Override + public boolean insertCodeAfterMethod(String methodName, String[] args, String code) { + try { + CtMethod method = getMethod(methodName, args); + method.insertAfter(code); + return true; + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return false; + } + } public void addTraceVariable(String variableName, String setterName, String getterName, String variableType, String initValue) throws InstrumentException { addTraceVariable0(variableName, setterName, getterName, variableType, initValue); @@ -118,34 +112,34 @@ public class JavaAssistClass implements InstrumentClass { } } - public int addConstructorInterceptor(String[] args, Interceptor interceptor) throws InstrumentException, NotFoundInstrumentException { + public int addConstructorInterceptor(String[] args, Interceptor interceptor) throws InstrumentException, NotFoundInstrumentException { if (interceptor == null) { - throw new IllegalArgumentException("interceptor is null"); + throw new IllegalArgumentException("interceptor is null"); } return addInterceptor0(null, args, interceptor, -1, Type.auto); } @Override - public int addInterceptor(String methodName, String[] args, Interceptor interceptor) throws InstrumentException, NotFoundInstrumentException { + public int addInterceptor(String methodName, String[] args, Interceptor interceptor) throws InstrumentException, NotFoundInstrumentException { if (interceptor == null) { - throw new IllegalArgumentException("interceptor is null"); + throw new IllegalArgumentException("interceptor is null"); } - return addInterceptor0(methodName, args, interceptor, -1, Type.auto); - } + return addInterceptor0(methodName, args, interceptor, -1, Type.auto); + } @Override public int reuseInterceptor(String methodName, String[] args, int interceptorId) throws InstrumentException, NotFoundInstrumentException { return addInterceptor0(methodName, args, null, interceptorId, Type.auto); } - @Override - public int addInterceptor(String methodName, String[] args, Interceptor interceptor, Type type) throws InstrumentException, NotFoundInstrumentException { + @Override + public int addInterceptor(String methodName, String[] args, Interceptor interceptor, Type type) throws InstrumentException, NotFoundInstrumentException { if (interceptor == null) { - throw new IllegalArgumentException("interceptor is null"); + throw new IllegalArgumentException("interceptor is null"); } return addInterceptor0(methodName, args, interceptor, -1, type); - } + } private CtBehavior getBehavior(String methodName, String[] args) throws NotFoundException { if (methodName == null) { @@ -154,7 +148,7 @@ public class JavaAssistClass implements InstrumentClass { return getMethod(methodName, args); } - private int addInterceptor0(String methodName, String[] args, Interceptor interceptor, int interceptorId,Type type) throws InstrumentException, NotFoundInstrumentException { + private int addInterceptor0(String methodName, String[] args, Interceptor interceptor, int interceptorId, Type type) throws InstrumentException, NotFoundInstrumentException { CtBehavior behavior = null; try { behavior = getBehavior(methodName, args); @@ -169,9 +163,13 @@ public class JavaAssistClass implements InstrumentClass { try { if (interceptor != null) { interceptorId = InterceptorRegistry.addInterceptor(interceptor); + if (interceptor instanceof ByteCodeMethodDescriptorSupport) { + setMethodDescriptor(behavior, (ByteCodeMethodDescriptorSupport) interceptor); + } } else { interceptor = InterceptorRegistry.getInterceptor(interceptorId); } + if (type == Type.auto) { if (interceptor instanceof StaticAroundInterceptor) { addStaticAroundInterceptor(methodName, interceptorId, behavior); @@ -191,96 +189,126 @@ public class JavaAssistClass implements InstrumentClass { } else { throw new IllegalArgumentException("unsupported"); } - return interceptorId; + return interceptorId; } catch (NotFoundException e) { throw new InstrumentException(interceptor.getClass().getSimpleName() + " add fail. Cause:" + e.getMessage(), e); } catch (CannotCompileException e) { - throw new InstrumentException(interceptor.getClass().getSimpleName() + "add fail. Cause:" + e.getMessage(), e); + throw new InstrumentException(interceptor.getClass().getSimpleName() + "add fail. Cause:" + e.getMessage(), e); } } - private void addStaticAroundInterceptor(String methodName, int id, CtBehavior method) throws NotFoundException, CannotCompileException { - addStaticBeforeInterceptor(methodName, id, method); - addStaticAfterInterceptor(methodName, id, method); - } + private void setMethodDescriptor(CtBehavior behavior, ByteCodeMethodDescriptorSupport interceptor) throws NotFoundException { + DefaultMethodDescriptor methodDescriptor = new DefaultMethodDescriptor(); - private void addStaticAfterInterceptor(String methodName, int id, CtBehavior behavior) throws NotFoundException, CannotCompileException { + String methodName = behavior.getName(); + methodDescriptor.setMethodName(methodName); + + methodDescriptor.setClassName(ctClass.getName()); + methodDescriptor.setSimpleClassName(ctClass.getSimpleName()); + + CtClass[] parameterTypes = behavior.getParameterTypes(); + String[] parameterType = JavaAssistUtils.getParameterType(parameterTypes); + methodDescriptor.setParameterTypes(parameterType); + + String[] parameterSimpleType = JavaAssistUtils.getParameterSimpleType(parameterTypes); + methodDescriptor.setSimpleParameterTypes(parameterSimpleType); + + String[] parameterVariableName = JavaAssistUtils.getParameterVariableName(behavior); + methodDescriptor.setParameterVariableName(parameterVariableName); + + int lineNumber = JavaAssistUtils.getLineNumber(behavior); + methodDescriptor.setLineNumber(lineNumber); + + String parameterDescription = JavaAssistUtils.mergeParameterVariableNameDescription(parameterType, parameterVariableName); + methodDescriptor.setParameterDescriptor(parameterDescription); + + String simpleParameterDescription = JavaAssistUtils.mergeParameterVariableNameDescription(parameterType, parameterVariableName); + methodDescriptor.setSimpleParameterDescriptor(simpleParameterDescription); + + interceptor.setMethodDescriptor(methodDescriptor); + } + + private void addStaticAroundInterceptor(String methodName, int id, CtBehavior method) throws NotFoundException, CannotCompileException { + addStaticBeforeInterceptor(methodName, id, method); + addStaticAfterInterceptor(methodName, id, method); + } + + private void addStaticAfterInterceptor(String methodName, int id, CtBehavior behavior) throws NotFoundException, CannotCompileException { String target = getTarget(behavior); - String returnType = getReturnType(behavior); + String returnType = getReturnType(behavior); String parameterTypeString = JavaAssistUtils.getParameterDescription(behavior.getParameterTypes()); String parameter = getParameter(behavior); CodeBuilder after = new CodeBuilder(); - after.begin(); + after.begin(); after.format(" %1$s interceptor = (%1$s) com.profiler.interceptor.InterceptorRegistry.getInterceptor(%2$d);", StaticAfterInterceptor.class.getName(), id); - after.format(" interceptor.after(%1$s, \"%2$s\", \"%3$s\", \"%4$s\", %5$s, %6$s);", target, ctClass.getName(), methodName, parameterTypeString, parameter,returnType); - after.end(); - String buildAfter = after.toString(); - if (logger.isLoggable(Level.INFO)) { - logger.info("addStaticAfterInterceptor after behavior:" + behavior.getLongName() + " code:" + buildAfter); - } - behavior.insertAfter(buildAfter); + after.format(" interceptor.after(%1$s, \"%2$s\", \"%3$s\", \"%4$s\", %5$s, %6$s);", target, ctClass.getName(), methodName, parameterTypeString, parameter, returnType); + after.end(); + String buildAfter = after.toString(); + if (logger.isLoggable(Level.INFO)) { + logger.info("addStaticAfterInterceptor after behavior:" + behavior.getLongName() + " code:" + buildAfter); + } + behavior.insertAfter(buildAfter); - CodeBuilder catchCode = new CodeBuilder(); - catchCode.begin(); + CodeBuilder catchCode = new CodeBuilder(); + catchCode.begin(); catchCode.format(" %1$s interceptor = (%1$s) com.profiler.interceptor.InterceptorRegistry.getInterceptor(%2$d);", StaticAfterInterceptor.class.getName(), id); catchCode.format(" interceptor.after(%1$s, \"%2$s\", \"%3$s\", \"%4$s\", %5$s, $e);", target, ctClass.getName(), methodName, parameterTypeString, parameter); - catchCode.append(" throw $e;"); - catchCode.end(); - String buildCatch = catchCode.toString(); - if (logger.isLoggable(Level.INFO)) { - logger.info("addStaticAfterInterceptor catch behavior:" + behavior.getLongName() + " code:" + buildCatch); - } - CtClass th = instrumentor.getClassPool().get("java.lang.Throwable"); - behavior.addCatch(buildCatch, th); + catchCode.append(" throw $e;"); + catchCode.end(); + String buildCatch = catchCode.toString(); + if (logger.isLoggable(Level.INFO)) { + logger.info("addStaticAfterInterceptor catch behavior:" + behavior.getLongName() + " code:" + buildCatch); + } + CtClass th = instrumentor.getClassPool().get("java.lang.Throwable"); + behavior.addCatch(buildCatch, th); - } + } - private String getTarget(CtBehavior behavior) { - boolean staticMethod = JavaAssistUtils.isStaticBehavior(behavior); - if (staticMethod) { - return "null"; - } else { - return "this"; - } - } + private String getTarget(CtBehavior behavior) { + boolean staticMethod = JavaAssistUtils.isStaticBehavior(behavior); + if (staticMethod) { + return "null"; + } else { + return "this"; + } + } - public String getReturnType(CtBehavior behavior) throws NotFoundException { - if (behavior instanceof CtMethod) { - CtClass returnType = ((CtMethod) behavior).getReturnType(); - if (CtClass.voidType == returnType) { - return "null"; - } - } - return "($w)$_"; - } + public String getReturnType(CtBehavior behavior) throws NotFoundException { + if (behavior instanceof CtMethod) { + CtClass returnType = ((CtMethod) behavior).getReturnType(); + if (CtClass.voidType == returnType) { + return "null"; + } + } + return "($w)$_"; + } - - private void addStaticBeforeInterceptor(String methodName, int id, CtBehavior behavior) throws CannotCompileException, NotFoundException { - String target = getTarget(behavior); + private void addStaticBeforeInterceptor(String methodName, int id, CtBehavior behavior) throws CannotCompileException, NotFoundException { + String target = getTarget(behavior); // 인터셉터 호출시 최대한 연산량을 줄이기 위해서 정보는 가능한 정적 데이터로 생성한다. String parameterDescription = JavaAssistUtils.getParameterDescription(behavior.getParameterTypes()); String parameter = getParameter(behavior); CodeBuilder code = new CodeBuilder(); - code.begin(); + code.begin(); code.format(" %1$s interceptor = (%1$s) com.profiler.interceptor.InterceptorRegistry.getInterceptor(%2$d);", StaticBeforeInterceptor.class.getName(), id); code.format(" interceptor.before(%1$s, \"%2$s\", \"%3$s\", \"%4$s\", %5$s);", target, ctClass.getName(), methodName, parameterDescription, parameter); - code.end(); - String buildBefore = code.toString(); - if (logger.isLoggable(Level.INFO)) { - logger.info("addStaticBeforeInterceptor catch behavior:" + behavior.getLongName() + " code:" + buildBefore); - } + code.end(); + String buildBefore = code.toString(); + if (logger.isLoggable(Level.INFO)) { + logger.info("addStaticBeforeInterceptor catch behavior:" + behavior.getLongName() + " code:" + buildBefore); + } - if (behavior instanceof CtConstructor) { - ((CtConstructor) behavior).insertBeforeBody(buildBefore); - } else { - behavior.insertBefore(buildBefore); - } - } + if (behavior instanceof CtConstructor) { + ((CtConstructor) behavior).insertBeforeBody(buildBefore); + } else { + behavior.insertBefore(buildBefore); + } + } private String getParameter(CtBehavior behavior) throws NotFoundException { CtClass[] parameterTypes = behavior.getParameterTypes(); @@ -291,123 +319,122 @@ public class JavaAssistClass implements InstrumentClass { } public boolean addDebugLogBeforeAfterMethod() { - String className = this.ctClass.getName(); - LoggingInterceptor loggingInterceptor = new LoggingInterceptor(className); - int id = InterceptorRegistry.addInterceptor(loggingInterceptor); - try { - CtClass cc = this.instrumentor.getClassPool().get(className); - CtMethod[] methods = cc.getDeclaredMethods(); + String className = this.ctClass.getName(); + LoggingInterceptor loggingInterceptor = new LoggingInterceptor(className); + int id = InterceptorRegistry.addInterceptor(loggingInterceptor); + try { + CtClass cc = this.instrumentor.getClassPool().get(className); + CtMethod[] methods = cc.getDeclaredMethods(); - for (CtMethod method : methods) { - if (method.isEmpty()) { - if (logger.isLoggable(Level.FINE)) { - logger.fine(method.getLongName() + " is empty."); - } - continue; - } - String methodName = method.getName(); + for (CtMethod method : methods) { + if (method.isEmpty()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine(method.getLongName() + " is empty."); + } + continue; + } + String methodName = method.getName(); - // TODO method의 prameter type을 interceptor에 별도 추가해야 될것으로 보임. - String params = getParamsToString(method.getParameterTypes()); - addStaticAroundInterceptor(methodName, id, method); - } - return true; - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - } - return false; - } + // TODO method의 prameter type을 interceptor에 별도 추가해야 될것으로 보임. + String params = getParamsToString(method.getParameterTypes()); + addStaticAroundInterceptor(methodName, id, method); + } + return true; + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + } + return false; + } - /** - * 제대로 동작안함 다시 봐야 될것 같음. 생성자일경우의 bytecode 수정시 에러가 남. - * - * @return - */ - @Deprecated - public boolean addDebugLogBeforeAfterConstructor() { - String className = this.ctClass.getName(); - LoggingInterceptor loggingInterceptor = new LoggingInterceptor(className); - int id = InterceptorRegistry.addInterceptor(loggingInterceptor); - try { - CtClass cc = this.instrumentor.getClassPool().get(className); - CtConstructor[] constructors = cc.getConstructors(); + /** + * 제대로 동작안함 다시 봐야 될것 같음. 생성자일경우의 bytecode 수정시 에러가 남. + * + * @return + */ + @Deprecated + public boolean addDebugLogBeforeAfterConstructor() { + String className = this.ctClass.getName(); + LoggingInterceptor loggingInterceptor = new LoggingInterceptor(className); + int id = InterceptorRegistry.addInterceptor(loggingInterceptor); + try { + CtClass cc = this.instrumentor.getClassPool().get(className); + CtConstructor[] constructors = cc.getConstructors(); - for (CtConstructor constructor : constructors) { - if (constructor.isEmpty()) { - if (logger.isLoggable(Level.FINE)) { - logger.fine(constructor.getLongName() + " is empty."); - } - continue; - } - String constructorName = constructor.getName(); - String params = getParamsToString(constructor.getParameterTypes()); + for (CtConstructor constructor : constructors) { + if (constructor.isEmpty()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine(constructor.getLongName() + " is empty."); + } + continue; + } + String constructorName = constructor.getName(); + String params = getParamsToString(constructor.getParameterTypes()); - // constructor.insertAfter("{System.out.println(\"*****" + - // constructorName + " Constructor:Param=(" + params + - // ") is finished. \" + $args);}"); - // constructor.addCatch("{System.out.println(\"*****" + - // constructorName + " Constructor:Param=(" + params + - // ") is finished.\"); throw $e; }" - // , instrumentor.getClassPool().get("java.lang.Throwable")); - addStaticAroundInterceptor(constructorName, id, constructor); - } - return true; - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - } - return false; - } + // constructor.insertAfter("{System.out.println(\"*****" + + // constructorName + " Constructor:Param=(" + params + + // ") is finished. \" + $args);}"); + // constructor.addCatch("{System.out.println(\"*****" + + // constructorName + " Constructor:Param=(" + params + + // ") is finished.\"); throw $e; }" + // , instrumentor.getClassPool().get("java.lang.Throwable")); + addStaticAroundInterceptor(constructorName, id, constructor); + } + return true; + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + } + return false; + } - private String getParamsToString(CtClass[] params) throws NotFoundException { - StringBuilder sb = new StringBuilder(512); - if (params.length != 0) { - int paramsLength = params.length; - for (int loop = paramsLength - 1; loop > 0; loop--) { - sb.append(params[loop].getName()).append(","); - } - } - String paramsStr = sb.toString(); - if (logger.isLoggable(Level.FINE)) { - logger.fine("params type:" + paramsStr); - } - return paramsStr; - } + private String getParamsToString(CtClass[] params) throws NotFoundException { + StringBuilder sb = new StringBuilder(512); + if (params.length != 0) { + int paramsLength = params.length; + for (int loop = paramsLength - 1; loop > 0; loop--) { + sb.append(params[loop].getName()).append(","); + } + } + String paramsStr = sb.toString(); + if (logger.isLoggable(Level.FINE)) { + logger.fine("params type:" + paramsStr); + } + return paramsStr; + } - private CtMethod getMethod(String methodName, String[] args) throws NotFoundException { + private CtMethod getMethod(String methodName, String[] args) throws NotFoundException { CtClass[] params = JavaAssistUtils.getCtParameter(args, instrumentor.getClassPool()); // cttime에는 직접 구현클래스를 조작해야 되므로 상속관계의 method를 찾으면 안됨. return ctClass.getDeclaredMethod(methodName, params); } - private CtConstructor getConstructor(String[] args) throws NotFoundException { + private CtConstructor getConstructor(String[] args) throws NotFoundException { CtClass[] params = JavaAssistUtils.getCtParameter(args, instrumentor.getClassPool()); return ctClass.getDeclaredConstructor(params); - } + } + @Override + public byte[] toBytecode() { + try { + return ctClass.toBytecode(); + } catch (IOException e) { + logger.log(Level.INFO, "IoException class:" + ctClass.getName() + " " + e.getMessage(), e); + } catch (CannotCompileException e) { + logger.log(Level.INFO, "CannotCompileException class:" + ctClass.getName() + " " + e.getMessage(), e); + } + return null; + } - @Override - public byte[] toBytecode() { - try { - return ctClass.toBytecode(); - } catch (IOException e) { - logger.log(Level.INFO, "IoException class:" + ctClass.getName() + " " + e.getMessage(), e); - } catch (CannotCompileException e) { - logger.log(Level.INFO, "CannotCompileException class:" + ctClass.getName() + " " + e.getMessage(), e); - } - return null; - } - - public Class toClass() { - try { - return ctClass.toClass(); - } catch (CannotCompileException e) { - logger.log(Level.INFO, "CannotCompileException class:" + ctClass.getName() + " " + e.getMessage(), e); - } - return null; - } + public Class toClass() { + try { + return ctClass.toClass(); + } catch (CannotCompileException e) { + logger.log(Level.INFO, "CannotCompileException class:" + ctClass.getName() + " " + e.getMessage(), e); + } + return null; + } } diff --git a/src/main/java/com/profiler/modifier/db/interceptor/PreparedStatementExecuteQueryInterceptor.java b/src/main/java/com/profiler/modifier/db/interceptor/PreparedStatementExecuteQueryInterceptor.java index faba2b1d2..eaab4460b 100644 --- a/src/main/java/com/profiler/modifier/db/interceptor/PreparedStatementExecuteQueryInterceptor.java +++ b/src/main/java/com/profiler/modifier/db/interceptor/PreparedStatementExecuteQueryInterceptor.java @@ -3,6 +3,8 @@ package com.profiler.modifier.db.interceptor; import com.profiler.context.Annotation; import com.profiler.context.Trace; import com.profiler.context.TraceContext; +import com.profiler.interceptor.ByteCodeMethodDescriptorSupport; +import com.profiler.interceptor.MethodDescriptor; import com.profiler.interceptor.StaticAroundInterceptor; import com.profiler.modifier.db.util.DatabaseInfo; import com.profiler.util.InterceptorUtils; @@ -16,7 +18,7 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -public class PreparedStatementExecuteQueryInterceptor implements StaticAroundInterceptor { +public class PreparedStatementExecuteQueryInterceptor implements StaticAroundInterceptor, ByteCodeMethodDescriptorSupport { private final Logger logger = Logger.getLogger(PreparedStatementExecuteQueryInterceptor.class.getName()); @@ -25,6 +27,7 @@ public class PreparedStatementExecuteQueryInterceptor implements StaticAroundInt private final MetaObject getBindValue = new MetaObject("__getBindValue"); private final MetaObject setBindValue = new MetaObject("__setBindValue", Map.class); + private MethodDescriptor descriptor; @Override public void before(Object target, String className, String methodName, String parameterDescription, Object[] args) { @@ -37,6 +40,7 @@ public class PreparedStatementExecuteQueryInterceptor implements StaticAroundInt } TraceContext traceContext = TraceContext.getTraceContext(); Trace trace = traceContext.currentTraceObject(); + if (trace == null) { return; } @@ -52,6 +56,7 @@ public class PreparedStatementExecuteQueryInterceptor implements StaticAroundInt Map bindValue = getBindValue.invoke(target); String bindString = toBindVariable(bindValue); trace.recordAttribute("BindValue", bindString); + trace.recordAttribute("API", descriptor.getClassName() + "." + descriptor.getMethodName() + descriptor.getSimpleParameterDescriptor()); clean(target); @@ -113,4 +118,8 @@ public class PreparedStatementExecuteQueryInterceptor implements StaticAroundInt } } + @Override + public void setMethodDescriptor(MethodDescriptor descriptor) { + this.descriptor = descriptor; + } } 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 c468294aa..5a8490cdc 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java @@ -45,9 +45,12 @@ public class MySQLPreparedStatementModifier extends AbstractModifier { try { InstrumentClass preparedStatement = byteCodeInstrumentor.getClass(javassistClassName); - Interceptor interceptor = new PreparedStatementExecuteQueryInterceptor(); - int id = preparedStatement.addInterceptor("executeQuery", null, interceptor); - preparedStatement.reuseInterceptor("executeUpdate", null, id); + Interceptor execute = new PreparedStatementExecuteQueryInterceptor(); + preparedStatement.addInterceptor("execute", null, execute); + Interceptor executeQuery = new PreparedStatementExecuteQueryInterceptor(); + preparedStatement.addInterceptor("executeQuery", null, executeQuery); + Interceptor executeUpdate = new PreparedStatementExecuteQueryInterceptor(); + preparedStatement.addInterceptor("executeUpdate", null, executeUpdate); preparedStatement.addTraceVariable("__url", "__setUrl", "__getUrl", "java.lang.Object"); preparedStatement.addTraceVariable("__sql", "__setSql", "__getSql", "java.lang.String"); diff --git a/src/main/java/com/profiler/modifier/db/util/DatabaseInfo.java b/src/main/java/com/profiler/modifier/db/util/DatabaseInfo.java index 7bf0e7cbf..f4eea9ecc 100644 --- a/src/main/java/com/profiler/modifier/db/util/DatabaseInfo.java +++ b/src/main/java/com/profiler/modifier/db/util/DatabaseInfo.java @@ -10,14 +10,17 @@ public class DatabaseInfo { DBType type = DBType.UNKOWN; String databaseId; - String url; + // 입력된 url을 보정하지 않은 값 + String realUrl; + String normalizedUrl; String host; String port; - public DatabaseInfo(DBType type, String url, String host, String port, String databaseId) { + public DatabaseInfo(DBType type, String realUrl, String normalizedUrl, String host, String port, String databaseId) { this.type = type; - this.url = url; + this.realUrl = realUrl; + this.normalizedUrl = normalizedUrl; this.host = host; this.port = port; this.databaseId = databaseId; @@ -39,8 +42,12 @@ public class DatabaseInfo { return databaseId; } + public String getRealUrl() { + return realUrl; + } + public String getUrl() { - return url; + return normalizedUrl; } public DBType getType() { @@ -52,7 +59,8 @@ public class DatabaseInfo { return "DatabaseInfo{" + "type=" + type + ", databaseId='" + databaseId + '\'' + - ", url='" + url + '\'' + + ", realUrl='" + realUrl + '\'' + + ", normalizedUrl='" + normalizedUrl + '\'' + ", host='" + host + '\'' + ", port='" + port + '\'' + '}'; diff --git a/src/main/java/com/profiler/modifier/db/util/JDBCUrlParser.java b/src/main/java/com/profiler/modifier/db/util/JDBCUrlParser.java index 3dcc07ac6..e54649d83 100644 --- a/src/main/java/com/profiler/modifier/db/util/JDBCUrlParser.java +++ b/src/main/java/com/profiler/modifier/db/util/JDBCUrlParser.java @@ -7,12 +7,15 @@ import java.util.regex.Matcher; */ public class JDBCUrlParser { public DatabaseInfo parse(String url) { - String lowCaseURL = url.toLowerCase(); - if (lowCaseURL.contains("jdbc:mysql")) { + String lowCaseURL = url.toLowerCase().trim(); + if (lowCaseURL.startsWith("jdbc:mysql")) { return parseMysql(url); } + if (lowCaseURL.startsWith("jdbc:oracle")) { + return parseOracle(url); + } - return new DatabaseInfo(DatabaseInfo.DBType.UNKOWN, url, "error", "error", "error"); + return new DatabaseInfo(DatabaseInfo.DBType.UNKOWN, url, url, "error", "error", "error"); // else if (url.indexOf("jdbc:oracle") >= 0) { // maker.lower().after("jdbc:oracle:").after(':'); // info.type = TYPE.ORACLE; @@ -60,6 +63,11 @@ public class JDBCUrlParser { // return null; } + private DatabaseInfo parseOracle(String url) { + return null; + } + + private DatabaseInfo parseMysql(String url) { // jdbc:mysql://10.98.133.22:3306/test_lucy_db StringMaker maker = new StringMaker(url); @@ -67,6 +75,7 @@ public class JDBCUrlParser { String host = maker.after("//").before('/').before(':').value(); String port = maker.next().after(':').before('/').value(); String databaseId = maker.next().afterLast('/').before('?').value(); - return new DatabaseInfo(DatabaseInfo.DBType.MYSQL, url, host, port, databaseId); + String normalizedUrl = maker.clear().before('?').value(); + return new DatabaseInfo(DatabaseInfo.DBType.MYSQL, url, normalizedUrl, host, port, databaseId); } } diff --git a/src/main/java/com/profiler/util/JavaAssistUtils.java b/src/main/java/com/profiler/util/JavaAssistUtils.java index 96b865847..ae02d14af 100644 --- a/src/main/java/com/profiler/util/JavaAssistUtils.java +++ b/src/main/java/com/profiler/util/JavaAssistUtils.java @@ -1,22 +1,25 @@ package com.profiler.util; import javassist.*; -import javassist.bytecode.Descriptor; +import javassist.bytecode.*; public class JavaAssistUtils { - private final static String NULL = "()"; + private final static String EMTPY_ARRAY = "()"; + private static String[] EMPTY_STRING_ARRAY = new String[0]; + /** * test(int, java.lang.String) 일경우 * (int, java.lang.String)로 생성된다. + * * @param params * @return */ public static String getParameterDescription(CtClass[] params) { - if(params == null) { - return NULL; + if (params == null) { + return EMTPY_ARRAY; } StringBuilder sb = new StringBuilder(64); - sb.append("("); + sb.append('('); int end = params.length - 1; for (int i = 0; i < params.length; i++) { sb.append(params[i].getName()); @@ -24,10 +27,11 @@ public class JavaAssistUtils { sb.append(", "); } } - sb.append(")"); + sb.append(')'); return sb.toString(); } + public static String[] getParameterType(Class[] paramsClass) { if (paramsClass == null) { return null; @@ -39,12 +43,34 @@ public class JavaAssistUtils { return paramsString; } + public static String[] getParameterSimpleType(CtClass[] paramsClass) { + if (paramsClass == null) { + return null; + } + String[] paramsString = new String[paramsClass.length]; + for (int i = 0; i < paramsClass.length; i++) { + paramsString[i] = paramsClass[i].getSimpleName(); + } + return paramsString; + } + + public static String[] getParameterType(CtClass[] paramsClass) { + if (paramsClass == null) { + return null; + } + String[] paramsString = new String[paramsClass.length]; + for (int i = 0; i < paramsClass.length; i++) { + paramsString[i] = paramsClass[i].getName(); + } + return paramsString; + } + public static String getParameterDescription(Class[] params) { - if(params == null) { - return NULL; + if (params == null) { + return EMTPY_ARRAY; } StringBuilder sb = new StringBuilder(64); - sb.append("("); + sb.append('('); int end = params.length - 1; for (int i = 0; i < params.length; i++) { sb.append(params[i].getName()); @@ -52,16 +78,40 @@ public class JavaAssistUtils { sb.append(", "); } } - sb.append(")"); + sb.append(')'); return sb.toString(); } + public static String mergeParameterVariableNameDescription(String[] paramterType, String[] variableName) { + if (paramterType.length != variableName.length) { + throw new IllegalArgumentException("args size not equal"); + } + if (paramterType.length == 0) { + return EMTPY_ARRAY; + } + + StringBuilder sb = new StringBuilder(64); + sb.append('('); + int end = paramterType.length - 1; + for (int i = 0; i < paramterType.length; i++) { + sb.append(paramterType[i]); + sb.append(' '); + sb.append(variableName[i]); + if (i < end) { + sb.append(", "); + } + } + sb.append(')'); + return sb.toString(); + } + + public static String getParameterDescription(String[] params) { - if(params == null) { - return NULL; + if (params == null) { + return EMTPY_ARRAY; } StringBuilder sb = new StringBuilder(64); - sb.append("("); + sb.append('('); int end = params.length - 1; for (int i = 0; i < params.length; i++) { sb.append(params[i]); @@ -69,35 +119,94 @@ public class JavaAssistUtils { sb.append(", "); } } - sb.append(")"); + sb.append(')'); return sb.toString(); } public static CtClass[] getCtParameter(String[] args, ClassPool pool) throws NotFoundException { - if (args == null) { - return null; - } - CtClass[] params = new CtClass[args.length]; - for (int i = 0; i < args.length; i++) { - params[i] = pool.getCtClass(args[i]); - } - return params; - } + if (args == null) { + return null; + } + CtClass[] params = new CtClass[args.length]; + for (int i = 0; i < args.length; i++) { + params[i] = pool.getCtClass(args[i]); + } + return params; + } + + + public static int getLineNumber(CtBehavior method) { + if (method == null) { + return -1; + } + return method.getMethodInfo().getLineNumber(0); + } + public CtMethod findAllMethod(CtClass ctClass, String methodName, String[] args) throws NotFoundException { CtClass[] params = getCtParameter(args, ctClass.getClassPool()); String paramDescriptor = Descriptor.ofParameters(params); CtMethod[] methods = ctClass.getMethods(); for (CtMethod method : methods) { - if(method.getName().equals(methodName) && method.getMethodInfo2().getDescriptor().startsWith(paramDescriptor)) { + if (method.getName().equals(methodName) && method.getMethodInfo2().getDescriptor().startsWith(paramDescriptor)) { return method; } } - throw new NotFoundException(methodName+ "(..) is not found in " + ctClass.getName()); + throw new NotFoundException(methodName + "(..) is not found in " + ctClass.getName()); } public static boolean isStaticBehavior(CtBehavior behavior) { - int modifiers = behavior.getModifiers(); - return java.lang.reflect.Modifier.isStatic(modifiers); - } + int modifiers = behavior.getModifiers(); + return java.lang.reflect.Modifier.isStatic(modifiers); + } + + + public static String[] getParameterVariableName(CtBehavior method) throws NotFoundException { + LocalVariableAttribute localVariableAttribute = lookupLocalVariableAttribute(method); + return getParameterVariableName(method, localVariableAttribute); + } + + /** + * LocalVariable 메모리 공간을 얻어 온다. + * + * @param method + * @return null일 경우 debug모드로 컴파일 되지 않아서 그럼. + */ + public static LocalVariableAttribute lookupLocalVariableAttribute(CtBehavior method) { + MethodInfo methodInfo = method.getMethodInfo(); + CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); + AttributeInfo localVariableTable = codeAttribute.getAttribute(LocalVariableAttribute.tag); + LocalVariableAttribute local = (LocalVariableAttribute) localVariableTable; + return local; + } + + public static String[] getParameterVariableName(CtBehavior method, LocalVariableAttribute localVariableAttribute) throws NotFoundException { + // http://www.jarvana.com/jarvana/view/org/jboss/weld/servlet/weld-servlet/1.0.1-Final/weld-servlet-1.0.1-Final-sources.jar!/org/slf4j/instrumentation/JavassistHelper.java?format=ok + // 이거 참고함. + if (localVariableAttribute == null) { + // null이라는건 debug모드로 컴파일 되지 않았다는 의미이다. + // parameter class명을 default로 하자. + return null; + } + CtClass[] parameterTypes = method.getParameterTypes(); + if (parameterTypes.length == 0) { + return EMPTY_STRING_ARRAY; + } + String[] parameterVariableNames = new String[parameterTypes.length]; + int firstIndex = 0; + int modifiers = method.getModifiers(); +// 동기화 메소드라도 index를 증가시키면 안되는데. 참고 소스와는 뭔가 다름 나중에 문제가 생길수 있으니 일단 주석으로 적음. +// if (Modifier.isSynchronized(modifiers)) { +// firstIndex++; +// } + if (Modifier.isStatic(modifiers) == false) { + firstIndex++; + } + for (int i = 0; i < parameterTypes.length; i++) { + int accesIndex = firstIndex + i; + String variablename = localVariableAttribute.variableName(accesIndex); + parameterVariableNames[i] = variablename; + } + return parameterVariableNames; + } } diff --git a/src/test/java/com/profiler/modifier/db/util/JDBCUrlParserTest.java b/src/test/java/com/profiler/modifier/db/util/JDBCUrlParserTest.java index ba415e873..5e920a248 100644 --- a/src/test/java/com/profiler/modifier/db/util/JDBCUrlParserTest.java +++ b/src/test/java/com/profiler/modifier/db/util/JDBCUrlParserTest.java @@ -44,8 +44,7 @@ public class JDBCUrlParserTest { Assert.assertEquals(dbInfo.getHost(), "ip_address"); Assert.assertEquals(dbInfo.getPort(), "3306"); Assert.assertEquals(dbInfo.getDatabaseId(), "database_name"); -// JDBCUrlParser.parse("jdbc:mysql://61.74.71.31/log?useUnicode=yes&characterEncoding=UTF-8") - + Assert.assertEquals(dbInfo.getUrl(), "jdbc:mysql://ip_address:3306/database_name"); } @Test @@ -56,5 +55,16 @@ public class JDBCUrlParserTest { Assert.assertEquals(dbInfo.getHost(), "10.98.133.22"); Assert.assertEquals(dbInfo.getPort(), "3306"); Assert.assertEquals(dbInfo.getDatabaseId(), "test_lucy_db"); + Assert.assertEquals(dbInfo.getUrl(), "jdbc:mysql://10.98.133.22:3306/test_lucy_db"); + } + + @Test + public void mysqlParse3() { + DatabaseInfo dbInfo = JDBCUrlParser.parse("jdbc:mysql://61.74.71.31/log?useUnicode=yes&characterEncoding=UTF-8"); + Assert.assertEquals(dbInfo.getType(), DatabaseInfo.DBType.MYSQL); + Assert.assertEquals(dbInfo.getHost(), "61.74.71.31"); + Assert.assertEquals(dbInfo.getPort(), ""); + Assert.assertEquals(dbInfo.getDatabaseId(), "log"); + Assert.assertEquals(dbInfo.getUrl(), "jdbc:mysql://61.74.71.31/log"); } } diff --git a/src/test/java/com/profiler/util/JavaAssistUtilsTest.java b/src/test/java/com/profiler/util/JavaAssistUtilsTest.java index 1912b213e..8486d1628 100644 --- a/src/test/java/com/profiler/util/JavaAssistUtilsTest.java +++ b/src/test/java/com/profiler/util/JavaAssistUtilsTest.java @@ -1,14 +1,15 @@ package com.profiler.util; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtMethod; +import javassist.*; +import javassist.bytecode.LocalVariableAttribute; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Arrays; + public class JavaAssistUtilsTest { private final Logger logger = LoggerFactory.getLogger(JavaAssistUtilsTest.class.getName()); private ClassPool pool; @@ -30,6 +31,40 @@ public class JavaAssistUtilsTest { String clsDescription = JavaAssistUtils.getParameterDescription(new Class[]{int.class}); logger.info(clsDescription); Assert.assertEquals(ctDescription, clsDescription); + + + } + + @Test + public void testGetLineNumber() throws Exception { +// pool.appendClassPath(new ClassClassPath(AbstractHttpClient.class)); + CtClass ctClass = pool.get("org.apache.http.impl.client.AbstractHttpClient"); + CtClass params = pool.get("org.apache.http.params.HttpParams"); + // non-javadoc, see interface HttpClient +// public synchronized final HttpParams getParams() { +// if (defaultParams == null) { +// defaultParams = createHttpParams(); +// } +// return defaultParams; +// } + + CtMethod setParams = ctClass.getDeclaredMethod("setParams", new CtClass[]{params}); + int lineNumber = JavaAssistUtils.getLineNumber(setParams); + logger.info("line:" + lineNumber); + + logger.info(setParams.getName()); + logger.info(setParams.getLongName()); + + String[] paramName = JavaAssistUtils.getParameterVariableName(setParams); + logger.info(Arrays.toString(paramName)); + Assert.assertEquals(paramName.length, 1); + Assert.assertEquals(paramName[0], "params"); + + String[] parameterType = JavaAssistUtils.getParameterType(setParams.getParameterTypes()); + logger.info(Arrays.toString(parameterType)); + + String s = JavaAssistUtils.mergeParameterVariableNameDescription(parameterType, paramName); + logger.info(s); } @Test