blob: 85c792c6471c9f433f000a59c374d9235d390c65 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 1997-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*========================================================================
*/
package com.gemstone.persistence.admin;
import java.util.*;
import java.io.PrintWriter;
import java.text.*;
/**
* Provides single point for all log messages to written to.
* Currently this class only supports static methods and always
* writes to stdout.
*
* @author darrel
*/
public class Logger
{
private static final PrintWriter logWriter = new PrintWriter(System.out, true);
// Set LOGWIDTH to maxint as a cheap way of turning off formatting
private static final int LOGWIDTH = Integer.MAX_VALUE;
private static final SimpleDateFormat timeFormatter;
static {
final String defaultFormatPattern = "MM/dd/yy HH:mm:ss.SSS z";
final String resourceName = "com.gemstone.persistence.admin.LoggerResources";
final String keyName = "logger.timeStampFormat";
String formatPattern = defaultFormatPattern;
SimpleDateFormat sdf;
try {
ResourceBundle messageRB =
ResourceBundle.getBundle(resourceName);
try {
formatPattern = messageRB.getString(keyName);
} catch (MissingResourceException e) {
System.out.println("NOTICE: Logger using default timestamp format."
+ " Could not get resource key \""
+ keyName
+ "\" because: " + e);
}
} catch (MissingResourceException e) {
System.out.println("NOTICE: Logger using default timestamp format."
+ " Could not load resource bundle \""
+ resourceName
+ "\" because: " + e);
}
if (formatPattern.length() == 0) {
sdf = null;
} else {
try {
sdf = new SimpleDateFormat(formatPattern);
} catch (RuntimeException e) {
System.out.println("NOTICE: ignoring timestamp pattern \""
+ formatPattern
+ "\" because: " + e.toString());
System.out.println(" Using default pattern: \""
+ defaultFormatPattern + "\".");
formatPattern = defaultFormatPattern;
sdf = new SimpleDateFormat(formatPattern);
}
}
timeFormatter = sdf;
}
static private void formatText(PrintWriter writer, String target,
int maxLength, int initialLength) {
BreakIterator boundary = BreakIterator.getLineInstance();
boundary.setText(target);
int start = boundary.first();
int end = boundary.next();
int lineLength = initialLength;
while (end != BreakIterator.DONE) {
// Look at the end and only accept whitespace breaks
char endChar = target.charAt(end-1);
while (!Character.isWhitespace(endChar)) {
int lastEnd = end;
end = boundary.next();
if (end == BreakIterator.DONE) {
// give up. We are at the end of the string
end = lastEnd;
break;
}
endChar = target.charAt(end-1);
}
int wordEnd = end;
if (endChar == '\n') {
// trim off the \n since println will do it for us
wordEnd--;
} else if (endChar == '\t') {
// figure tabs use 8 characters
lineLength += 7;
}
String word = target.substring(start, wordEnd);
if ((lineLength + word.length()) >= maxLength) {
if (lineLength != 0) {
writer.println();
writer.print(" ");
lineLength = 2;
}
}
lineLength += word.length();
writer.print(word);
if (endChar == '\n') {
// force end of line
writer.println();
writer.print(" ");
lineLength = 2;
}
start = end;
end = boundary.next();
}
if (lineLength != 0) {
writer.println();
}
}
/**
* Gets a String representation of the current time.
* @return a String representation of the current time.
*/
static public String getTimeStamp() {
return formatDate(new Date());
}
/**
* Convert a Date to a timestamp String.
* @param d a Date to format as a timestamp String.
* @return a String representation of the current time.
*/
static public String formatDate(Date d) {
if (timeFormatter == null) {
try {
// very simple format that shows millisecond resolution
return Long.toString(d.getTime());
} catch (Exception ignore) {
return "timestampFormatFailed";
}
}
try {
synchronized (timeFormatter) {
// Need sync: see bug 21858
return timeFormatter.format(d);
}
} catch (Exception e1) {
// Fix bug 21857
try {
return d.toString();
} catch (Exception e2) {
try {
return Long.toString(d.getTime());
} catch (Exception e3) {
return "timestampFormatFailed";
}
}
}
}
/**
* Logs a message to the static log destination.
* @param msg the actual message to log
*/
static public void put(String msg) {
put(msg, (Throwable)null);
}
/**
* Logs a message to the specified log destination.
* @param log the <code>PrintWriter</code> that the message will be written to.
* @param msg the actual message to log
*/
static public void put(PrintWriter log, String msg) {
put(log, msg, (Throwable)null);
}
/**
* Logs an exception to the static log destination.
* @param exception the actual Exception to log
*/
static public void put(Throwable exception) {
put((String)null, exception);
}
/**
* Logs an exception to the specified log destination.
* @param log the <code>PrintWriter</code> that the message will be written to.
* @param exception the actual Exception to log
*/
static public void put(PrintWriter log, Throwable exception) {
put(log, (String)null, exception);
}
/**
* Logs a message and an exception to the static log destination.
* @param msg the actual message to log
* @param exception the actual Exception to log
*/
static public void put(String msg, Throwable exception) {
put(logWriter, msg, exception);
}
/**
* Logs a message and an exception to the specified log destination.
* @param log the <code>PrintWriter</code> that the message will be written to. If null then the default stdout writer is used.
* @param msg the actual message to log
* @param exception the actual Exception to log
*/
static public void put(PrintWriter log, String msg, Throwable exception) {
java.io.StringWriter sw = new java.io.StringWriter();
String header;
PrintWriter pw = new PrintWriter(sw);
pw.println();
header = '[' + getTimeStamp() + ' ' + Thread.currentThread().getName() + "] ";
pw.print(header);
if (msg != null) {
try {
formatText(pw, msg, LOGWIDTH, header.length());
} catch (RuntimeException e) {
pw.println(msg);
pw.println("Ignoring exception:");
e.printStackTrace(pw);
}
} else {
pw.println();
}
if (exception != null) {
exception.printStackTrace(pw);
}
pw.close();
try {
sw.close();
} catch (java.io.IOException ignore) {}
if (log == null) {
log = logWriter;
}
log.print(sw.toString());
log.flush();
}
/**
* Formats a message. Takes special care when invoking the
* toString() method of objects that might cause NPEs.
*/
public static String format(String format, Object[] objs) {
String[] strings = new String[objs.length];
for (int i = 0; i < objs.length; i++) {
Object obj = objs[i];
if (obj == null) {
strings[i] = "null";
} else {
try {
strings[i] = obj.toString();
} catch (Exception ex) {
strings[i] = obj.getClass().getName() + "@" +
System.identityHashCode(obj);
}
}
}
return java.text.MessageFormat.format(format, (Object[])strings);
}
}