/************************************************************************** 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 2008 Alex Buloichik 2013 Didier Briel 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; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.Logger; import org.omegat.util.logging.OmegaTFileHandler; /** * A collection of methods to make logging things easier. * * @author Henry Pijffers (henry.pijffers@saxnot.com) * @author Alex Buloichik (alex73mail@gmail.com) */ public class Log { private static Logger LOGGER; static { LOGGER = Logger.getLogger("global"); boolean loaded = false; File usersLogSettings = new File(StaticUtils.getConfigDir(), "logger.properties"); if (usersLogSettings.isFile() && usersLogSettings.canRead()) { // try to load logger settings from user home dir try (InputStream in = new FileInputStream(usersLogSettings)) { init(in); loaded = true; } catch (Exception e) { } } if (!loaded) { // load built-in logger settings try (InputStream in = Log.class.getResourceAsStream("/org/omegat/logger.properties")) { init(in); } catch (IOException ex) { LOGGER.log(Level.SEVERE, "Can't open file for logging", ex); } } } /** * Initialize handlers manually. Required for WebStart. * * @param in * settings */ protected static void init(InputStream in) throws IOException { Properties props = new Properties(); props.load(in); String handlers = props.getProperty("handlers"); if (handlers != null) { props.remove("handlers"); ByteArrayOutputStream b = new ByteArrayOutputStream(); props.store(b, null); LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(b.toByteArray())); Logger rootLogger = LogManager.getLogManager().getLogger(""); // remove initialized handlers for (Handler h : rootLogger.getHandlers()) { rootLogger.removeHandler(h); } String[] hs = handlers.split(","); for (String hn : hs) { String word = hn.trim(); try { Class<?> clz = Log.class.getClassLoader().loadClass(word); Handler h = (Handler) clz.newInstance(); String fname = props.getProperty(word + ".formatter"); if (fname != null) { Class<?> clzF = Log.class.getClassLoader().loadClass(fname.trim()); h.setFormatter((Formatter) clzF.newInstance()); } String level = props.getProperty(word + ".level"); if (level != null) { h.setLevel(Level.parse(level)); } rootLogger.addHandler(h); } catch (Exception ex) { System.err.println("Error in logger init: " + ex); ex.printStackTrace(); } } } } /** * Returns the path to the log file. */ public static String getLogLocation() { return StaticUtils.getConfigDir() + "/logs"; } /** * Compute the filename of the log file * @return the filename of the log, or an empty string */ public static String getLogFileName() { Handler[] hand = LOGGER.getParent().getHandlers(); if (hand[1] instanceof OmegaTFileHandler) { OmegaTFileHandler omegatLog = (OmegaTFileHandler) hand[1]; return omegatLog.getOmegaTLogFileName()+ ".log"; } else { return ""; } } /** * Compute the full path of the log file * @return the full path of the log file */ public static String getLogFilePath() { return getLogLocation() + "/" + getLogFileName(); } /** * Set the level for the global logger. This is normally determined by the * <code>logger.properties</code> file; use this method to override for * special use cases. * * @param level * The new level */ public static void setLevel(Level level) { LOGGER.setLevel(level); } /** * Logs what otherwise would go to System.out */ public static void log(String s) { LOGGER.info(s); } /** * Logs a message, retrieved from the resource bundle. * * @param key * The key of the message in the resource bundle. * @param parameters * Parameters for the message. These are inserted by using * StaticUtils.format. */ public static void logRB(String key, Object... parameters) { if (LOGGER.isLoggable(Level.INFO)) { LogRecord rec = new LogRecord(Level.INFO, key); rec.setResourceBundle(OStrings.getResourceBundle()); rec.setParameters(parameters); rec.setLoggerName(LOGGER.getName()); LOGGER.log(rec); } } /** * Logs an Exception or Error. * * To the log are written: - The class name of the Exception or Error - The * message, if any - The stack trace * * @param throwable * The exception or error to log */ public static void log(Throwable throwable) { LOGGER.log(Level.SEVERE, "", throwable); } /** * Writes a warning message to the log (to be retrieved from the resource * bundle) * <p> * While the warning message can be localized, the warning key is also * logged, so developers can determine what warning was given by looking at * the error key, instead of trying to interpret localized messages. * * @param key * The key of the error message in the resource bundle * @param parameters * Parameters for the error message. These are inserted by using * StaticUtils.format. */ public static void logWarningRB(String key, Object... parameters) { if (LOGGER.isLoggable(Level.WARNING)) { LogRecord rec = new LogRecord(Level.WARNING, key); rec.setResourceBundle(OStrings.getResourceBundle()); rec.setParameters(parameters); rec.setLoggerName(LOGGER.getName()); LOGGER.log(rec); } } /** * Writes an info message to the log (to be retrieved from the resource * bundle) * <p> * While the info message can be localized, the info key is also logged, so * developers can determine what info was given by looking at the error key, * instead of trying to interpret localized messages. * * @param key * The key of the error message in the resource bundle * @param parameters * Parameters for the error message. These are inserted by using * StaticUtils.format. */ public static void logInfoRB(String id, Object... parameters) { if (LOGGER.isLoggable(Level.INFO)) { LogRecord rec = new LogRecord(Level.INFO, id); rec.setResourceBundle(OStrings.getResourceBundle()); rec.setParameters(parameters); rec.setLoggerName(LOGGER.getName()); LOGGER.log(rec); } } /** * Writes an error message to the log (to be retrieved from the resource * bundle) * <p> * While the error message can be localized, the error key is also logged, * so developers can determine what error was given by looking at the error * key, instead of trying to interpret localized messages. * * @param key * The key of the error message in the resource bundle * @param parameters * Parameters for the error message. These are inserted by using * StaticUtils.format. */ public static void logErrorRB(String key, Object... parameters) { if (LOGGER.isLoggable(Level.SEVERE)) { LogRecord rec = new LogRecord(Level.SEVERE, key); rec.setResourceBundle(OStrings.getResourceBundle()); rec.setParameters(parameters); rec.setLoggerName(LOGGER.getName()); LOGGER.log(rec); } } /** * Writes an error message to the log (to be retrieved from the resource * bundle) * <p> * While the error message can be localized, the error key is also logged, * so developers can determine what error was given by looking at the error * key, instead of trying to interpret localized messages. * * @param ex * The error that was thrown * @param key * The key of the error message in the resource bundle * @param parameters * Parameters for the error message. These are inserted by using * StaticUtils.format. */ public static void logErrorRB(Throwable ex, String key, Object... parameters) { if (LOGGER.isLoggable(Level.SEVERE)) { LogRecord rec = new LogRecord(Level.SEVERE, key); rec.setResourceBundle(OStrings.getResourceBundle()); rec.setParameters(parameters); rec.setLoggerName(LOGGER.getName()); rec.setThrown(ex); LOGGER.log(rec); } } /** * Writes debug message to log (without localization) * * @param message * message text * @param parameters * Parameters for the error message. These are inserted by using * StaticUtils.format. */ public static void logDebug(Logger logger, String message, Object... parameters) { if (logger.isLoggable(Level.FINE)) { LogRecord rec = new LogRecord(Level.FINE, message); rec.setParameters(parameters); rec.setLoggerName(logger.getName()); logger.log(rec); } } }