diff --git a/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java b/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java index 8e1e2247c..d127b7606 100644 --- a/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java +++ b/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java @@ -11,7 +11,7 @@ public interface ByteCodeInstrumentor { void checkLibrary(ClassLoader classLoader, String javassistClassName); - InstrumentClass getClass(String javassistClassName); + InstrumentClass getClass(String javassistClassName) throws InstrumentException; - Class defineClass(ClassLoader classLoader, String defineClass, ProtectionDomain protectedDomain); + Class defineClass(ClassLoader classLoader, String defineClass, ProtectionDomain protectedDomain) throws InstrumentException; } diff --git a/src/main/java/com/profiler/interceptor/bci/InstrumentClass.java b/src/main/java/com/profiler/interceptor/bci/InstrumentClass.java index 996a28bd2..bc084f0d2 100644 --- a/src/main/java/com/profiler/interceptor/bci/InstrumentClass.java +++ b/src/main/java/com/profiler/interceptor/bci/InstrumentClass.java @@ -8,19 +8,21 @@ public interface InstrumentClass { boolean insertCodeAfterMethod(String methodName, String[] args, String code); - boolean addInterceptor(String methodName, String[] args, Interceptor interceptor); + int addConstructorInterceptor(String[] args, Interceptor interceptor) throws InstrumentException; - boolean addInterceptor(String methodName, String[] args, Interceptor interceptor, Type type); + int addInterceptor(String methodName, String[] args, Interceptor interceptor) throws InstrumentException; + + int addInterceptor(String methodName, String[] args, Interceptor interceptor, Type type) throws InstrumentException; boolean addDebugLogBeforeAfterMethod(); boolean addDebugLogBeforeAfterConstructor(); - byte[] toBytecode(); + byte[] toBytecode() throws InstrumentException ; - Class toClass(); + Class toClass() throws InstrumentException ; - boolean addTraceVariable(String variableName, String setterName, String getterName, String variableType); + void addTraceVariable(String variableName, String setterName, String getterName, String variableType) throws InstrumentException ; boolean insertCodeAfterConstructor(String[] args, String code); diff --git a/src/main/java/com/profiler/interceptor/bci/InstrumentException.java b/src/main/java/com/profiler/interceptor/bci/InstrumentException.java new file mode 100644 index 000000000..2d4f21f98 --- /dev/null +++ b/src/main/java/com/profiler/interceptor/bci/InstrumentException.java @@ -0,0 +1,20 @@ +package com.profiler.interceptor.bci; + +// TODO 추후 별도 계층구조가 필요하면 분화 필요. +public class InstrumentException extends Exception { + + public InstrumentException() { + } + + public InstrumentException(String message) { + super(message); + } + + public InstrumentException(String message, Throwable cause) { + super(message, cause); + } + + public InstrumentException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java b/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java index d420cc17c..de6c3a19a 100644 --- a/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java +++ b/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java @@ -61,34 +61,29 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor { } @Override - public InstrumentClass getClass(String javassistClassName) { + public InstrumentClass getClass(String javassistClassName) throws InstrumentException { try { CtClass cc = classPool.get(javassistClassName); return new JavaAssistClass(this, cc); } catch (NotFoundException e) { - // TODO 실패시 더미 객체를 반환해서 잘 에러를 숨길수 있도록 수정필요. - return null; + throw new InstrumentException(javassistClassName + " class not fund. Cause:" + e.getMessage(), e); } } @Override - public Class defineClass(ClassLoader classLoader, String defineClass, ProtectionDomain protectedDomain) { - try { - if (logger.isLoggable(Level.INFO)) { + public Class defineClass(ClassLoader classLoader, String defineClass, ProtectionDomain protectedDomain) throws InstrumentException { + if (logger.isLoggable(Level.INFO)) { logger.info("defineClass classLoader:" + classLoader + " class:" + defineClass); - } + } + + try { CtClass clazz = classPool.get(defineClass); return clazz.toClass(classLoader, protectedDomain); } catch (NotFoundException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, "defineClass classLoader:" + classLoader + " " + e.getMessage(), e); - } + throw new InstrumentException(defineClass + " class not fund. Cause:" + e.getMessage(), e); } catch (CannotCompileException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, "defineClass classLoader:" + classLoader + " " + e.getMessage(), e); - } + throw new InstrumentException(defineClass + " class define fail. cl:" + classLoader + " Cause:" + e.getMessage(), e); } - return null; } public boolean findClass(String javassistClassName) { @@ -119,7 +114,7 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor { } } catch (NotFoundException e) { if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, "lib not fail. " + e.getMessage(), e); + logger.log(Level.WARNING, "lib not fail. path:" + filePath + " cl:" + classLoader + " Cause:" + e.getMessage(), e); } } } diff --git a/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java b/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java index e7eff643e..913059c11 100644 --- a/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java +++ b/src/main/java/com/profiler/interceptor/bci/JavaAssistClass.java @@ -1,6 +1,7 @@ package com.profiler.interceptor.bci; import java.io.IOException; +import java.util.Arrays; import java.util.Formatter; import java.util.logging.Level; import java.util.logging.Logger; @@ -100,7 +101,7 @@ public class JavaAssistClass implements InstrumentClass { } // TODO return type을 별도 exception으로 할지 추가 검토가 필요함. - public boolean addTraceVariable(String variableName, String setterName, String getterName, String variableType) { + public void addTraceVariable(String variableName, String setterName, String getterName, String variableType) throws InstrumentException { try { CtClass type = instrumentor.getClassPool().get(variableType); CtField traceVariable = new CtField(type, variableName, ctClass); @@ -113,82 +114,68 @@ public class JavaAssistClass implements InstrumentClass { CtMethod getterMethod = CtNewMethod.getter(getterName, traceVariable); ctClass.addMethod(getterMethod); } - return true; } catch (NotFoundException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException("addTraceVariable fail. Cause:" + e.getMessage(), e); } catch (CannotCompileException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException("addTraceVariable fail. Cause:" + e.getMessage(), e); } - return false; } - public boolean addConstructorInterceptor(String[] args, Interceptor interceptor) { + public int addConstructorInterceptor(String[] args, Interceptor interceptor) throws InstrumentException { return addInterceptor(null, args, interceptor); } @Override - public boolean addInterceptor(String methodName, String[] args, Interceptor interceptor) { + public int addInterceptor(String methodName, String[] args, Interceptor interceptor) throws InstrumentException { return addInterceptor(methodName, args, interceptor, Type.auto); } @Override - public boolean addInterceptor(String methodName, String[] args, Interceptor interceptor, Type type) { + public int addInterceptor(String methodName, String[] args, Interceptor interceptor, Type type) throws InstrumentException { if (interceptor == null) { - return false; + throw new IllegalArgumentException("interceptor is null"); } CtBehavior behavior = getBehavior(methodName, args); - if (behavior == null) { - return false; - } return addInterceptor0(methodName, interceptor, type, behavior); } - private CtBehavior getBehavior(String methodName, String[] args) { + private CtBehavior getBehavior(String methodName, String[] args) throws InstrumentException { if (methodName == null) { return getConstructor(args); } return getMethod(methodName, args); } - private boolean addInterceptor0(String methodName, Interceptor interceptor, Type type, CtBehavior behavior) { - int id = InterceptorRegistry.addInterceptor(interceptor); + private int addInterceptor0(String methodName, Interceptor interceptor, Type type, CtBehavior behavior) throws InstrumentException { + int interceptorId = InterceptorRegistry.addInterceptor(interceptor); try { if (type == Type.auto) { if (interceptor instanceof StaticAroundInterceptor) { - addStaticAroundInterceptor(methodName, id, behavior); + addStaticAroundInterceptor(methodName, interceptorId, behavior); } else if (interceptor instanceof StaticBeforeInterceptor) { - addStaticBeforeInterceptor(methodName, id, behavior); + addStaticBeforeInterceptor(methodName, interceptorId, behavior); } else if (interceptor instanceof StaticAfterInterceptor) { - addStaticAfterInterceptor(methodName, id, behavior); + addStaticAfterInterceptor(methodName, interceptorId, behavior); } else { - return false; + throw new IllegalArgumentException("unsupported"); } } else if (type == Type.around && interceptor instanceof StaticAroundInterceptor) { - addStaticAroundInterceptor(methodName, id, behavior); + addStaticAroundInterceptor(methodName, interceptorId, behavior); } else if (type == Type.before && interceptor instanceof StaticBeforeInterceptor) { - addStaticBeforeInterceptor(methodName, id, behavior); + addStaticBeforeInterceptor(methodName, interceptorId, behavior); } else if (type == Type.after && interceptor instanceof StaticAfterInterceptor) { - addStaticAfterInterceptor(methodName, id, behavior); + addStaticAfterInterceptor(methodName, interceptorId, behavior); } else { - return false; + throw new IllegalArgumentException("unsupported"); } - return true; } catch (NotFoundException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException("addInterceptor fail. Cause:" + e.getMessage(), e); } catch (CannotCompileException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException("addInterceptor fail. Cause:" + e.getMessage(), e); } - return false; + return interceptorId; } private void addStaticAroundInterceptor(String methodName, int id, CtBehavior method) throws NotFoundException, CannotCompileException { @@ -367,28 +354,22 @@ public class JavaAssistClass implements InstrumentClass { return paramsStr; } - private CtMethod getMethod(String methodName, String[] args) { + private CtMethod getMethod(String methodName, String[] args) throws InstrumentException { try { CtClass[] params = getCtParameter(args); return ctClass.getDeclaredMethod(methodName, params); } catch (NotFoundException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException(methodName + Arrays.toString(args) + " method not found. Cause:" + e.getMessage(), e); } - return null; } - private CtConstructor getConstructor(String[] args) { + private CtConstructor getConstructor(String[] args) throws InstrumentException { try { CtClass[] params = getCtParameter(args); return ctClass.getDeclaredConstructor(params); } catch (NotFoundException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException(Arrays.toString(args) + " Constructor not found. Cause:" + e.getMessage(), e); } - return null; } private CtClass[] getCtParameter(String[] args) throws NotFoundException { diff --git a/src/main/java/com/profiler/modifier/AbstractModifier.java b/src/main/java/com/profiler/modifier/AbstractModifier.java index b7470dc46..b61e7b4ca 100644 --- a/src/main/java/com/profiler/modifier/AbstractModifier.java +++ b/src/main/java/com/profiler/modifier/AbstractModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.interceptor.bci.InstrumentException; import javassist.ClassPool; import com.profiler.interceptor.Interceptor; @@ -31,19 +32,14 @@ public abstract class AbstractModifier implements Modifier { this.byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName); } - protected Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN) { + protected Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN) throws InstrumentException { Class aClass = this.byteCodeInstrumentor.defineClass(classLoader, interceptorFQCN, protectedDomain); try { return (Interceptor) aClass.newInstance(); } catch (InstantiationException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e); } catch (IllegalAccessException e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } + throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e); } - return null; } } diff --git a/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java b/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java index dbb0ec80c..07eee7c3b 100644 --- a/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java +++ b/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.interceptor.bci.InstrumentException; import javassist.ByteArrayClassPath; import com.profiler.interceptor.Interceptor; @@ -52,18 +53,16 @@ public class HTTPClientModifier extends AbstractModifier { } catch (Exception e) { e.printStackTrace(); } - - Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.connector.interceptors.ExecuteMethodInterceptor"); - if (interceptor == null) { - return null; - } - byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName); - classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer)); - - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - aClass.addInterceptor("execute", new String[] { "org.apache.http.HttpHost", "org.apache.http.HttpRequest", "org.apache.http.client.ResponseHandler", "org.apache.http.protocol.HttpContext" }, interceptor); - - return aClass.toBytecode(); - } + classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer)); + try { + Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.connector.interceptors.ExecuteMethodInterceptor"); + InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); + aClass.addInterceptor("execute", new String[] { "org.apache.http.HttpHost", "org.apache.http.HttpRequest", "org.apache.http.client.ResponseHandler", "org.apache.http.protocol.HttpContext" }, interceptor); + return aClass.toBytecode(); + } catch (InstrumentException e) { + // TODO log + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java b/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java index 37287c898..b3e83f1aa 100644 --- a/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java @@ -48,14 +48,11 @@ public class CubridStatementModifier extends AbstractModifier { } }; - InstrumentClass aClass = this.byteCodeInstrumentor.getClass(javassistClassName); - aClass.addInterceptor("executeQuery", new String[] {"java.lang.String"}, interceptor); - - printClassConvertComplete(javassistClassName); -// return aClass.toBytecode(); - - try { + // TODO 추가로 고쳐야 될듯. + InstrumentClass aClass = this.byteCodeInstrumentor.getClass(javassistClassName); + aClass.addInterceptor("executeQuery", new String[] {"java.lang.String"}, interceptor); + printClassConvertComplete(javassistClassName); CtClass cc = classPool.get(javassistClassName); updateExecuteQueryMethod(cc); diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java index 90552a9f2..811e50951 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java @@ -3,6 +3,7 @@ package com.profiler.modifier.db.mysql; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; +import com.profiler.interceptor.bci.InstrumentException; import javassist.CtClass; import javassist.CtMethod; @@ -36,29 +37,24 @@ public class MySQLConnectionImplModifier extends AbstractModifier { if (mysqlConnection == null) { return null; } + + Interceptor createConnection = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.CreateConnectionInterceptor"); + Interceptor closeConnection = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.CloseConnectionInterceptor"); + Interceptor createStatement = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.CreateStatementInterceptor"); + Interceptor preparedStatement = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.CreatePreparedStatementInterceptor"); + String[] params = new String[] { "java.lang.String", "int", "java.util.Properties", "java.lang.String", "java.lang.String" }; - Interceptor createConnection = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.CreateConnectionInterceptor"); - if (createConnection == null) { - return null; - } - Interceptor closeConnection = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.CloseConnectionInterceptor"); - if (closeConnection == null) { - return null; - } - Interceptor createStatement = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.CreateStatementInterceptor"); - if (createStatement == null) { - return null; - } mysqlConnection.addInterceptor("getInstance", params, createConnection); mysqlConnection.addInterceptor("close", null, closeConnection); mysqlConnection.addInterceptor("createStatement", null, createStatement); + mysqlConnection.addInterceptor("prepareStatement", new String[]{"java.lang.String"}, createStatement); printClassConvertComplete(javassistClassName); return mysqlConnection.toBytecode(); - } catch (Exception e) { + } catch (InstrumentException e) { if (logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING, e.getMessage(), e); } 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 f82b1beb0..02ba1d08f 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java @@ -4,7 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; -import javassist.ByteArrayClassPath; +import com.profiler.interceptor.bci.InstrumentException; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtMethod; @@ -33,6 +33,14 @@ public class MySQLPreparedStatementModifier extends AbstractModifier { } checkLibrary(classLoader, javassistClassName); + try { + InstrumentClass preparedStatement = byteCodeInstrumentor.getClass(javassistClassName); + Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.PreparedStatementMethodInterceptor"); + + preparedStatement.addInterceptor("prepareStatement", new String[]{"java.lang.String"}, interceptor); + } catch (InstrumentException e) { + return null; + } // Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.ExecuteMethodInterceptor"); // if (interceptor == null) { diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java index cc2c6d6e7..ee0268137 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java @@ -1,10 +1,12 @@ package com.profiler.modifier.db.mysql; import java.security.ProtectionDomain; +import java.sql.Connection; import java.util.logging.Level; import java.util.logging.Logger; import com.profiler.interceptor.Interceptor; +import com.profiler.interceptor.bci.InstrumentException; import com.profiler.interceptor.bci.JavaAssistClass; import javassist.*; @@ -31,28 +33,21 @@ public class MySQLStatementModifier extends AbstractModifier { } byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName); -// classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer)); - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.ExecuteQueryMethodInterceptor"); - boolean executeQuery = aClass.addInterceptor("executeQuery", new String[]{"java.lang.String"}, interceptor); - if (logger.isLoggable(Level.INFO)) { - logger.info("executeQuery =" + executeQuery); + try { + InstrumentClass statementClass = byteCodeInstrumentor.getClass(javassistClassName); + Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.ExecuteQueryMethodInterceptor"); + statementClass.addInterceptor("executeQuery", new String[]{"java.lang.String"}, interceptor); + + + Interceptor interceptor1 = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.ExecuteUpdateMethodInterceptor"); + statementClass.addInterceptor("executeUpdate", new String[]{"java.lang.String", "boolean", "boolean"}, interceptor1); + + statementClass.addTraceVariable("__url", "__setUrl", "__getUrl", "java.lang.String"); + return statementClass.toBytecode(); + } catch (InstrumentException e) { + return null; } - - Interceptor interceptor1 = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.ExecuteUpdateMethodInterceptor"); - boolean executeUpdate = aClass.addInterceptor("executeUpdate", new String[]{"java.lang.String", "boolean", "boolean"}, interceptor1); - if (logger.isLoggable(Level.INFO)) { - logger.info("executeUpdate =" + executeUpdate); - } - // TODO 아무래도 에러 체크를 Exception으로 변경하는게 좋을것 같음. - aClass.addTraceVariable("__url", "__setUrl", "__getUrl", "java.lang.String"); - - - if (executeQuery && executeQuery) { - return aClass.toBytecode(); - } - return null; } diff --git a/src/main/java/com/profiler/modifier/db/mysql/interceptors/CreatePreparedStatementInterceptor.java b/src/main/java/com/profiler/modifier/db/mysql/interceptors/CreatePreparedStatementInterceptor.java new file mode 100644 index 000000000..4b0b5b641 --- /dev/null +++ b/src/main/java/com/profiler/modifier/db/mysql/interceptors/CreatePreparedStatementInterceptor.java @@ -0,0 +1,54 @@ +package com.profiler.modifier.db.mysql.interceptors; + +import com.profiler.context.Trace; +import com.profiler.interceptor.StaticAfterInterceptor; +import com.profiler.modifier.db.ConnectionTrace; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class CreatePreparedStatementInterceptor implements StaticAfterInterceptor { + private final Logger logger = Logger.getLogger(CreatePreparedStatementInterceptor.class.getName()); + + private Method setUrl = null; + + @Override + public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { + if (logger.isLoggable(Level.INFO)) { + logger.info("after " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args) + " result:" + result); + } + if (Trace.getCurrentTraceId() == null) { + return; + } + if (target instanceof Connection) { + ConnectionTrace connectionTrace = ConnectionTrace.getConnectionTrace(); + String connectionUrl = connectionTrace.getConnectionUrl((Connection) target); + setUrl(result, connectionUrl); + } + } + + private void setUrl(Object result, String connectionUrl) { + try { + if (setUrl == null) { + setUrl = result.getClass().getMethod("__setUrl", String.class); + } + setUrl.invoke(result, connectionUrl); + } catch (NoSuchMethodException e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + } catch (InvocationTargetException e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + } catch (IllegalAccessException e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + } + } +} 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 new file mode 100644 index 000000000..5e3f0a5de --- /dev/null +++ b/src/main/java/com/profiler/modifier/db/mysql/interceptors/PreparedStatementMethodInterceptor.java @@ -0,0 +1,4 @@ +package com.profiler.modifier.db.mysql.interceptors; + +public class PreparedStatementMethodInterceptor { +} diff --git a/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java b/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java index 99ea42a27..9aad41ecc 100644 --- a/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java +++ b/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java @@ -6,6 +6,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.interceptor.bci.InstrumentException; import javassist.*; import com.profiler.interceptor.Interceptor; @@ -38,20 +39,19 @@ public class EntryPointStandardHostValveModifier extends AbstractModifier { } addRequiredCladdToCurrentClassLoader(classLoader); + byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName); + classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer)); - Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.tomcat.interceptors.InvokeMethodInterceptor"); - if (interceptor == null) { - return null; - } - - byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName); - classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer)); - - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - aClass.addInterceptor("invoke", new String[] { "org.apache.catalina.connector.Request", "org.apache.catalina.connector.Response" }, interceptor); - - return aClass.toBytecode(); - } + try { + Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.tomcat.interceptors.InvokeMethodInterceptor"); + InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); + aClass.addInterceptor("invoke", new String[] { "org.apache.catalina.connector.Request", "org.apache.catalina.connector.Response" }, interceptor); + return aClass.toBytecode(); + } catch (InstrumentException e) { + logger.log(Level.WARNING, "modify fail Cause:" + e.getMessage(), e); + return null; + } + } private void addRequiredCladdToCurrentClassLoader(ClassLoader classLoader) { try { diff --git a/src/main/java/com/profiler/util/JavaAssistUtils.java b/src/main/java/com/profiler/util/JavaAssistUtils.java index 6a231bece..52ef9e521 100644 --- a/src/main/java/com/profiler/util/JavaAssistUtils.java +++ b/src/main/java/com/profiler/util/JavaAssistUtils.java @@ -3,6 +3,7 @@ package com.profiler.util; import javassist.CtClass; public class JavaAssistUtils { + private final static String NULL = "()"; /** * test(int, java.lang.String) 일경우 * (int, java.lang.String)로 생성된다. @@ -10,13 +11,16 @@ public class JavaAssistUtils { * @return */ public static String getParameterDescription(CtClass[] params) { - StringBuilder sb = new StringBuilder(); + if(params == null) { + return NULL; + } + StringBuilder sb = new StringBuilder(64); sb.append("("); - if (params != null) { - for (int i = 0; i < params.length; i++) { - sb.append(params[i].getName()); - if (i < (params.length - 1)) - sb.append(", "); + int end = params.length - 1; + for (int i = 0; i < params.length; i++) { + sb.append(params[i].getName()); + if (i < end) { + sb.append(", "); } } sb.append(")"); @@ -24,13 +28,16 @@ public class JavaAssistUtils { } public static String getParameterDescription(Class[] params) { - StringBuilder sb = new StringBuilder(); + if(params == null) { + return NULL; + } + StringBuilder sb = new StringBuilder(64); sb.append("("); - if (params != null) { - for (int i = 0; i < params.length; i++) { - sb.append(params[i].getName()); - if (i < (params.length - 1)) - sb.append(", "); + int end = params.length - 1; + for (int i = 0; i < params.length; i++) { + sb.append(params[i].getName()); + if (i < end) { + sb.append(", "); } } sb.append(")"); diff --git a/src/test/java/com/profiler/javaassist/JavaAssiastTest.java b/src/test/java/com/profiler/javaassist/JavaAssiastTest.java index a9a286a68..8c64c3267 100644 --- a/src/test/java/com/profiler/javaassist/JavaAssiastTest.java +++ b/src/test/java/com/profiler/javaassist/JavaAssiastTest.java @@ -5,6 +5,7 @@ import javassist.CtClass; import javassist.CtMethod; import javassist.NotFoundException; import javassist.bytecode.ClassFile; +import org.junit.Before; import org.junit.Test; import java.lang.reflect.Method; @@ -12,15 +13,22 @@ import java.net.URL; import java.net.URLClassLoader; public class JavaAssiastTest { + private ClassPool pool; + + @Before + public void setUp() throws Exception { + pool = new ClassPool(); + pool.appendSystemPath(); + } + @Test public void newClass() { - } @Test public void testAssist() throws NotFoundException, NoSuchMethodException { - ClassPool getDefault = ClassPool.getDefault(); - CtClass ctClass = getDefault.get(String.class.getName()); + + CtClass ctClass = pool.get(String.class.getName()); // System.out.println(ctClass) ; String s = ""; // ctClass.getMethod("valueOf", "(D)"); @@ -57,4 +65,21 @@ public class JavaAssiastTest { // new URLClassLoader() } + + @Test + public void innerClass() throws NotFoundException { + CtClass testClass = pool.get("com.profiler.javaassist.TestClass"); + System.out.println(testClass); + CtClass[] nestedClasses = testClass.getNestedClasses(); + for(CtClass nested : nestedClasses) { + System.out.println("nestedClass:" + nested); + } + + + CtClass innerClass = pool.get("com.profiler.javaassist.TestClass$InnerClass"); + System.out.println(innerClass); + + CtClass class1 = pool.get("com.profiler.javaassist.TestClass$1"); + System.out.println(class1); + } } diff --git a/src/test/java/com/profiler/javaassist/TestClass.java b/src/test/java/com/profiler/javaassist/TestClass.java new file mode 100644 index 000000000..83518b551 --- /dev/null +++ b/src/test/java/com/profiler/javaassist/TestClass.java @@ -0,0 +1,35 @@ +package com.profiler.javaassist; + +public class TestClass { + private int a; + + public int getA() { + return a; + } + + public void setA(int a) { + this.a = a; + } + + public int inlineClass(final int a) { + Comparable c = new Comparable() { + @Override + public int compareTo(Object o) { + return a; + } + }; + return c.compareTo(null); + } + + private class InnerClass { + private String str; + + public String getStr() { + return str; + } + + public void setStr(String str) { + this.str = str; + } + } +}