Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/ByteStreamLogger.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/ByteStreamLogger.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/ByteStreamLogger.java (revision 0) @@ -0,0 +1,130 @@ +package org.apache.logging.log4j.streams; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +public class ByteStreamLogger { + private static final int BUFFER_SIZE = 1024; + + private final LoggerProvider logger; + private final Level level; + private final Marker marker; + private final ByteBufferInputStream in; + private final InputStreamReader reader; + private final char[] msgBuf = new char[BUFFER_SIZE]; + private final StringBuilder msg = new StringBuilder(); + private boolean closed; + final ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE); + + public ByteStreamLogger(final LoggerProvider logger, final Level level, final Marker marker, final Charset charset) { + this.logger = logger; + this.level = level; + this.marker = marker; + this.in = new ByteBufferInputStream(); + this.reader = new InputStreamReader(in, charset); + } + + public void put(final String fqcn, final int b) throws IOException { + if (b >= 0) { + synchronized (msg) { + buf.put((byte) (b & 0xFF)); + extractMessages(fqcn); + } + } else { + logEnd(fqcn); + } + } + + public void put(final String fqcn, final byte[] b, int off, int len) throws IOException { + if (len >= 0) { + synchronized (msg) { + while (len > buf.remaining()) { + final int remaining = buf.remaining(); + buf.put(b, off, remaining); + len -= remaining; + off += remaining; + extractMessages(fqcn); + } + buf.put(b, off, len); + extractMessages(fqcn); + } + } else { + logEnd(fqcn); + } + } + + public void close(String fqcn) { + synchronized (msg) { + closed = true; + logEnd(fqcn); + } + } + + private void extractMessages(final String fqcn) throws IOException { + if (closed) { + return; + } + int read = reader.read(msgBuf); + while (read > 0) { + int off = 0; + for (int pos = 0; pos < read; pos++) { + switch (msgBuf[pos]) { + case '\r': + msg.append(msgBuf, off, pos - off); + off = pos + 1; + break; + case '\n': + msg.append(msgBuf, off, pos - off); + off = pos + 1; + log(fqcn); + break; + } + } + msg.append(msgBuf, off, read - off); + read = reader.read(msgBuf); + } + } + + private void logEnd(final String fqcn) { + if (msg.length() > 0) { + log(fqcn); + } + } + + private void log(final String fqcn) { + // convert to string now so async loggers work + logger.logIfEnabled(fqcn, level, marker, msg.toString()); + msg.setLength(0); + } + + private class ByteBufferInputStream extends InputStream { + + public int read() throws IOException { + buf.flip(); + int result = -1; + if (buf.limit() > 0) { + result = buf.get() & 0xFF; + } + buf.compact(); + return result; + } + + public int read(byte[] bytes, int off, int len) throws IOException { + buf.flip(); + int result = -1; + if (buf.limit() > 0) { + result = Math.min(len, buf.limit()); + buf.get(bytes, off, result); + } + buf.compact(); + return result; + } + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/CharStreamLogger.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/CharStreamLogger.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/CharStreamLogger.java (revision 0) @@ -0,0 +1,93 @@ +package org.apache.logging.log4j.streams; + +import java.nio.CharBuffer; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +public class CharStreamLogger { + private final LoggerProvider logger; + private final Level level; + private final Marker marker; + private final StringBuilder msg = new StringBuilder(); + private boolean closed = false; + + public CharStreamLogger(final LoggerProvider logger, final Level level, final Marker marker) { + this.logger = logger; + this.level = level; + this.marker = marker; + } + + public void put(final String fqcn, final int c) { + if (c >= 0) { + synchronized (msg) { + if (closed) { + return; + } + switch (c) { + case '\n': + log(fqcn); + break; + case '\r': + break; + default: + msg.append((char) c); + } + } + } else { + logEnd(fqcn); + } + } + + public void put(final String fqcn, final char[] cbuf, final int off, final int len) { + put(fqcn, CharBuffer.wrap(cbuf), off, len); + } + + public void put(final String fqcn, final CharSequence str, final int off, final int len) { + if (len >= 0) { + synchronized (msg) { + if (closed) { + return; + } + int start = off; + final int end = off + len; + for (int pos = off; pos < end; pos++) { + char c = str.charAt(pos); + switch (c) { + case '\r': + case '\n': + msg.append(str, start, pos); + start = pos + 1; + if (c == '\n') { + log(fqcn); + } + break; + } + } + msg.append(str, start, end); + } + } else { + logEnd(fqcn); + } + } + + public void close(final String fqcn) { + synchronized (msg) { + closed = true; + logEnd(fqcn); + } + } + + private void logEnd(final String fqcn) { + if (msg.length() > 0) { + log(fqcn); + } + } + + private void log(final String fqcn) { + logger.logIfEnabled(fqcn, level, marker, msg.toString()); // convert to string now so async loggers + // work + msg.setLength(0); + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerBufferedInputStream.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerBufferedInputStream.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerBufferedInputStream.java (revision 0) @@ -0,0 +1,88 @@ +package org.apache.logging.log4j.streams; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +public class LoggerBufferedInputStream extends BufferedInputStream { + private final static String FQCN = LoggerBufferedInputStream.class.getName(); + + public LoggerBufferedInputStream(final InputStream in, final Logger logger, final Level level) { + this(in, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerBufferedInputStream(final InputStream in, final Charset charset, final Logger logger, final Level level) { + this(in, charset, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerBufferedInputStream(final InputStream in, final Logger logger, final Level level, final Marker marker) { + this(in, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerBufferedInputStream(final InputStream in, final Charset charset, final Logger logger, final Level level, final Marker marker) { + this(in, charset, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerBufferedInputStream(final InputStream in, final int sz, final Logger logger, final Level level) { + this(in, sz, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerBufferedInputStream(final InputStream in, final Charset charset, final int sz, final Logger logger, final Level level) { + this(in, charset, sz, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerBufferedInputStream(final InputStream in, final int sz, final Logger logger, final Level level, final Marker marker) { + this(in, sz, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerBufferedInputStream(final InputStream in, final Charset charset, final int sz, final Logger logger, final Level level, final Marker marker) { + this(in, charset, sz, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerBufferedInputStream(final InputStream in, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + this(in, Charset.defaultCharset(), logger, fqcn, level, marker); + } + + public LoggerBufferedInputStream(final InputStream in, final Charset charset, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + super(new LoggerInputStream(in, charset, logger, fqcn, level, marker)); + } + + public LoggerBufferedInputStream(final InputStream in, final int sz, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + this(in, Charset.defaultCharset(), sz, logger, fqcn, level, marker); + } + + public LoggerBufferedInputStream(final InputStream in, final Charset charset, final int sz, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + super(new LoggerInputStream(in, charset, logger, fqcn, level, marker), sz); + } + + @Override + public void close() throws IOException { + super.close(); + } + + @Override + public synchronized int read() throws IOException { + return super.read(); + } + + @Override + public int read(byte[] b) throws IOException { + return super.read(b, 0, b.length); + } + + @Override + public synchronized int read(byte[] b, int off, int len) throws IOException { + return super.read(b, off, len); + } + + @Override + public String toString() { + return LoggerBufferedInputStream.class.getSimpleName() + "{stream=" + in + '}'; + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerBufferedReader.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerBufferedReader.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerBufferedReader.java (revision 0) @@ -0,0 +1,75 @@ +package org.apache.logging.log4j.streams; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +public class LoggerBufferedReader extends BufferedReader { + private final static String FQCN = LoggerBufferedReader.class.getName(); + + public LoggerBufferedReader(final Reader reader, final Logger logger, final Level level) { + this(reader, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerBufferedReader(final Reader reader, final Logger logger, final Level level, final Marker marker) { + this(reader, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerBufferedReader(final Reader reader, final int sz, final Logger logger, final Level level) { + this(reader, sz, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerBufferedReader(final Reader reader, final int sz, final Logger logger, final Level level, final Marker marker) { + this(reader, sz, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerBufferedReader(final Reader reader, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + super(new LoggerReader(reader, logger, FQCN, level, marker)); + } + + public LoggerBufferedReader(final Reader reader, final int sz, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + super(new LoggerReader(reader, logger, FQCN, level, marker), sz); + } + + @Override + public void close() throws IOException { + super.close(); + } + + @Override + public int read() throws IOException { + return super.read(); + } + + @Override + public int read(char[] cbuf) throws IOException { + return super.read(cbuf, 0, cbuf.length); + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + return super.read(cbuf, off, len); + } + + @Override + public int read(CharBuffer target) throws IOException { + int len = target.remaining(); + char[] cbuf = new char[len]; + int charsRead = read(cbuf, 0, len); + if (charsRead > 0) { + target.put(cbuf, 0, charsRead); + } + return charsRead; + } + + @Override + public String readLine() throws IOException { + return super.readLine(); + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerInputStream.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerInputStream.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerInputStream.java (revision 0) @@ -0,0 +1,90 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +/** + * Input stream that logs each line read to a pre-defined level. Can also be configured with a + * Marker. + */ +public class LoggerInputStream extends FilterInputStream { + private static final String FQCN = LoggerInputStream.class.getName(); + + private final String fqcn; + private final ByteStreamLogger logger; + + public LoggerInputStream(final InputStream in, final Logger logger, final Level level) { + this(in, Charset.defaultCharset(), (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerInputStream(final InputStream in, final Charset charset, final Logger logger, final Level level) { + this(in, charset, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerInputStream(final InputStream in, final Logger logger, final Level level, final Marker marker) { + this(in, Charset.defaultCharset(), (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerInputStream(final InputStream in, final Charset charset, final Logger logger, final Level level, final Marker marker) { + this(in, charset, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerInputStream(final InputStream in, final Charset charset, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + super(in); + this.logger = new ByteStreamLogger(logger, level, marker, charset); + this.fqcn = fqcn; + } + + @Override + public int read() throws IOException { + final int b = super.read(); + logger.put(fqcn, b); + return b; + } + + @Override + public int read(final byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + int bytesRead = super.read(b, off, len); + logger.put(fqcn, b, off, bytesRead); + return bytesRead; + } + + @Override + public void close() throws IOException { + logger.close(fqcn); + super.close(); + } + + @Override + public String toString() { + return LoggerInputStream.class.getSimpleName() + "{stream=" + in + '}'; + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerOutputStream.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerOutputStream.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerOutputStream.java (revision 0) @@ -0,0 +1,124 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +/** + * Output stream that logs each line written to a pre-defined level. Can also be configured with a + * Marker. This class provides an interface that follows the {@link java.io.OutputStream} methods in + * spirit, but doesn't require output to any external stream. This class should not be used + * as a stream for an underlying logger unless it's being used as a bridge. Otherwise, infinite + * loops may occur! + */ +public class LoggerOutputStream extends OutputStream { + private static final String FQCN = LoggerOutputStream.class.getName(); + + private final OutputStream out; + private final ByteStreamLogger logger; + private final String fqcn; + + public LoggerOutputStream(final Logger logger, final Level level) { + this(null, Charset.defaultCharset(), (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerOutputStream(final Charset charset, final Logger logger, final Level level) { + this(null, charset, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerOutputStream(final Logger logger, final Level level, final Marker marker) { + this(null, Charset.defaultCharset(), (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerOutputStream(final Charset charset, final Logger logger, final Level level, final Marker marker) { + this(null, charset, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerOutputStream(final OutputStream out, final Logger logger, final Level level) { + this(out, Charset.defaultCharset(), (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerOutputStream(final OutputStream out, final Charset charset, final Logger logger, final Level level) { + this(out, charset, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerOutputStream(final OutputStream out, final Logger logger, final Level level, final Marker marker) { + this(out, Charset.defaultCharset(), (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerOutputStream(final OutputStream out, final Charset charset, final Logger logger, final Level level, final Marker marker) { + this(out, charset, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerOutputStream(final OutputStream out, final Charset charset, final LoggerProvider logger, final String fqcn, final Level level, + final Marker marker) { + this.out = out; + this.logger = new ByteStreamLogger(logger, level, marker, charset); + this.fqcn = fqcn; + } + + @Override + public void write(final int b) throws IOException { + if (out != null) { + out.write(b); + } + logger.put(fqcn, (byte) (b & 0xFF)); + } + + @Override + public void write(byte[] b) throws IOException { + if (out != null) { + out.write(b); + } + logger.put(fqcn, b, 0, b.length); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (out != null) { + out.write(b, off, len); + } + logger.put(fqcn, b, off, len); + } + + @Override + public void flush() throws IOException { + if (out != null) { + out.flush(); + } + } + + @Override + public void close() throws IOException { + if (out != null) { + out.close(); + } + logger.close(fqcn); + } + + @Override + public String toString() { + return LoggerOutputStream.class.getSimpleName() + "{stream=" + out + '}'; + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerPrintStream.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerPrintStream.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerPrintStream.java (revision 0) @@ -0,0 +1,272 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.Locale; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +/** + * Output stream that logs each line written to a pre-defined level. Can also be configured with a + * Marker. This class provides an interface that follows the {@link java.io.PrintStream} methods in + * spirit, but doesn't require output to any external stream. This class should not be used + * as a stream for an underlying logger unless it's being used as a bridge. Otherwise, infinite + * loops may occur! + */ +public class LoggerPrintStream extends PrintStream { + private static final String FQCN = LoggerPrintStream.class.getName(); + + public LoggerPrintStream(final Logger logger, final Level level) { + this(null, false, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintStream(final Charset charset, final Logger logger, final Level level) throws UnsupportedEncodingException { + this(null, false, charset, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintStream(final Logger logger, final Level level, final Marker marker) { + this(null, false, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintStream(final Charset charset, final Logger logger, final Level level, final Marker marker) throws UnsupportedEncodingException { + this(null, false, charset, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintStream(final OutputStream out, final Logger logger, final Level level) { + this(out, false, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintStream(final OutputStream out, final Charset charset, final Logger logger, final Level level) throws UnsupportedEncodingException { + this(out, false, charset, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintStream(final OutputStream out, final Logger logger, final Level level, final Marker marker) { + this(out, false, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintStream(final OutputStream out, final Charset charset, final Logger logger, final Level level, final Marker marker) + throws UnsupportedEncodingException { + this(out, false, charset, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintStream(final OutputStream out, final boolean autoFlush, final Logger logger, final Level level) { + this(out, autoFlush, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintStream(final OutputStream out, final boolean autoFlush, final Charset charset, final Logger logger, final Level level) + throws UnsupportedEncodingException { + this(out, autoFlush, charset, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintStream(final OutputStream out, final boolean autoFlush, final Logger logger, final Level level, final Marker marker) { + this(out, autoFlush, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintStream(final OutputStream out, final boolean autoFlush, final Charset charset, final Logger logger, final Level level, final Marker marker) + throws UnsupportedEncodingException { + this(out, autoFlush, charset, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintStream(final OutputStream out, boolean autoFlush, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + super(new LoggerOutputStream(out, Charset.defaultCharset(), logger, fqcn, level, marker), autoFlush); + } + + public LoggerPrintStream(final OutputStream out, boolean autoFlush, final Charset charset, final LoggerProvider logger, final String fqcn, + final Level level, final Marker marker) throws UnsupportedEncodingException { + super(new LoggerOutputStream(out, charset, logger, fqcn, level, marker), autoFlush, charset.name()); + } + + @Override + public void write(int b) { + super.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + super.write(b); + } + + @Override + public void write(byte[] b, int off, int len) { + super.write(b, off, len); + } + + @Override + public void flush() { + super.flush(); + } + + @Override + public void close() { + super.close(); + } + + @Override + public void print(boolean b) { + super.print(b); + } + + @Override + public void print(char c) { + super.print(c); + } + + @Override + public void print(int i) { + super.print(i); + } + + @Override + public void print(long l) { + super.print(l); + } + + @Override + public void print(float f) { + super.print(f); + } + + @Override + public void print(double d) { + super.print(d); + } + + @Override + public void print(char[] s) { + super.print(s); + } + + @Override + public void print(String s) { + super.print(s); + } + + @Override + public void print(Object obj) { + super.print(obj); + } + + @Override + public void println() { + super.println(); + } + + @Override + public void println(boolean x) { + super.println(x); + } + + @Override + public void println(char x) { + super.println(x); + } + + @Override + public void println(int x) { + super.println(x); + } + + @Override + public void println(long x) { + super.println(x); + } + + @Override + public void println(float x) { + super.println(x); + } + + @Override + public void println(double x) { + super.println(x); + } + + @Override + public void println(char[] x) { + super.println(x); + } + + @Override + public void println(String x) { + super.println(x); + } + + @Override + public void println(Object x) { + super.println(x); + } + + @Override + public LoggerPrintStream printf(String format, Object... args) { + super.printf(format, args); + return this; + } + + @Override + public LoggerPrintStream printf(Locale l, String format, Object... args) { + super.printf(l, format, args); + return this; + } + + @Override + public LoggerPrintStream append(char c) { + super.append(c); + return this; + } + + @Override + public LoggerPrintStream append(CharSequence csq) { + super.append(csq); + return this; + } + + @Override + public LoggerPrintStream append(CharSequence csq, int start, int end) { + super.append(csq, start, end); + return this; + } + + @Override + public LoggerPrintStream format(String format, Object... args) { + super.format(format, args); + return this; + } + + @Override + public LoggerPrintStream format(Locale l, String format, Object... args) { + super.format(l, format, args); + return this; + } + + @Override + public boolean checkError() { + return super.checkError(); + } + + @Override + public String toString() { + return LoggerPrintStream.class.getSimpleName() + "{stream=" + out + '}'; + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerPrintWriter.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerPrintWriter.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerPrintWriter.java (revision 0) @@ -0,0 +1,246 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Locale; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +/** + * Print Writer that logs each line written to a pre-defined level. Can also be configured with a + * Marker. This class provides an interface that follows the {@link java.io.PrintWriter} methods in + * spirit, but doesn't require output to any external writer. + */ +public class LoggerPrintWriter extends PrintWriter { + private static final String FQCN = LoggerPrintWriter.class.getName(); + + public LoggerPrintWriter(final Logger logger, final Level level) { + this(null, false, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintWriter(final Logger logger, final Level level, final Marker marker) { + this(null, false, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintWriter(final Writer writer, final Logger logger, final Level level) { + this(writer, false, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintWriter(final Writer writer, final Logger logger, final Level level, final Marker marker) { + this(writer, false, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintWriter(final Writer writer, final boolean autoFlush, final Logger logger, final Level level) { + this(writer, autoFlush, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerPrintWriter(final Writer writer, final boolean autoFlush, final Logger logger, final Level level, final Marker marker) { + this(writer, autoFlush, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerPrintWriter(final Writer writer, boolean autoFlush, final LoggerProvider logger, final String fqcn, + final Level level, final Marker marker) { + super(new LoggerWriter(writer, logger, fqcn, level, marker), autoFlush); + } + + @Override + public void write(int c) { + super.write(c); + } + + @Override + public void write(char[] buf) { + super.write(buf); + } + + @Override + public void write(char[] buf, int off, int len) { + super.write(buf, off, len); + } + + @Override + public void write(String s) { + super.write(s); + } + + @Override + public void write(String s, int off, int len) { + super.write(s, off, len); + } + + @Override + public void flush() { + super.flush(); + } + + @Override + public void close() { + super.close(); + } + + @Override + public void print(boolean b) { + super.print(b); + } + + @Override + public void print(char c) { + super.print(c); + } + + @Override + public void print(int i) { + super.print(i); + } + + @Override + public void print(long l) { + super.print(l); + } + + @Override + public void print(float f) { + super.print(f); + } + + @Override + public void print(double d) { + super.print(d); + } + + @Override + public void print(char[] s) { + super.print(s); + } + + @Override + public void print(String s) { + super.print(s); + } + + @Override + public void print(Object obj) { + super.print(obj); + } + + @Override + public void println() { + super.println(); + } + + @Override + public void println(boolean x) { + super.println(x); + } + + @Override + public void println(char x) { + super.println(x); + } + + @Override + public void println(int x) { + super.println(x); + } + + @Override + public void println(long x) { + super.println(x); + } + + @Override + public void println(float x) { + super.println(x); + } + + @Override + public void println(double x) { + super.println(x); + } + + @Override + public void println(char[] x) { + super.println(x); + } + + @Override + public void println(String x) { + super.println(x); + } + + @Override + public void println(Object x) { + super.println(x); + } + + @Override + public LoggerPrintWriter printf(String format, Object... args) { + super.printf(format, args); + return this; + } + + @Override + public LoggerPrintWriter printf(Locale l, String format, Object... args) { + super.printf(l, format, args); + return this; + } + + @Override + public LoggerPrintWriter append(char c) { + super.append(c); + return this; + } + + @Override + public LoggerPrintWriter append(CharSequence csq) { + super.append(csq); + return this; + } + + @Override + public LoggerPrintWriter append(CharSequence csq, int start, int end) { + super.append(csq, start, end); + return this; + } + + @Override + public LoggerPrintWriter format(String format, Object... args) { + super.format(format, args); + return this; + } + + @Override + public LoggerPrintWriter format(Locale l, String format, Object... args) { + super.format(l, format, args); + return this; + } + + @Override + public boolean checkError() { + return super.checkError(); + } + + @Override + public String toString() { + return LoggerPrintWriter.class.getSimpleName() + "{stream=" + out + '}'; + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerReader.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerReader.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerReader.java (revision 0) @@ -0,0 +1,94 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.FilterReader; +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +/** + * Writer that logs each line written to a pre-defined level. Can also be configured with a Marker. + * This class provides an interface that follows the {@link java.io.Writer} methods in spirit, but + * doesn't require output to any external writer. + */ +public class LoggerReader extends FilterReader { + private final static String FQCN = LoggerReader.class.getName(); + + private final CharStreamLogger logger; + private final String fqcn; + + public LoggerReader(final Reader reader, final Logger logger, final Level level) { + this(reader, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerReader(final Reader reader, final Logger logger, final Level level, final Marker marker) { + this(reader, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerReader(final Reader reader, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + super(reader); + this.logger = new CharStreamLogger(logger, level, marker); + this.fqcn = fqcn; + } + + @Override + public int read() throws IOException { + final int c = super.read(); + logger.put(fqcn, c); + return c; + } + + @Override + public int read(final char[] cbuf) throws IOException { + return read(cbuf, 0, cbuf.length); + } + + @Override + public int read(final char[] cbuf, final int off, final int len) throws IOException { + final int charsRead = super.read(cbuf, off, len); + logger.put(fqcn, cbuf, off, charsRead); + return charsRead; + } + + @Override + public int read(CharBuffer target) throws IOException { + int len = target.remaining(); + char[] cbuf = new char[len]; + int charsRead = read(cbuf, 0, len); + if (charsRead > 0) { + target.put(cbuf, 0, charsRead); + } + return charsRead; + } + + @Override + public void close() throws IOException { + super.close(); + logger.close(fqcn); + } + + @Override + public String toString() { + return LoggerReader.class.getSimpleName() + "{stream=" + in + '}'; + } +} Index: log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerWriter.java =================================================================== --- log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerWriter.java (revision 0) +++ log4j-streams/src/main/java/org/apache/logging/log4j/streams/LoggerWriter.java (revision 0) @@ -0,0 +1,120 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.LoggerProvider; + +/** + * Writer that logs each line written to a pre-defined level. Can also be configured with a Marker. + * This class provides an interface that follows the {@link java.io.Writer} methods in spirit, but + * doesn't require output to any external writer. + */ +public class LoggerWriter extends Writer { + private final static String FQCN = LoggerWriter.class.getName(); + + private final Writer writer; + private final CharStreamLogger logger; + private final String fqcn; + + public LoggerWriter(final Logger logger, final Level level) { + this(null, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerWriter(final Logger logger, final Level level, final Marker marker) { + this(null, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerWriter(final Writer writer, final Logger logger, final Level level) { + this(writer, (LoggerProvider) logger, FQCN, level, null); + } + + public LoggerWriter(final Writer writer, final Logger logger, final Level level, final Marker marker) { + this(writer, (LoggerProvider) logger, FQCN, level, marker); + } + + public LoggerWriter(final Writer writer, final LoggerProvider logger, final String fqcn, final Level level, final Marker marker) { + this.writer = writer; + this.logger = new CharStreamLogger(logger, level, marker); + this.fqcn = fqcn; + } + + @Override + public void write(final int c) throws IOException { + if (writer != null) { + writer.write(c); + } + logger.put(fqcn, (char) c); + } + + @Override + public void write(final char[] cbuf) throws IOException { + if (writer != null) { + writer.write(cbuf); + } + logger.put(fqcn, cbuf, 0, cbuf.length); + } + + @Override + public void write(final char[] cbuf, final int off, final int len) throws IOException { + if (writer != null) { + writer.write(cbuf, off, len); + } + logger.put(fqcn, cbuf, off, len); + } + + @Override + public void write(final String str) throws IOException { + if (writer != null) { + writer.write(str); + } + logger.put(fqcn, str, 0, str.length()); + } + + @Override + public void write(final String str, final int off, final int len) throws IOException { + if (writer != null) { + writer.write(str, off, len); + } + logger.put(fqcn, str, off, len); + } + + @Override + public void flush() throws IOException { + if (writer != null) { + writer.flush(); + } + } + + @Override + public void close() throws IOException { + if (writer != null) { + writer.close(); + } + logger.close(fqcn); + } + + @Override + public String toString() { + return LoggerWriter.class.getSimpleName() + "{stream=" + writer + '}'; + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedInputStreamCallerInfoTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedInputStreamCallerInfoTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedInputStreamCallerInfoTest.java (revision 0) @@ -0,0 +1,66 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.junit.Before; +import org.junit.Test; + +public class LoggerBufferedInputStreamCallerInfoTest extends LoggerStreamsCallerInfoTesting { + + private LoggerBufferedInputStream logIn; + + @Before + public void setupStreams() { + final InputStream srcInputStream = new ByteArrayInputStream("a\nb\nc\nd".getBytes()); + logIn = new LoggerBufferedInputStream(srcInputStream, getLogger(), LEVEL); + } + + @Test + public void read() throws Exception { + logIn.read(); + + assertMessages("read", 3, "read"); + logIn.close(); + } + + @Test + public void readBytes() throws Exception { + logIn.read(new byte[2]); + + assertMessages("read", 3, "readBytes"); + logIn.close(); + } + + @Test + public void readBytesOffsetLen() throws Exception { + logIn.read(new byte[2], 0, 2); + + assertMessages("read", 3, "readBytesOffsetLen"); + logIn.close(); + } + + @Test + public void close() throws Exception { + logIn.read(); + assertMessages("before close", 3, "close"); + logIn.close(); + assertMessages("after close", 4, "close"); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedInputStreamTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedInputStreamTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedInputStreamTest.java (revision 0) @@ -0,0 +1,29 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.InputStream; + +import org.apache.logging.log4j.Level; + +public class LoggerBufferedInputStreamTest extends LoggerInputStreamTest { + + @Override + protected InputStream createInputStream() { + return new LoggerBufferedInputStream(wrapped, getLogger(), Level.ERROR); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedReaderCallerInfoTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedReaderCallerInfoTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedReaderCallerInfoTest.java (revision 0) @@ -0,0 +1,84 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.Reader; +import java.io.StringReader; +import java.nio.CharBuffer; + +import org.apache.logging.log4j.Level; +import org.junit.Before; +import org.junit.Test; + +public class LoggerBufferedReaderCallerInfoTest extends LoggerStreamsCallerInfoTesting { + + LoggerBufferedReader logReader; + + @Before + public void setupReader() { + final Reader srcReader = new StringReader("a\nb\nc\nd"); + logReader = new LoggerBufferedReader(srcReader, getLogger(), Level.WARN); + } + + @Test + public void read() throws Exception { + logReader.read(); + + assertMessages("read", 3, "read"); + logReader.close(); + } + + @Test + public void readCbuf() throws Exception { + logReader.read(new char[2]); + + assertMessages("read", 3, "readCbuf"); + logReader.close(); + } + + @Test + public void readCbufOffset() throws Exception { + logReader.read(new char[2], 0, 2); + + assertMessages("read", 3, "readCbufOffset"); + logReader.close(); + } + + @Test + public void readCharBuffer() throws Exception { + logReader.read(CharBuffer.allocate(2)); + + assertMessages("read", 3, "readCharBuffer"); + logReader.close(); + } + + @Test + public void readLine() throws Exception { + logReader.readLine(); + + assertMessages("read", 3, "readLine"); + logReader.close(); + } + + @Test + public void close() throws Exception { + logReader.readLine(); + assertMessages("before close", 3, "close"); + logReader.close(); + assertMessages("after close", 4, "close"); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedReaderTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedReaderTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerBufferedReaderTest.java (revision 0) @@ -0,0 +1,41 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.Reader; + +import org.junit.Test; + +public class LoggerBufferedReaderTest extends LoggerReaderTest { + private BufferedReader reader; + + @Override + protected Reader createReader() { + return this.reader = new LoggerBufferedReader(wrapped, getLogger(), LEVEL); + } + + @Test + public void testReadLine() throws Exception { + assertEquals("first line", FIRST, reader.readLine()); + assertMessages(FIRST); + assertEquals("second line", LAST, reader.readLine()); + assertMessages(FIRST, LAST); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerInputStreamCallerInfoTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerInputStreamCallerInfoTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerInputStreamCallerInfoTest.java (revision 0) @@ -0,0 +1,54 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.apache.logging.log4j.Level; +import org.junit.Before; +import org.junit.Test; + +public class LoggerInputStreamCallerInfoTest extends LoggerStreamsCallerInfoTesting { + + private LoggerInputStream logIn; + + @Before + public void setupStreams() { + final InputStream srcInputStream = new ByteArrayInputStream("a\nb\nc\nd".getBytes()); + logIn = new LoggerInputStream(srcInputStream, getLogger(), Level.WARN); + } + + @Test + public void read() throws Exception { + logIn.read(); + assertMessages("before read int size", 0, "read"); + logIn.read(); + assertMessages("after read int size", 1, "read"); + + logIn.read(new byte[2]); + assertMessages("after read bytes size", 2, "read"); + + logIn.read(new byte[2], 0, 2); + assertMessages("after read bytes offset size", 3, "read"); + + logIn.read(); + assertMessages("before close size", 3, "read"); + logIn.close(); + assertMessages("after close size", 4, "read"); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerInputStreamTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerInputStreamTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerInputStreamTest.java (revision 0) @@ -0,0 +1,127 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.junit.Before; +import org.junit.Test; + +public class LoggerInputStreamTest extends StreamTesting { + protected ByteArrayInputStream wrapped; + protected ByteArrayOutputStream read; + protected InputStream in; + + @Before + public void createStream() { + wrapped = new ByteArrayInputStream((FIRST + "\r\n" + LAST).getBytes()); + read = new ByteArrayOutputStream(); + in = createInputStream(); + } + + protected InputStream createInputStream() { + return new LoggerInputStream(wrapped, getLogger(), LEVEL); + } + + @Test + public void testRead_int() throws Exception { + for (int i = 0; i < FIRST.length(); i++) { + read.write(in.read()); + } + if (!(in instanceof BufferedInputStream)) { + assertMessages(); + } + assertEquals("carriage return", '\r', in.read()); + if (!(in instanceof BufferedInputStream)) { + assertMessages(); + } + assertEquals("newline", '\n', in.read()); + assertMessages(FIRST); + } + + @Test + public void testRead_ByteArray() throws Exception { + final byte[] bytes = new byte[FIRST.length()]; + assertEquals("len", bytes.length, in.read(bytes)); + if (!(in instanceof BufferedInputStream)) { + assertMessages(); + } + in.read(bytes); + assertMessages(FIRST); + } + + @Test + public void testRead_ByteArray_Offset_Length() throws Exception { + final byte[] bytes = new byte[FIRST.length() * 2]; + assertEquals("len", FIRST.length(), in.read(bytes, 0, FIRST.length())); + if (!(in instanceof BufferedInputStream)) { + assertMessages(); + } + in.read(bytes); + assertMessages(FIRST); + } + + @Test + public void testRead_IgnoresWindowsNewline() throws IOException { + final byte[] bytes = new byte[1024]; + int len = in.read(bytes); + read.write(bytes, 0, len); + assertMessages(FIRST); + assertEquals(FIRST + "\r\n" + LAST, read.toString()); + in.close(); + assertMessages(FIRST, LAST); + } + + @Test + public void testRead_MultipleLines() throws IOException { + wrapped = new ByteArrayInputStream((FIRST + "\n" + LAST + '\n').getBytes()); + in = new LoggerInputStream(wrapped, getLogger(), LEVEL); + + final byte[] bytes = new byte[1024]; + int len = in.read(bytes); + read.write(bytes, 0, len); + assertMessages(FIRST, LAST); + assertEquals(FIRST + '\n' + LAST + '\n', read.toString()); + } + + @Test + public void testClose_NoRemainingData() throws IOException { + wrapped = new ByteArrayInputStream((FIRST + '\n').getBytes()); + in = new LoggerInputStream(wrapped, getLogger(), LEVEL); + + final byte[] bytes = new byte[1024]; + in.read(bytes); + assertMessages(FIRST); + in.close(); + assertMessages(FIRST); + } + + @Test + public void testClose_HasRemainingData() throws IOException { + final byte[] bytes = new byte[1024]; + in.read(bytes); + assertMessages(FIRST); + in.close(); + assertMessages(FIRST, LAST); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerOutputStreamCallerInfoTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerOutputStreamCallerInfoTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerOutputStreamCallerInfoTest.java (revision 0) @@ -0,0 +1,50 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import org.apache.logging.log4j.Level; +import org.junit.Before; +import org.junit.Test; + +public class LoggerOutputStreamCallerInfoTest extends LoggerStreamsCallerInfoTesting { + + private LoggerOutputStream logOut; + + @Before + public void setupStreams() { + logOut = new LoggerOutputStream(getLogger(), Level.WARN); + } + + @Test + public void write() throws Exception { + logOut.write('a'); + assertMessages("before write int", 0, "write"); + logOut.write('\n'); + assertMessages("after write int", 1, "write"); + + logOut.write("b\n".getBytes()); + assertMessages("after write byte array", 2, "write"); + + logOut.write("c\n".getBytes(), 0, 2); + assertMessages("after write byte array offset size", 3, "write"); + + logOut.write('d'); + assertMessages("before close size", 3, "write"); + logOut.close(); + assertMessages("after close size", 4, "write"); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerOutputStreamTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerOutputStreamTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerOutputStreamTest.java (revision 0) @@ -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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.logging.log4j.Level; +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +public class LoggerOutputStreamTest extends StreamTesting { + protected ByteArrayOutputStream wrapped; + protected OutputStream out; + + @Before + public void createStream() { + wrapped = new ByteArrayOutputStream(); + out = createOutputStream(); + } + + protected OutputStream createOutputStream() { + return new LoggerOutputStream(wrapped, getLogger(), Level.ERROR); + } + + @Test + public void testWrite_Int() throws Exception { + for (byte b : "int".getBytes()) { + out.write(b); + assertMessages(); + } + out.write('\n'); + assertMessages("int"); + assertEquals("int" + '\n', wrapped.toString()); + } + + @Test + public void testWrite_ByteArray() throws Exception { + final byte[] bytes = "byte[]".getBytes(); + out.write(bytes); + assertMessages(); + out.write('\n'); + assertMessages("byte[]"); + assertEquals("byte[]\n", wrapped.toString()); + } + + @Test + public void testWrite_ByteArray_Offset_Length() throws Exception { + final byte[] bytes = "byte[]".getBytes(); + int middle = bytes.length/2; + int length = bytes.length - middle; + final String right = new String(bytes, middle, length); + out.write(bytes, middle, length); + assertMessages(); + out.write('\n'); + assertMessages(right); + assertEquals("byte[]".substring(middle, bytes.length) + '\n', wrapped.toString()); + } + + @Test + public void testWrite_IgnoresWindowsNewline() throws IOException { + out.write(FIRST.getBytes()); + out.write("\r\n".getBytes()); + out.write(LAST.getBytes()); + out.close(); + assertMessages(FIRST, LAST); + assertEquals(FIRST + "\r\n" + LAST, wrapped.toString()); + } + + @Test + public void testWrite_MultipleLines() throws IOException { + out.write((FIRST + '\n' + LAST + '\n').getBytes()); + assertMessages(FIRST, LAST); + assertEquals(FIRST + '\n' + LAST + '\n', wrapped.toString()); + } + + @Test + public void testFlush() throws IOException { + final OutputStream out = EasyMock.createMock("out", OutputStream.class); + out.flush(); // expect the flush to come through to the mocked OutputStream + out.close(); + replay(out); + + final LoggerOutputStream los = new LoggerOutputStream(out, getLogger(), LEVEL); + los.flush(); + los.close(); + verify(out); + } + + @Test + public void testClose_NoRemainingData() throws IOException { + out.close(); + assertMessages(); + assertEquals("", wrapped.toString()); + } + + @Test + public void testClose_HasRemainingData() throws IOException { + out.write(FIRST.getBytes()); + assertMessages(); + out.close(); + assertMessages(FIRST); + assertEquals(FIRST, wrapped.toString()); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintStreamCallerInfoTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintStreamCallerInfoTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintStreamCallerInfoTest.java (revision 0) @@ -0,0 +1,145 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.util.Locale; + +import org.apache.logging.log4j.Level; +import org.junit.Before; +import org.junit.Test; + +public class LoggerPrintStreamCallerInfoTest extends LoggerStreamsCallerInfoTesting { + + private LoggerPrintStream logOut; + + @Before + public void setupStreams() { + logOut = new LoggerPrintStream(getLogger(), Level.WARN); + } + + @Test + public void write_int() throws Exception { + logOut.write('a'); + assertMessages("write int", 0, "write_int"); + logOut.write('\n'); + assertMessages("write newline", 1, "write_int"); + } + + @Test + public void write_bytes() throws Exception { + logOut.write("b\n".getBytes()); + assertMessages("write", 1, "write_bytes"); + } + + @Test + public void write_bytes_offset() throws Exception { + logOut.write("c\n".getBytes(), 0, 2); + assertMessages("write", 1, "write_bytes_offset"); + } + + @Test + public void print_boolean() throws Exception { + logOut.print(true); + assertMessages("print", 0, "print_boolean"); + logOut.println(true); + assertMessages("println", 1, "print_boolean"); + } + + @Test + public void print_char() throws Exception { + logOut.print('a'); + assertMessages("print", 0, "print_char"); + logOut.println('b'); + assertMessages("println", 1, "print_char"); + } + + @Test + public void print_chararray() throws Exception { + logOut.print("a".toCharArray()); + assertMessages("print", 0, "print_chararray"); + logOut.println("b".toCharArray()); + assertMessages("println", 1, "print_chararray"); + } + + @Test + public void print_double() throws Exception { + logOut.print(1D); + assertMessages("print", 0, "print_double"); + logOut.println(2D); + assertMessages("println", 1, "print_double"); + } + + @Test + public void print_float() throws Exception { + logOut.print(1f); + assertMessages("print", 0, "print_float"); + logOut.println(2f); + assertMessages("println", 1, "print_float"); + } + + @Test + public void print_int() throws Exception { + logOut.print(1); + assertMessages("print", 0, "print_int"); + logOut.println(2); + assertMessages("println", 1, "print_int"); + } + + @Test + public void print_long() throws Exception { + logOut.print(1L); + assertMessages("print", 0, "print_long"); + logOut.println(2L); + assertMessages("println", 1, "print_long"); + } + + @Test + public void print_object() throws Exception { + logOut.print((Object) 'a'); + assertMessages("print", 0, "print_object"); + logOut.println((Object) 'b'); + assertMessages("println", 1, "print_object"); + } + + @Test + public void print_string() throws Exception { + logOut.print("a"); + assertMessages("print", 0, "print_string"); + logOut.println("b"); + assertMessages("println", 1, "print_string"); + } + + @Test + public void print_printf() throws Exception { + logOut.printf("a\n"); + assertMessages("println", 1, "print_printf"); + } + + @Test + public void print_printf_locale() throws Exception { + logOut.printf(Locale.getDefault(), "a\n"); + assertMessages("println", 1, "print_printf_locale"); + } + + @Test + public void close() throws Exception { + logOut.print("a\nb"); + assertMessages("before close size", 1, "close"); + logOut.close(); + assertMessages("after close size", 2, "close"); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintStreamTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintStreamTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintStreamTest.java (revision 0) @@ -0,0 +1,116 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.io.OutputStream; + +import org.junit.Test; + +public class LoggerPrintStreamTest extends LoggerOutputStreamTest { + private LoggerPrintStream print; + + @Override + protected OutputStream createOutputStream() { + return this.print = new LoggerPrintStream(wrapped, getLogger(), LEVEL); + } + + @Test + public void testPrint_boolean() throws Exception { + print.print(true); + assertMessages(); + print.println(); + assertMessages("true"); + assertEquals("true" + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_char() throws Exception { + for (char c : FIRST.toCharArray()) { + print.print(c); + assertMessages(); + } + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_int() throws Exception { + print.print(12); + assertMessages(); + print.println(); + assertMessages("12"); + assertEquals("12" + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_long() throws Exception { + print.print(12L); + assertMessages(); + print.println(); + assertMessages("12"); + assertEquals("12" + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_CharacterArray() throws Exception { + print.print(FIRST.toCharArray()); + assertMessages(); + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_String() throws Exception { + print.print(FIRST); + assertMessages(); + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_Object() throws Exception { + print.print((Object) FIRST); + assertMessages(); + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrintf() throws Exception { + assertSame(print, print.printf("<<<%s>>>", FIRST)); + assertMessages(); + print.println(); + assertMessages("<<<" + FIRST + ">>>"); + assertEquals("<<<" + FIRST + ">>>" + NEWLINE, wrapped.toString()); + } + + @Test + public void testFormat() throws Exception { + assertSame(print, print.format("[%s]", FIRST)); + assertMessages(); + print.println(); + assertMessages("[" + FIRST + "]"); + assertEquals("[" + FIRST + "]" + NEWLINE, wrapped.toString()); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintWriterCallerInfoTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintWriterCallerInfoTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintWriterCallerInfoTest.java (revision 0) @@ -0,0 +1,145 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.util.Locale; + +import org.apache.logging.log4j.Level; +import org.junit.Before; +import org.junit.Test; + +public class LoggerPrintWriterCallerInfoTest extends LoggerStreamsCallerInfoTesting { + + private LoggerPrintWriter logOut; + + @Before + public void setupStreams() { + logOut = new LoggerPrintWriter(getLogger(), Level.WARN); + } + + @Test + public void write_int() throws Exception { + logOut.write('a'); + assertMessages("write int", 0, "write_int"); + logOut.write('\n'); + assertMessages("write newline", 1, "write_int"); + } + + @Test + public void write_bytes() throws Exception { + logOut.write("b\n".toCharArray()); + assertMessages("write", 1, "write_bytes"); + } + + @Test + public void write_bytes_offset() throws Exception { + logOut.write("c\n".toCharArray(), 0, 2); + assertMessages("write", 1, "write_bytes_offset"); + } + + @Test + public void print_boolean() throws Exception { + logOut.print(true); + assertMessages("print", 0, "print_boolean"); + logOut.println(true); + assertMessages("println", 1, "print_boolean"); + } + + @Test + public void print_char() throws Exception { + logOut.print('a'); + assertMessages("print", 0, "print_char"); + logOut.println('b'); + assertMessages("println", 1, "print_char"); + } + + @Test + public void print_chararray() throws Exception { + logOut.print("a".toCharArray()); + assertMessages("print", 0, "print_chararray"); + logOut.println("b".toCharArray()); + assertMessages("println", 1, "print_chararray"); + } + + @Test + public void print_double() throws Exception { + logOut.print(1D); + assertMessages("print", 0, "print_double"); + logOut.println(2D); + assertMessages("println", 1, "print_double"); + } + + @Test + public void print_float() throws Exception { + logOut.print(1f); + assertMessages("print", 0, "print_float"); + logOut.println(2f); + assertMessages("println", 1, "print_float"); + } + + @Test + public void print_int() throws Exception { + logOut.print(1); + assertMessages("print", 0, "print_int"); + logOut.println(2); + assertMessages("println", 1, "print_int"); + } + + @Test + public void print_long() throws Exception { + logOut.print(1L); + assertMessages("print", 0, "print_long"); + logOut.println(2L); + assertMessages("println", 1, "print_long"); + } + + @Test + public void print_object() throws Exception { + logOut.print((Object) 'a'); + assertMessages("print", 0, "print_object"); + logOut.println((Object) 'b'); + assertMessages("println", 1, "print_object"); + } + + @Test + public void print_string() throws Exception { + logOut.print("a"); + assertMessages("print", 0, "print_string"); + logOut.println("b"); + assertMessages("println", 1, "print_string"); + } + + @Test + public void print_printf() throws Exception { + logOut.printf("a\n"); + assertMessages("println", 1, "print_printf"); + } + + @Test + public void print_printf_locale() throws Exception { + logOut.printf(Locale.getDefault(), "a\n"); + assertMessages("println", 1, "print_printf_locale"); + } + + @Test + public void close() throws Exception { + logOut.print("a\nb"); + assertMessages("before close size", 1, "close"); + logOut.close(); + assertMessages("after close size", 2, "close"); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintWriterTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintWriterTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerPrintWriterTest.java (revision 0) @@ -0,0 +1,118 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.io.PrintWriter; +import java.io.Writer; + +import org.junit.Test; + +public class LoggerPrintWriterTest extends LoggerWriterTest { + private PrintWriter print; + + @Override + protected Writer createWriter() { + this.print = new LoggerPrintWriter(wrapped, getLogger(), LEVEL); + return this.print; + } + + @Test + public void testPrint_boolean() throws Exception { + print.print(true); + assertMessages(); + print.println(); + assertMessages("true"); + assertEquals("true" + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_char() throws Exception { + for (char c : FIRST.toCharArray()) { + print.print(c); + assertMessages(); + } + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_int() throws Exception { + print.print(12); + assertMessages(); + print.println(); + assertMessages("12"); + assertEquals("12" + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_long() throws Exception { + print.print(12L); + assertMessages(); + print.println(); + assertMessages("12"); + assertEquals("12" + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_CharacterArray() throws Exception { + print.print(FIRST.toCharArray()); + assertMessages(); + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_String() throws Exception { + print.print(FIRST); + assertMessages(); + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrint_Object() throws Exception { + print.print((Object) FIRST); + assertMessages(); + print.println(); + assertMessages(FIRST); + assertEquals(FIRST + NEWLINE, wrapped.toString()); + } + + @Test + public void testPrintf() throws Exception { + assertSame(print, print.printf("<<<%s>>>", FIRST)); + assertMessages(); + print.println(); + assertMessages("<<<" + FIRST + ">>>"); + assertEquals("<<<" + FIRST + ">>>" + NEWLINE, wrapped.toString()); + } + + @Test + public void testFormat() throws Exception { + assertSame(print, print.format("[%s]", FIRST)); + assertMessages(); + print.println(); + assertMessages("[" + FIRST + "]"); + assertEquals("[" + FIRST + "]" + NEWLINE, wrapped.toString()); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerReaderCallerInfoTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerReaderCallerInfoTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerReaderCallerInfoTest.java (revision 0) @@ -0,0 +1,57 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import java.io.Reader; +import java.io.StringReader; +import java.nio.CharBuffer; + +import org.junit.Before; +import org.junit.Test; + +public class LoggerReaderCallerInfoTest extends LoggerStreamsCallerInfoTesting { + + LoggerReader logReader; + + @Before + public void setupReader() { + final Reader srcReader = new StringReader("a\nb\nc\nd\ne"); + logReader = new LoggerReader(srcReader, getLogger(), LEVEL); + } + + @Test + public void read() throws Exception { + logReader.read(); + assertMessages("before read int size", 0, "read"); + logReader.read(); + assertMessages("after read int size", 1, "read"); + + logReader.read(new char[2]); + assertMessages("after read bytes size", 2, "read"); + + logReader.read(new char[2], 0, 2); + assertMessages("after read bytes offset size", 3, "read"); + + logReader.read(CharBuffer.allocate(2)); + assertMessages("after read charBuffer size", 4, "read"); + + logReader.read(); + assertMessages("before close size", 4, "read"); + logReader.close(); + assertMessages("after close size", 5, "read"); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerReaderTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerReaderTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerReaderTest.java (revision 0) @@ -0,0 +1,141 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.nio.CharBuffer; + +import org.junit.Before; +import org.junit.Test; + +public class LoggerReaderTest extends StreamTesting { + protected StringReader wrapped; + protected StringWriter read; + protected Reader reader; + + @Before + public void createStream() { + wrapped = new StringReader(FIRST + "\r\n" + LAST); + read = new StringWriter(); + reader = createReader(); + } + + protected Reader createReader() { + return new LoggerReader(wrapped, getLogger(), LEVEL); + } + + @Test + public void testRead_int() throws Exception { + for (int i = 0; i < FIRST.length(); i++) { + read.write(reader.read()); + } + if (!(reader instanceof BufferedReader)) { + assertMessages(); + } + assertEquals("carriage return", '\r', reader.read()); + if (!(reader instanceof BufferedReader)) { + assertMessages(); + } + assertEquals("newline", '\n', reader.read()); + assertMessages(FIRST); + } + + @Test + public void testRead_CharArray() throws Exception { + final char[] chars = new char[FIRST.length()]; + assertEquals("len", FIRST.length(), reader.read(chars)); + if (!(reader instanceof BufferedReader)) { + assertMessages(); + } + reader.read(chars); + assertMessages(FIRST); + } + + @Test + public void testRead_CharArray_Offset_Length() throws Exception { + final char[] chars = new char[1024]; + assertEquals("len", FIRST.length(), reader.read(chars, 0, FIRST.length())); + if (!(reader instanceof BufferedReader)) { + assertMessages(); + } + reader.read(chars); + reader.close(); + assertMessages(FIRST, LAST); + } + + @Test + public void testRead_CharBuffer() throws Exception { + final CharBuffer chars = CharBuffer.allocate(1024); + assertEquals("len", FIRST.length() + LAST.length() + 2, reader.read(chars)); + reader.close(); + assertMessages(FIRST, LAST); + } + + @Test + public void testRead_IgnoresWindowsNewline() throws IOException { + final char[] chars = new char[1024]; + int len = reader.read(chars); + read.write(chars, 0, len); + if (!(reader instanceof BufferedReader)) { + assertMessages(FIRST); + } + assertEquals(FIRST + "\r\n" + LAST, read.toString()); + reader.close(); + assertMessages(FIRST, LAST); + } + + @Test + public void testRead_MultipleLines() throws IOException { + wrapped = new StringReader(FIRST + "\n" + LAST + '\n'); + reader = createReader(); + + final char[] chars = new char[1024]; + int len = reader.read(chars); + read.write(chars, 0, len); + assertMessages(FIRST, LAST); + assertEquals(FIRST + '\n' + LAST + '\n', read.toString()); + } + + @Test + public void testClose_NoRemainingData() throws IOException { + wrapped = new StringReader(FIRST + '\n'); + reader = createReader(); + + final char[] chars = new char[1024]; + reader.read(chars); + assertMessages(FIRST); + reader.close(); + assertMessages(FIRST); + } + + @Test + public void testClose_HasRemainingData() throws IOException { + final char[] chars = new char[1024]; + reader.read(chars); + if (!(reader instanceof BufferedReader)) { + assertMessages(FIRST); + } + reader.close(); + assertMessages(FIRST, LAST); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerStreamsCallerInfoTesting.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerStreamsCallerInfoTesting.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerStreamsCallerInfoTesting.java (revision 0) @@ -0,0 +1,51 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.junit.Assert.assertEquals; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.junit.InitialLoggerContext; +import org.apache.logging.log4j.test.appender.ListAppender; +import org.junit.Before; +import org.junit.ClassRule; + +public class LoggerStreamsCallerInfoTesting { + + protected final static Level LEVEL = Level.WARN; + + @ClassRule + public static InitialLoggerContext ctx = new InitialLoggerContext("log4j2-streams-calling-info.xml"); + + protected static Logger getLogger() { + return ctx.getLogger("ClassAndMethodLogger"); + } + + @Before + public void clearAppender() { + ((ListAppender) ctx.getAppender("ClassAndMethod")).clear(); + } + + public void assertMessages(final String msg, int size, String methodName) { + ListAppender appender = (ListAppender) ctx.getAppender("ClassAndMethod"); + assertEquals(msg + ".size", size, appender.getMessages().size()); + for (final String message : appender.getMessages()) { + assertEquals(msg + " has incorrect caller info", this.getClass().getName() + '.' + methodName, message); + } + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerWriterTest.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerWriterTest.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/LoggerWriterTest.java (revision 0) @@ -0,0 +1,124 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.logging.log4j.streams; + +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.io.Writer; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +public class LoggerWriterTest extends StreamTesting { + protected StringWriter wrapped; + protected Writer writer; + + @Before + public void createStream() { + wrapped = new StringWriter(); + writer = createWriter(); + } + + protected Writer createWriter() { + return new LoggerWriter(wrapped, getLogger(), LEVEL); + } + + @Test + public void testWrite_CharArray() throws Exception { + final char[] chars = FIRST.toCharArray(); + writer.write(chars); + assertMessages(); + writer.write('\n'); + assertMessages(FIRST); + assertEquals(FIRST + '\n', wrapped.toString()); + } + + @Test + public void testWrite_CharArray_Offset_Length() throws Exception { + final char[] chars = FIRST.toCharArray(); + int middle = chars.length / 2; + int length = chars.length - middle; + final String right = new String(chars, middle, length); + writer.write(chars, middle, length); + assertMessages(); + writer.write('\n'); + assertMessages(right); + assertEquals(FIRST.substring(middle, FIRST.length()) + '\n', wrapped.toString()); + } + + @Test + public void testWrite_Character() throws Exception { + for (char c : FIRST.toCharArray()) { + writer.write(c); + assertMessages(); + } + writer.write('\n'); + assertMessages(FIRST); + assertEquals(FIRST + '\n', wrapped.toString()); + } + + @Test + public void testWrite_IgnoresWindowsNewline() throws IOException { + writer.write(FIRST + "\r\n"); + writer.write(LAST); + writer.close(); + assertMessages(FIRST, LAST); + assertEquals(FIRST + "\r\n" + LAST, wrapped.toString()); + } + + @Test + public void testWrite_MultipleLines() throws IOException { + writer.write(FIRST + '\n' + LAST + '\n'); + assertMessages(FIRST, LAST); + assertEquals(FIRST + '\n' + LAST + '\n', wrapped.toString()); + } + + @Test + public void testFlush() throws IOException { + final OutputStream out = EasyMock.createMock(OutputStream.class); + out.flush(); // expect the flush to come through to the mocked OutputStream + out.close(); + replay(out); + + final LoggerOutputStream los = new LoggerOutputStream(out, getLogger(), LEVEL); + los.flush(); + los.close(); + verify(out); + } + + @Test + public void testClose_NoRemainingData() throws IOException { + writer.close(); + assertMessages(); + assertEquals("", wrapped.toString()); + } + + @Test + public void testClose_HasRemainingData() throws IOException { + writer.write(FIRST); + assertMessages(); + writer.close(); + assertMessages(FIRST); + assertEquals(FIRST, wrapped.toString()); + } +} Index: log4j-streams/src/test/java/org/apache/logging/log4j/streams/StreamTesting.java =================================================================== --- log4j-streams/src/test/java/org/apache/logging/log4j/streams/StreamTesting.java (revision 0) +++ log4j-streams/src/test/java/org/apache/logging/log4j/streams/StreamTesting.java (revision 0) @@ -0,0 +1,44 @@ +package org.apache.logging.log4j.streams; + +import static org.hamcrest.core.StringStartsWith.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.junit.InitialLoggerContext; +import org.apache.logging.log4j.test.appender.ListAppender; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Ignore; + +@Ignore +public class StreamTesting { + protected final static String NEWLINE = System.getProperty("line.separator"); + protected final static Level LEVEL = Level.ERROR; + protected final static String FIRST = "first"; + protected final static String LAST = "last"; + + @ClassRule + public static InitialLoggerContext ctx = new InitialLoggerContext("log4j2-streams-unit-test.xml"); + + protected static Logger getLogger() { + return ctx.getLogger("UnitTestLogger"); + } + + @Before + public void clearAppender() { + ((ListAppender) ctx.getAppender("UnitTest")).clear(); + } + + protected void assertMessages(final String... messages) { + List actualMsgs = ((ListAppender) ctx.getAppender("UnitTest")).getMessages(); + assertEquals("Unexpected number of results.", messages.length, actualMsgs.size()); + for (int i = 0; i < messages.length; i++) { + final String start = LEVEL.name() + ' ' + messages[i]; + assertThat(actualMsgs.get(i), startsWith(start)); + } + } +} Index: log4j-streams/src/test/resources/log4j2-streams-calling-info.xml =================================================================== --- log4j-streams/src/test/resources/log4j2-streams-calling-info.xml (revision 0) +++ log4j-streams/src/test/resources/log4j2-streams-calling-info.xml (revision 0) @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + \ No newline at end of file Index: log4j-streams/src/test/resources/log4j2-streams-unit-test.xml =================================================================== --- log4j-streams/src/test/resources/log4j2-streams-unit-test.xml (revision 0) +++ log4j-streams/src/test/resources/log4j2-streams-unit-test.xml (revision 0) @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + \ No newline at end of file Index: log4j-streams/pom.xml =================================================================== --- log4j-streams/pom.xml (revision 0) +++ log4j-streams/pom.xml (revision 0) @@ -0,0 +1,207 @@ + + + + 4.0.0 + + org.apache.logging.log4j + log4j + 2.0-rc2-SNAPSHOT + ../ + + log4j-streams + jar + Apache Log4j Streaming Interface + Provides the ability to convert streams into log statements + + ${basedir}/.. + Streaming Documentation + /slf4j-streams + + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + test + + + + + + + org.apache.logging.log4j + log4j-core + test-jar + test + + + junit + junit + test + + + org.easymock + easymock + test + + + + + + + org.apache.maven.plugins + maven-remote-resources-plugin + + + + process + + + false + + + + + + + + + + org.apache.maven.plugins + maven-changes-plugin + ${changes.plugin.version} + + + + changes-report + + + + + %URL%/show_bug.cgi?id=%ISSUE% + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.7 + + + ${log4jParentDir}/checkstyle.xml + ${log4jParentDir}/checkstyle-suppressions.xml + false + basedir=${basedir} + licensedir=${log4jParentDir}/checkstyle-header.txt + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${javadoc.plugin.version} + + Copyright © {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.
+ Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo, + and the Apache Log4j logo are trademarks of The Apache Software Foundation.

]]>
+ + false + true + + + issue + a + JIRA issue: + + + doubt + a + Troublesome: + + + compare + a + Compare with: + + +
+ + + non-aggregate + + javadoc + + + +
+ + org.codehaus.mojo + findbugs-maven-plugin + 2.5.2 + + true + -Duser.language=en + Normal + Default + ${log4jParentDir}/findbugs-exclude-filter.xml + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + + non-aggregate + + jxr + + + + aggregate + + aggregate + + + + + + org.apache.maven.plugins + maven-pmd-plugin + ${pmd.plugin.version} + + ${maven.compile.target} + + + + org.codehaus.mojo + cobertura-maven-plugin + ${cobertura.plugin.version} + + + + + + + +
+
+
+ Index: pom.xml =================================================================== --- pom.xml (revision 1587128) +++ pom.xml (working copy) @@ -930,6 +930,7 @@ log4j-samples log4j-bom log4j-plugin-processor + log4j-streams Index: log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java =================================================================== --- log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java (revision 1587128) +++ log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java (working copy) @@ -39,7 +39,6 @@ public class Log4jLogEvent implements LogEvent { private static final long serialVersionUID = -1351367343806656055L; - private static final String NOT_AVAIL = "?"; private final String fqcnOfLogger; private final Marker marker; private final Level level; @@ -313,21 +312,13 @@ return null; } final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - boolean next = false; - for (final StackTraceElement element : stackTrace) { - final String className = element.getClassName(); - if (next) { - if (fqcnOfLogger.equals(className)) { - continue; - } - return element; - } - + StackTraceElement last = null; + for (int i = stackTrace.length - 1; i > 0; i--) { + final String className = stackTrace[i].getClassName(); if (fqcnOfLogger.equals(className)) { - next = true; - } else if (NOT_AVAIL.equals(className)) { - break; + return last; } + last = stackTrace[i]; } return null; }