| /* |
| * 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.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.util.Date; |
| |
| import org.apache.geode.GemFireIOException; |
| import org.apache.geode.LogWriter; |
| import org.apache.geode.i18n.StringId; |
| |
| /** |
| * Implementation of {@link LogWriter} 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; |
| |
| protected volatile int level; |
| |
| private PrintWriter printWriter; |
| private long bytesLogged; |
| |
| /** |
| * 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(final int level) { |
| this(level, System.out); |
| } |
| |
| /** |
| * Creates a writer that logs to <code>printStream</code>. |
| * |
| * @param level only messages greater than or equal to this value will be logged. |
| * @param printStream is the stream that message will be printed to. |
| * |
| * @throws IllegalArgumentException if level is not in legal range |
| */ |
| public PureLogWriter(final int level, final PrintStream printStream) { |
| this(level, new PrintWriter(printStream, true), null); |
| } |
| |
| /** |
| * Creates a writer that logs to <code>printStream</code>. |
| * |
| * @param level only messages greater than or equal to this value will be logged. |
| * @param printStream is the stream that message will be printed to. |
| * |
| * @throws IllegalArgumentException if level is not in legal range |
| */ |
| public PureLogWriter(final int level, final PrintStream printStream, |
| final String connectionName) { |
| this(level, new PrintWriter(printStream, true), connectionName); |
| } |
| |
| /** |
| * Creates a writer that logs to <code>printWriter</code>. |
| * |
| * @param level only messages greater than or equal to this value will be logged. |
| * @param printWriter 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(final int level, final PrintWriter printWriter, |
| final String connectionName) { |
| setLevel(level); |
| this.printWriter = printWriter; |
| this.connectionName = connectionName; |
| } |
| |
| /** |
| * Gets the writer's level. |
| */ |
| @Override |
| public int getLogWriterLevel() { |
| return level; |
| } |
| |
| /** |
| * Sets the writer's level. |
| * |
| * @throws IllegalArgumentException if level is not in legal range |
| */ |
| public void setLevel(final int level) { |
| this.level = level; |
| } |
| |
| 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 messageLevel a string representation of the level |
| * @param message the actual message to log |
| * @param throwable the actual Exception to log |
| */ |
| @Override |
| public void put(final int messageLevel, final String message, final Throwable throwable) { |
| String exceptionText = null; |
| if (throwable != null) { |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| throwable.printStackTrace(printWriter); |
| printWriter.close(); |
| try { |
| stringWriter.close(); |
| } catch (IOException ignore) { |
| } |
| exceptionText = stringWriter.toString(); |
| } |
| put(messageLevel, new Date(), connectionName, getThreadName(), getThreadId(), message, |
| exceptionText); |
| } |
| |
| /** |
| * Logs a message and an exception to the specified log destination. |
| * |
| * @param messageLevel a string representation of the level |
| * @param messageId the actual message to log |
| * @param throwable the actual Exception to log |
| */ |
| @Override |
| public void put(final int messageLevel, final StringId messageId, final Object[] parameters, |
| final Throwable throwable) { |
| String message = messageId.toLocalizedString(parameters); |
| put(messageLevel, message, throwable); |
| } |
| |
| private String formatLogLine(final int messageLevel, final Date messageDate, |
| final String connectionName, final String threadName, final long threadId, |
| final String message, final String exceptionText) { |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| printHeader(printWriter, messageLevel, messageDate, connectionName, threadName, threadId); |
| |
| if (message != null) { |
| try { |
| formatText(printWriter, message, 40); |
| } catch (RuntimeException e) { |
| printWriter.println(message); |
| printWriter.println("Ignoring exception: "); |
| e.printStackTrace(printWriter); |
| } |
| } else { |
| printWriter.println(); |
| } |
| if (exceptionText != null) { |
| printWriter.print(exceptionText); |
| } |
| printWriter.close(); |
| try { |
| stringWriter.close(); |
| } catch (IOException ignore) { |
| // ignored |
| } |
| |
| return stringWriter.toString(); |
| } |
| |
| private void printHeader(final PrintWriter printWriter, final int messageLevel, |
| final Date messageDate, final String connectionName, final String threadName, |
| final long threadId) { |
| printWriter.println(); |
| printWriter.print('['); |
| printWriter.print(levelToString(messageLevel)); |
| printWriter.print(' '); |
| printWriter.print(formatDate(messageDate)); |
| if (connectionName != null) { |
| printWriter.print(' '); |
| printWriter.print(connectionName); |
| } |
| if (threadName != null) { |
| printWriter.print(" <"); |
| printWriter.print(threadName); |
| printWriter.print(">"); |
| } |
| printWriter.print(" tid=0x"); |
| printWriter.print(Long.toHexString(threadId)); |
| printWriter.print("] "); |
| } |
| |
| public String put(final int messageLevel, final Date messageDate, final String connectionName, |
| final String threadName, final long threadId, final String message, |
| final String exceptionText) { |
| String formattedLine = formatLogLine(messageLevel, messageDate, connectionName, threadName, |
| threadId, message, exceptionText); |
| writeFormattedMessage(formattedLine); |
| return formattedLine; |
| } |
| |
| public void writeFormattedMessage(final String message) { |
| synchronized (this) { |
| bytesLogged += message.length(); |
| printWriter.print(message); |
| printWriter.flush(); |
| } |
| } |
| |
| /** |
| * Returns the number of bytes written to the current log file. |
| */ |
| long getBytesLogged() { |
| return bytesLogged; |
| } |
| |
| /** |
| * Sets the target that this logger will sends its output to. |
| * |
| * @return the previous target. |
| */ |
| public PrintWriter setTarget(final PrintWriter printWriter) { |
| return setTarget(printWriter, 0L); |
| } |
| |
| public PrintWriter setTarget(final File logFile) { |
| return setTarget(createFileOutputStream(logFile), 0L); |
| } |
| |
| private PrintWriter createFileOutputStream(final File logFile) { |
| try { |
| return new PrintWriter(new FileOutputStream(logFile, true), true); |
| } catch (FileNotFoundException ex) { |
| String s = String.format("Could not open log file \"%s\".", logFile); |
| throw new GemFireIOException(s, ex); |
| } |
| } |
| |
| public PrintWriter setTarget(final PrintWriter printWriter, final long targetLength) { |
| synchronized (this) { |
| PrintWriter oldPrintWriter = this.printWriter; |
| bytesLogged = targetLength; |
| this.printWriter = printWriter; |
| return oldPrintWriter; |
| } |
| } |
| |
| public void close() { |
| closed = true; |
| try { |
| if (printWriter != null) { |
| printWriter.close(); |
| } |
| } catch (Exception e) { |
| // ignore , we are closing. |
| } |
| } |
| |
| public boolean isClosed() { |
| return closed; |
| } |
| |
| /** |
| * Returns the name of the connection on whose behalf this log writer logs. |
| */ |
| @Override |
| public String getConnectionName() { |
| return connectionName; |
| } |
| } |