/*
* 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.geode.internal.logging;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import org.apache.geode.internal.i18n.LocalizedStrings;
import org.apache.geode.i18n.StringId;
/**
* Implementation of {@link org.apache.geode.i18n.LogWriterI18n} that will write to a local stream
* and only use pure java features.
*/
public class PureLogWriter extends LogWriterImpl {
/** The "name" of the connection associated with this log writer */
private final String connectionName;
/** If the log stream has been closed */
private volatile boolean closed;
// Constructors
/**
* Creates a writer that logs to <code>System.out</code>.
*
* @param level only messages greater than or equal to this value will be logged.
* @throws IllegalArgumentException if level is not in legal range
*/
public PureLogWriter(int level) {
this(level, System.out);
}
/**
* Creates a writer that logs to <code>logWriter</code>.
*
* @param level only messages greater than or equal to this value will be logged.
* @param logWriter is the stream that message will be printed to.
* @throws IllegalArgumentException if level is not in legal range
*/
public PureLogWriter(int level, PrintStream logWriter) {
this(level, new PrintWriter(logWriter, true), null);
}
/**
* Creates a writer that logs to <code>logWriter</code>.
*
* @param level only messages greater than or equal to this value will be logged.
* @param logWriter is the stream that message will be printed to.
* @throws IllegalArgumentException if level is not in legal range
*/
public PureLogWriter(int level, PrintStream logWriter, String connectionName) {
this(level, new PrintWriter(logWriter, true), connectionName);
}
/**
* Creates a writer that logs to <code>logWriter</code>.
*
* @param level only messages greater than or equal to this value will be logged.
* @param logWriter is the stream that message will be printed to.
* @param connectionName The name of the connection associated with this log writer
* @throws IllegalArgumentException if level is not in legal range
*/
public PureLogWriter(int level, PrintWriter logWriter, String connectionName) {
super();
this.setLevel(level);
this.logWriter = logWriter;
this.connectionName = connectionName;
}
// Special Instance Methods on this class only
/**
* Gets the writer's level.
*/
@Override
public int getLogWriterLevel() {
return this.level;
}
/**
* Sets the writer's level.
*
* @throws IllegalArgumentException if level is not in legal range
*/
public void setLevel(int newLevel) {
// if (newLevel < ALL_LEVEL || newLevel > NONE_LEVEL) {
// throw new
// IllegalArgumentException(LocalizedStrings.PureLogWriter_WRITER_LEVEL_0_WAS_NOT_IN_THE_RANGE_1_2.toLocalizedString(new
// Object[] {Integer.valueOf(newLevel), Integer.valueOf(ALL_LEVEL),
// Integer.valueOf(NONE_LEVEL)}));
// }
this.level = newLevel;
}
public void setLogWriterLevel(int newLevel) {
setLevel(newLevel);
}
// internal implementation methods
protected String getThreadName() {
return Thread.currentThread().getName();
}
protected long getThreadId() {
// fix for bug 37861
return Thread.currentThread().getId();
}
/**
* Logs a message and an exception to the specified log destination.
*
* @param msgLevel a string representation of the level
* @param msg the actual message to log
* @param ex the actual Exception to log
*/
@Override
public void put(int msgLevel, String msg, Throwable ex) {
String exceptionText = null;
if (ex != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
pw.close();
try {
sw.close();
} catch (IOException ignore) {
}
exceptionText = sw.toString();
}
put(msgLevel, new Date(), this.connectionName, getThreadName(), getThreadId(), msg,
exceptionText);
}
/**
* Logs a message and an exception to the specified log destination.
*
* @param msgLevel a string representation of the level
* @param msgId the actual message to log
* @param ex the actual Exception to log
*/
@Override
public void put(int msgLevel, StringId msgId, Object[] params, Throwable ex) {
String msg = msgId.toLocalizedString(params);
put(msgLevel, msg, ex);
}
protected String formatLogLine(int msgLevel, Date msgDate,
@SuppressWarnings("hiding") String connectionName, String threadName, long tid, String msg,
String exceptionText) {
java.io.StringWriter sw = new java.io.StringWriter();
PrintWriter pw = new PrintWriter(sw);
printHeader(pw, msgLevel, msgDate, connectionName, threadName, tid);
if (msg != null) {
try {
formatText(pw, msg, 40);
} catch (RuntimeException e) {
pw.println(msg);
pw.println(LocalizedStrings.PureLogWriter_IGNORING_EXCEPTION.toLocalizedString());
e.printStackTrace(pw);
}
} else {
pw.println();
}
if (exceptionText != null) {
pw.print(exceptionText);
}
pw.close();
try {
sw.close();
} catch (java.io.IOException ignore) {
}
return sw.toString();
}
protected void printHeader(PrintWriter pw, int msgLevel, Date msgDate, String connectionName,
String threadName, long tid) {
pw.println();
pw.print('[');
pw.print(levelToString(msgLevel));
pw.print(' ');
pw.print(this.formatDate(msgDate));
if (connectionName != null) {
pw.print(' ');
pw.print(connectionName);
}
if (threadName != null) {
pw.print(" <");
pw.print(threadName);
pw.print(">");
}
pw.print(" tid=0x");
pw.print(Long.toHexString(tid));
pw.print("] ");
}
public String put(int msgLevel, Date msgDate, String connectionName, String threadName, long tid,
String msg, String exceptionText) {
String result =
formatLogLine(msgLevel, msgDate, connectionName, threadName, tid, msg, exceptionText);
writeFormattedMessage(result);
return result;
}
public void writeFormattedMessage(String s) {
synchronized (this) {
this.bytesLogged += s.length();
this.logWriter.print(s);
this.logWriter.flush();
}
}
/**
* Returns the number of bytes written to the current log file.
*/
public long getBytesLogged() {
return this.bytesLogged;
}
/**
* Sets the target that this logger will sends its output to.
*
* @return the previous target.
*/
public PrintWriter setTarget(PrintWriter logWriter) {
return setTarget(logWriter, 0L);
}
public PrintWriter setTarget(PrintWriter logWriter, long targetLength) {
synchronized (this) {
PrintWriter result = this.logWriter;
this.bytesLogged = targetLength;
this.logWriter = logWriter;
return result;
}
}
public final void close() {
this.closed = true;
try {
if (this.logWriter != null) {
this.logWriter.close();
}
} catch (Exception e) {
// ignore , we are closing.
}
}
public final boolean isClosed() {
return this.closed;
}
/**
* Returns the name of the connection on whose behalf this log writer logs.
*/
public String getConnectionName() {
return this.connectionName;
}
/** Get the underlying PrintWriter. */
public PrintWriter getPrintWriter() {
return this.logWriter;
}
// instance variables
protected volatile int level;
private long bytesLogged = 0;
private PrintWriter logWriter;
}