diff --git a/src/main/java/com/alibaba/druid/mock/MockDriver.java b/src/main/java/com/alibaba/druid/mock/MockDriver.java index 2b1b562b08..1f0d902946 100644 --- a/src/main/java/com/alibaba/druid/mock/MockDriver.java +++ b/src/main/java/com/alibaba/druid/mock/MockDriver.java @@ -43,7 +43,7 @@ import com.alibaba.druid.support.logging.LogFactory; public class MockDriver implements Driver, MockDriverMBean { - private final static Log LOG = LogFactory.getLog(MockDriver.class); + private static Log LOG; public final static MockExecuteHandler DEFAULT_HANDLER = new MySqlMockExecuteHandlerImpl(); @@ -75,6 +75,14 @@ public class MockDriver implements Driver, MockDriverMBean { return logExecuteQueryEnable; } + private static Log getLog() { + if (LOG == null) { + LOG = LogFactory.getLog(MockDriver.class); + } + + return LOG; + } + public void setLogExecuteQueryEnable(boolean logExecuteQueryEnable) { this.logExecuteQueryEnable = logExecuteQueryEnable; } @@ -119,8 +127,8 @@ public class MockDriver implements Driver, MockDriverMBean { connections.remove(conn); - if (LOG.isDebugEnabled()) { - LOG.debug("conn-" + conn.getId() + " close"); + if (getLog().isDebugEnabled()) { + getLog().debug("conn-" + conn.getId() + " close"); } } @@ -136,12 +144,12 @@ public class MockDriver implements Driver, MockDriverMBean { mbeanServer.registerMBean(instance, objectName); } } catch (Exception ex) { - LOG.error("register druid-driver mbean error", ex); + getLog().error("register druid-driver mbean error", ex); } return true; } catch (Exception e) { - LOG.error("registerDriver error", e); + getLog().error("registerDriver error", e); } return false; @@ -175,8 +183,8 @@ public class MockDriver implements Driver, MockDriverMBean { MockConnection conn = createMockConnection(this, url, info); - if (LOG.isDebugEnabled()) { - LOG.debug("connect, url " + url + ", id " + conn.getId()); + if (getLog().isDebugEnabled()) { + getLog().debug("connect, url " + url + ", id " + conn.getId()); } if (url == null) { @@ -234,14 +242,14 @@ public class MockDriver implements Driver, MockDriverMBean { public boolean jdbcCompliant() { return true; } - + public MockResultSet createMockResultSet(MockStatementBase stmt) { return new MockResultSet(stmt); } public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException { - if (logExecuteQueryEnable && LOG.isDebugEnabled()) { - LOG.debug("executeQuery " + sql); + if (logExecuteQueryEnable && getLog().isDebugEnabled()) { + getLog().debug("executeQuery " + sql); } MockConnection conn = stmt.getConnection(); diff --git a/src/main/java/com/alibaba/druid/support/logging/LogFactory.java b/src/main/java/com/alibaba/druid/support/logging/LogFactory.java index 4ca712a54d..930da63210 100644 --- a/src/main/java/com/alibaba/druid/support/logging/LogFactory.java +++ b/src/main/java/com/alibaba/druid/support/logging/LogFactory.java @@ -24,24 +24,43 @@ public class LogFactory { static { // TODO add slf4j logging - - //优先选择log4j,而非Apache Common Logging. 因为后者无法设置真实Log调用者的信息 + + // 优先选择log4j,而非Apache Common Logging. 因为后者无法设置真实Log调用者的信息 tryImplementation("org.apache.log4j.Logger", "com.alibaba.druid.support.logging.Log4jImpl"); tryImplementation("java.util.logging.Logger", "com.alibaba.druid.support.logging.Jdk14LoggingImpl"); tryImplementation("org.apache.commons.logging.LogFactory", "com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl"); + + if (logConstructor == null) { + try { + logConstructor = NoLoggingImpl.class.getConstructor(Class.class); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } tryImplementation("java.lang.Object", "com.alibaba.druid.support.logging.NoLoggingImpl"); } @SuppressWarnings("unchecked") private static void tryImplementation(String testClassName, String implClassName) { - if (logConstructor == null) { - try { - Resources.classForName(testClassName); - Class implClass = Resources.classForName(implClassName); - logConstructor = implClass.getConstructor(new Class[] { Class.class }); - } catch (Throwable t) { + if (logConstructor != null) { + return; + } + + try { + Resources.classForName(testClassName); + Class implClass = Resources.classForName(implClassName); + logConstructor = implClass.getConstructor(new Class[] { Class.class }); + { + Class declareClass = logConstructor.getDeclaringClass(); + if (!Log.class.isAssignableFrom(declareClass)) { + logConstructor = null; + } else { + return; + } } + } catch (Throwable t) { + t.printStackTrace(); } } diff --git a/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java b/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java index 2ff510947e..b30b574eba 100644 --- a/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java +++ b/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java @@ -20,8 +20,10 @@ public class NoLoggingImpl implements Log { private int infoCount; private int errorCount; private int warnCount; + private Class clazz; public NoLoggingImpl(Class clazz){ + this.clazz = clazz; } public boolean isDebugEnabled() { @@ -29,11 +31,18 @@ public class NoLoggingImpl implements Log { } public void error(String s, Throwable e) { - errorCount++; + error(s); + + if (e != null) { + e.printStackTrace(); + } } public void error(String s) { errorCount++; + if (s != null) { + System.err.println(clazz.getClass().getName() + " : " + s); + } } public void debug(String s) { diff --git a/src/main/java/com/alibaba/druid/support/logging/Resources.java b/src/main/java/com/alibaba/druid/support/logging/Resources.java index 8adc0fa605..b4a9439fc5 100644 --- a/src/main/java/com/alibaba/druid/support/logging/Resources.java +++ b/src/main/java/com/alibaba/druid/support/logging/Resources.java @@ -263,7 +263,7 @@ public final class Resources extends Object { in.close(); return props; } - + /** * Loads a class * diff --git a/src/test/java/com/alibaba/druid/bvt/log/LoggerTest.java b/src/test/java/com/alibaba/druid/bvt/log/LoggerTest.java new file mode 100644 index 0000000000..7bebdc8b0e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/log/LoggerTest.java @@ -0,0 +1,102 @@ +package com.alibaba.druid.bvt.log; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.PrivilegedAction; +import java.sql.Connection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.proxy.DruidDriver; +import com.alibaba.druid.util.IOUtils; +import com.alibaba.druid.util.JdbcUtils; + +public class LoggerTest extends TestCase { + + private static java.security.ProtectionDomain DOMAIN; + + private DruidDataSource dataSource; + + static { + DOMAIN = (java.security.ProtectionDomain) java.security.AccessController.doPrivileged(new PrivilegedAction() { + + public Object run() { + return TestLoader.class.getProtectionDomain(); + } + }); + } + + public static class TestLoader extends ClassLoader { + + private ClassLoader loader; + + private Set definedSet = new HashSet(); + + public TestLoader(){ + super(null); + loader = DruidDriver.class.getClassLoader(); + } + + public URL getResource(String name) { + return loader.getResource(name); + } + + public Enumeration getResources(String name) throws IOException { + return loader.getResources(name); + } + + public Class loadClass(String name) throws ClassNotFoundException { + if (name.startsWith("java")) { + return loader.loadClass(name); + } + + if (definedSet.contains(name)) { + return super.loadClass(name); + } + + String resourceName = name.replace('.', '/') + ".class"; + InputStream is = loader.getResourceAsStream(resourceName); + if (is == null) { + throw new ClassNotFoundException(); + } + try { + byte[] bytes = IOUtils.readByteArray(is); + this.defineClass(name, bytes, 0, bytes.length, DOMAIN); + definedSet.add(name); + } catch (IOException e) { + throw new ClassNotFoundException(e.getMessage(), e); + } + try { + is.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + Class clazz = super.loadClass(name); + + return clazz; + } + } + + public void test_log() throws Exception { + TestLoader classLoader = new TestLoader(); + + Thread.currentThread().setContextClassLoader(classLoader); + dataSource = new DruidDataSource(); + dataSource.setFilters("log"); + dataSource.setUrl("jdbc:mock:xx"); + Connection conn = dataSource.getConnection(); + conn.close(); + } + + @Override + protected void tearDown() throws Exception { + JdbcUtils.close(dataSource); + } +}