postgresql-jdbc.git / summary / log / commit / refs

commit    b97ad63089a9042cfef0ce97d1eaacce0fe47d4e
Author:   Dave Cramer <davecramer@gmail.com>
Commit:   GitHub <noreply@github.com>
Date:     Thu Mar 23 12:08:36 2017 +0000

    Honour setLogStream. If the logStream is set (#780)
    
    * Honour setLogStream. If the logStream is set
    then use it to output logs
    Also set the parent logger level to the log level
    requested.
    
    * Added a WriterHandler, borrowed and attributed to apache
    suppress our copyright check for that file
    added the first test case for WriterHandler
    
    * added seperate test for setLogStream
    
    * suppress the output from the logging tests
    
    * moved utility class to test


pgjdbc/pom.xml | 1 + pgjdbc/src/main/checkstyle/suppressions.xml | 9 ++ pgjdbc/src/main/java/org/postgresql/Driver.java | 23 +++- .../java/org/postgresql/util/WriterHandler.java | 125 +++++++++++++++++++++ .../java/org/postgresql/test/jdbc2/DriverTest.java | 75 +++++++++++++ .../java/org/postgresql/util/NullOutputStream.java | 29 +++++ 6 files changed, 260 insertions(+), 2 deletions(-) diff --git a/pgjdbc/pom.xml b/pgjdbc/pom.xml index 0d2ba622..f78fa4f6 100644 --- a/pgjdbc/pom.xml +++ b/pgjdbc/pom.xml @@ -266,6 +266,7 @@ </dependencies> <configuration> <configLocation>src/main/checkstyle/checks.xml</configLocation> + <suppressionsLocation>src/main/checkstyle/suppressions.xml</suppressionsLocation> <violationSeverity>error</violationSeverity> <failOnViolation>true</failOnViolation> <failsOnError>true</failsOnError> diff --git a/pgjdbc/src/main/checkstyle/suppressions.xml b/pgjdbc/src/main/checkstyle/suppressions.xml new file mode 100644 index 00000000..76e50708 --- /dev/null +++ b/pgjdbc/src/main/checkstyle/suppressions.xml @@ -0,0 +1,9 @@ +<?xml version="1.0"?> + +<!DOCTYPE suppressions PUBLIC + "-//Puppy Crawl//DTD Suppressions 1.1//EN" + "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd"> + +<suppressions> + <suppress files="WriterHandler\.java" checks="RegexpHeader"/> +</suppressions> diff --git a/pgjdbc/src/main/java/org/postgresql/Driver.java b/pgjdbc/src/main/java/org/postgresql/Driver.java index d471f4d9..27c6b486 100644 --- a/pgjdbc/src/main/java/org/postgresql/Driver.java +++ b/pgjdbc/src/main/java/org/postgresql/Driver.java @@ -6,12 +6,14 @@ package org.postgresql; import org.postgresql.jdbc.PgConnection; + import org.postgresql.util.ExpressionProperties; import org.postgresql.util.GT; import org.postgresql.util.HostSpec; import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLState; import org.postgresql.util.SharedTimer; +import org.postgresql.util.WriterHandler; import java.io.IOException; import java.io.InputStream; @@ -29,8 +31,11 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.Properties; import java.util.Set; +import java.util.logging.Formatter; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.logging.StreamHandler; /** * The Java SQL framework allows for multiple database drivers. Each driver should supply a class @@ -308,7 +313,7 @@ public class Driver implements java.sql.Driver { loggerHandlerFile = null; } - java.util.logging.Handler handler = new java.util.logging.ConsoleHandler(); + java.util.logging.Handler handler = null; if (driverLogFile != null) { try { handler = new java.util.logging.FileHandler(driverLogFile); @@ -318,7 +323,21 @@ public class Driver implements java.sql.Driver { } } - handler.setFormatter(new java.util.logging.SimpleFormatter()); + Formatter formatter = new SimpleFormatter(); + + if ( handler == null ) { + if (DriverManager.getLogWriter() != null) { + handler = new WriterHandler(DriverManager.getLogWriter()); + } else if ( DriverManager.getLogStream() != null) { + handler = new StreamHandler(DriverManager.getLogStream(), formatter); + } else { + handler = new StreamHandler(System.err, formatter); + } + } else { + handler.setFormatter(formatter); + } + + handler.setLevel(PARENT_LOGGER.getLevel()); PARENT_LOGGER.setUseParentHandlers(false); PARENT_LOGGER.addHandler(handler); } diff --git a/pgjdbc/src/main/java/org/postgresql/util/WriterHandler.java b/pgjdbc/src/main/java/org/postgresql/util/WriterHandler.java new file mode 100644 index 00000000..822f9536 --- /dev/null +++ b/pgjdbc/src/main/java/org/postgresql/util/WriterHandler.java @@ -0,0 +1,125 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.postgresql.util; + +import java.io.Writer; + +import java.util.logging.ErrorManager; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.SimpleFormatter; + +public class WriterHandler extends Handler { + + private boolean doneHeader; + + private Writer writer; + + public WriterHandler(Writer inWriter) { + super(); + setLevel(Level.INFO); + setFilter(null); + setFormatter(new SimpleFormatter()); + writer = inWriter; + } + + public WriterHandler(Writer inWriter, Formatter formatter) { + super(); + setLevel(Level.INFO); + setFilter(null); + setFormatter(formatter); + writer = inWriter; + + } + + public synchronized void publish(final LogRecord record) { + if (!isLoggable(record)) { + return; + } + String msg; + try { + msg = getFormatter().format(record); + } catch (Exception ex) { + // We don't want to throw an exception here, but we + // report the exception to any registered ErrorManager. + reportError(null, ex, ErrorManager.FORMAT_FAILURE); + return; + } + + try { + if (!doneHeader) { + writer.write(getFormatter().getHead(this)); + doneHeader = true; + } + writer.write(msg); + } catch (Exception ex) { + // We don't want to throw an exception here, but we + // report the exception to any registered ErrorManager. + reportError(null, ex, ErrorManager.WRITE_FAILURE); + } + } + + public boolean isLoggable(final LogRecord record) { + if (writer == null || record == null) { + return false; + } + return super.isLoggable(record); + } + + public synchronized void flush() { + if (writer != null) { + try { + writer.flush(); + } catch (Exception ex) { + // We don't want to throw an exception here, but we + // report the exception to any registered ErrorManager. + reportError(null, ex, ErrorManager.FLUSH_FAILURE); + } + } + } + + private synchronized void flushAndClose() throws SecurityException { + + if (writer != null) { + try { + if (!doneHeader) { + writer.write(getFormatter().getHead(this)); + doneHeader = true; + } + writer.write(getFormatter().getTail(this)); + writer.flush(); + writer.close(); + } catch (Exception ex) { + // We don't want to throw an exception here, but we + // report the exception to any registered ErrorManager. + reportError(null, ex, ErrorManager.CLOSE_FAILURE); + } + writer = null; + + } + } + + public synchronized void close() throws SecurityException { + flushAndClose(); + } +} diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DriverTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DriverTest.java index 9d26beaf..07416d81 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DriverTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DriverTest.java @@ -13,15 +13,20 @@ import static org.junit.Assert.fail; import org.postgresql.Driver; import org.postgresql.test.TestUtil; +import org.postgresql.util.NullOutputStream; +import org.postgresql.util.WriterHandler; import org.junit.Test; +import java.io.PrintWriter; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.DriverManager; import java.util.ArrayList; import java.util.Collections; import java.util.Properties; +import java.util.logging.Handler; +import java.util.logging.Logger; /* * Tests the dynamically created class org.postgresql.Driver @@ -180,4 +185,74 @@ public class DriverTest { } fail("Driver has not been found in DriverManager's list but it should be registered"); } + + @Test + public void testSetLogWriter() throws Exception { + + // this is a dummy to make sure TestUtil is initialized + Connection con = DriverManager.getConnection(TestUtil.getURL(), TestUtil.getUser(), TestUtil.getPassword()); + con.close(); + String loggerLevel = System.getProperty("loggerLevel"); + String loggerFile = System.getProperty("loggerFile"); + + try { + + PrintWriter printWriter = new PrintWriter(new NullOutputStream(System.err)); + DriverManager.setLogWriter(printWriter); + assertEquals(DriverManager.getLogWriter(), printWriter); + System.clearProperty("loggerFile"); + System.clearProperty("loggerLevel"); + Properties props = new Properties(); + props.setProperty("user", TestUtil.getUser()); + props.setProperty("password", TestUtil.getPassword()); + props.setProperty("loggerLevel", "DEBUG"); + con = DriverManager.getConnection(TestUtil.getURL(), props); + + Logger logger = Logger.getLogger("org.postgresql"); + Handler[] handlers = logger.getHandlers(); + assertTrue(handlers[0] instanceof WriterHandler ); + con.close(); + } finally { + DriverManager.setLogWriter(null); + System.setProperty("loggerLevel", loggerLevel); + System.setProperty("loggerFile", loggerFile); + + } + + } + + @Test + public void testSetLogStream() throws Exception { + + // this is a dummy to make sure TestUtil is initialized + Connection con = DriverManager.getConnection(TestUtil.getURL(), TestUtil.getUser(), TestUtil.getPassword()); + con.close(); + String loggerLevel = System.getProperty("loggerLevel"); + String loggerFile = System.getProperty("loggerFile"); + + try { + + DriverManager.setLogStream(new NullOutputStream(System.err)); + System.clearProperty("loggerFile"); + System.clearProperty("loggerLevel"); + Properties props = new Properties(); + props.setProperty("user", TestUtil.getUser()); + props.setProperty("password", TestUtil.getPassword()); + props.setProperty("loggerLevel", "DEBUG"); + con = DriverManager.getConnection(TestUtil.getURL(), props); + + Logger logger = Logger.getLogger("org.postgresql"); + Handler []handlers = logger.getHandlers(); + assertTrue( handlers[0] instanceof WriterHandler ); + con.close(); + } finally { + DriverManager.setLogStream(null); + System.setProperty("loggerLevel", loggerLevel); + System.setProperty("loggerFile", loggerFile); + + + } + + } + } diff --git a/pgjdbc/src/test/java/org/postgresql/util/NullOutputStream.java b/pgjdbc/src/test/java/org/postgresql/util/NullOutputStream.java new file mode 100644 index 00000000..764dc1ac --- /dev/null +++ b/pgjdbc/src/test/java/org/postgresql/util/NullOutputStream.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, PostgreSQL Global Development Group + * See the LICENSE file in the project root for more information. + */ + +package org.postgresql.util; + +import java.io.OutputStream; +import java.io.PrintStream; + +/** + * Created by davec on 3/14/17. + */ +public class NullOutputStream extends PrintStream { + + public NullOutputStream(OutputStream out) { + super(out); + } + + @Override + public void write(int b) { + + } + + @Override + public void write(byte[] buf, int off, int len) { + + } +} [parent: 95a3f41d6c0d]