/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2000-2006 Keith Godfrey, Maxym Mykhalchuk, and Henry Pijffers
Alex Buloichik
Home page: http://www.omegat.org/
Support center: http://groups.yahoo.com/group/OmegaT/
This file is part of OmegaT.
OmegaT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OmegaT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
package org.omegat.util.logging;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import org.omegat.util.OStrings;
import org.omegat.util.StringUtil;
/**
* Formatter for output data with session ID
*
* @author Henry Pijffers (henry.pijffers@saxnot.com)
* @author Alex Buloichik (alex73mail@gmail.com)
*/
public class OmegaTLogFormatter extends Formatter {
protected static final String lineMark;
private String logMask;
private boolean isMaskContainsMark;
private boolean isMaskContainsThreadName;
private boolean isMaskContainsLevel;
private boolean isMaskContainsText;
private boolean isMaskContainsKey;
private boolean isMaskContainsLoggerName;
private boolean isMaskContainsTime;
private String defaultTimeFormat = "HH:mm:ss";
/**
* We have to use ThreadLocal for formatting time because DateFormat is not
* thread safe.
*/
private ThreadLocal<SimpleDateFormat> timeFormatter = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(defaultTimeFormat);
}
};
static {
// get a positive random number
Random generator = new Random();
generator.setSeed(System.currentTimeMillis()); // use current time as
// seed
int random = generator.nextInt(Integer.MAX_VALUE);
// convert the number to string, 5 chars max, pad with zero's if
// necessary
String sessionID = String.valueOf(random);
if (sessionID.length() > 5)
sessionID = sessionID.substring(0, 5);
else if (sessionID.length() < 5)
for (int i = 5; i > sessionID.length(); i++)
sessionID = "0" + sessionID;
lineMark = sessionID;
}
/**
* Initialize formatter.
*/
public OmegaTLogFormatter() {
LogManager manager = LogManager.getLogManager();
String cname = getClass().getName();
logMask = manager.getProperty(cname + ".mask");
if (logMask == null) {
logMask = "$mark: $level: $text $key";
}
String timeFormat = manager.getProperty(cname + ".timeFormat");
if (timeFormat != null) {
defaultTimeFormat = timeFormat;
}
isMaskContainsKey = logMask.contains("$key");
isMaskContainsLevel = logMask.contains("$level");
isMaskContainsMark = logMask.contains("$mark");
isMaskContainsTime = logMask.contains("$time");
isMaskContainsText = logMask.contains("$text");
isMaskContainsThreadName = logMask.contains("$threadName");
isMaskContainsLoggerName = logMask.contains("$loggerName");
}
/**
* Format output message.
*/
@Override
public String format(final LogRecord record) {
final StringBuilder result = new StringBuilder();
String message;
String format;
if (record.getResourceBundle() != null) {
try {
format = record.getResourceBundle().getString(record.getMessage());
} catch (Exception ex) {
// looks like ID not found in bundle
format = record.getMessage();
}
} else {
format = record.getMessage();
}
if (format == null) {
format = "null";
}
if (record.getParameters() == null) {
message = format;
} else {
message = StringUtil.format(format, record.getParameters());
}
String[] lines = message.split("\r|\n");
for (String line : lines) {
appendFormattedLine(result, record, line, false);
}
if (record.getThrown() != null) {
StringWriter stackTrace = new StringWriter();
record.getThrown().printStackTrace(new PrintWriter(stackTrace));
for (String line : stackTrace.toString().split("\r|\n")) {
appendFormattedLine(result, record, line, true);
}
}
return result.toString();
}
/**
* Format one line and append to output.
*/
protected void appendFormattedLine(final StringBuilder out, final LogRecord record, final String line,
final boolean isStack) {
if (line.isEmpty()) {
return;
}
String res = logMask;
if (isMaskContainsMark) {
res = res.replace("$mark", lineMark);
}
if (isMaskContainsTime) {
res = res.replace("$time", timeFormatter.get().format(new Date()));
}
if (isMaskContainsLoggerName) {
res = res.replace("$loggerName", record.getLoggerName());
}
if (isMaskContainsThreadName) {
res = res.replace("$threadName", Thread.currentThread().getName());
}
if (isMaskContainsLevel) {
res = res.replace("$level", getLocalizedLevel(record.getLevel()));
}
if (isMaskContainsText) {
res = res.replace("$text", line);
}
if (isMaskContainsKey) {
if (record.getResourceBundle() != null && !isStack) {
res = res.replace("$key", "(" + record.getMessage() + ")");
} else {
res = res.replace("$key", "");
}
}
out.append(res).append(System.lineSeparator());
}
/**
* Get localized level name.
*/
protected String getLocalizedLevel(final Level logLevel) {
String result;
if (Level.INFO.getName().equals(logLevel.getName())) {
result = OStrings.getString("LOG_LEVEL_INFO");
} else if (Level.SEVERE.getName().equals(logLevel.getName())) {
result = OStrings.getString("LOG_LEVEL_SEVERE");
} else if (Level.WARNING.getName().equals(logLevel.getName())) {
result = OStrings.getString("LOG_LEVEL_WARNING");
} else {
result = logLevel.getName();
}
return result.trim();
}
}