Java tutorial
/********************************************************************** ** ** ** This code belongs to the KETTLE project. ** ** ** ** Kettle, from version 2.2 on, is released into the public domain ** ** under the Lesser GNU Public License (LGPL). ** ** ** ** For more details, please read the document LICENSE.txt, included ** ** in this project ** ** ** ** http://www.kettle.be ** ** info@kettle.be ** ** ** **********************************************************************/ package be.ibridge.kettle.core; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Enumeration; import org.apache.log4j.Appender; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Layout; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.Priority; import be.ibridge.kettle.core.exception.KettleException; import be.ibridge.kettle.core.exception.KettleFileException; import be.ibridge.kettle.core.logging.Log4jConsoleAppender; import be.ibridge.kettle.core.logging.Log4jFileAppender; import be.ibridge.kettle.core.logging.Log4jKettleLayout; import be.ibridge.kettle.core.logging.Log4jMessage; import be.ibridge.kettle.core.logging.Log4jStringAppender; /** * This class handles the logging. * * @author Matt * @since 25-04-2003 * */ public class LogWriter { private static LogWriter logWriter; public static final int LOG_LEVEL_ERROR = 0; public static final int LOG_LEVEL_NOTHING = 1; public static final int LOG_LEVEL_MINIMAL = 2; public static final int LOG_LEVEL_BASIC = 3; public static final int LOG_LEVEL_DETAILED = 4; public static final int LOG_LEVEL_DEBUG = 5; public static final int LOG_LEVEL_ROWLEVEL = 6; public static final String logLevelDescription[] = { Messages.getString("LogWriter.Level.Error"), Messages.getString("LogWriter.Level.Nothing"), Messages.getString("LogWriter.Level.Minimal"), Messages.getString("LogWriter.Level.Basic"), Messages.getString("LogWriter.Level.Detailed"), Messages.getString("LogWriter.Level.Debug"), Messages.getString("LogWriter.Level.Rowlevel") }; public static final String log_level_desc_long[] = { Messages.getString("LogWriter.Level.Error.LongDesc"), Messages.getString("LogWriter.Level.Nothing.LongDesc"), Messages.getString("LogWriter.Level.Minimal.LongDesc"), Messages.getString("LogWriter.Level.Basic.LongDesc"), Messages.getString("LogWriter.Level.Detailed.LongDesc"), Messages.getString("LogWriter.Level.Debug.LongDesc"), Messages.getString("LogWriter.Level.Rowlevel.LongDesc") }; // String... private int type; private int level; private String filter; // Log4j private Logger rootLogger; private Log4jConsoleAppender consoleAppender; private Log4jStringAppender stringAppender; private Log4jFileAppender fileAppender; private File realFilename; private static Layout layout; public static final LogWriter getInstance() { if (logWriter != null) return logWriter; return getInstance(LOG_LEVEL_BASIC); } public static final LogWriter getInstance(int lvl) { if (logWriter != null) { logWriter.setLogLevel(lvl); return logWriter; } logWriter = new LogWriter(lvl); return logWriter; } private LogWriter() { rootLogger = Logger.getRootLogger(); layout = new Log4jKettleLayout(true); // Create the console appender, don't add it yet! consoleAppender = new Log4jConsoleAppender(); consoleAppender.setLayout(layout); consoleAppender.setName("AppendToConsole"); // Create the string appender, don't add it yet! stringAppender = new Log4jStringAppender(); stringAppender.setLayout(layout); stringAppender.setName("AppendToString"); } // Default: screen --> out private LogWriter(int lvl) { this(); // Check if there already is a console appender (ConsoleAppender) (in the app server for example) // boolean found = false; Enumeration appenders = rootLogger.getAllAppenders(); // Set the logging level for the Jackcess stuff to INFO... // TODO: make some kind of general configuation possible for this, load from file, etc. Logger.getLogger("com.healthmarketscience.jackcess").setLevel(Level.INFO); System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog"); System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true"); System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "info"); while (appenders.hasMoreElements()) { Object appender = appenders.nextElement(); if (appender instanceof ConsoleAppender || appender instanceof Log4jConsoleAppender) found = true; } if (!found) { rootLogger.addAppender(consoleAppender); } level = lvl; filter = null; } /** * Get a new log instance for the specified file if it is not open yet! * @param filename The log file to open * @param exact is this an exact filename (false: prefix of name in temp directory) * @param level The log level * @return the LogWriter object */ public static final LogWriter getInstance(String filename, boolean exact, int level) throws KettleException { if (logWriter != null) { // OK, see if we have a file appender already for this if (logWriter.rootLogger.getAppender(LogWriter.createFileAppenderName(filename, exact)) == null) { logWriter.fileAppender = createFileAppender(filename, exact); logWriter.addAppender(logWriter.fileAppender); } return logWriter; } logWriter = new LogWriter(filename, exact, level); return logWriter; } private LogWriter(String filename, boolean exact, int level) { this(); this.level = level; try { fileAppender = createFileAppender(filename, exact); addAppender(fileAppender); } catch (Exception e) { System.out.println("ERROR OPENING LOG FILE [" + filename + "] --> " + e.toString()); } } public static final Log4jFileAppender createFileAppender(String filename, boolean exact) throws KettleException { try { File file; if (!exact) { file = File.createTempFile(filename + ".", ".log"); file.deleteOnExit(); } else { file = new File(filename); } File realFile = file.getAbsoluteFile(); Log4jFileAppender appender = new Log4jFileAppender(realFile); appender.setLayout(new Log4jKettleLayout(true)); appender.setName(LogWriter.createFileAppenderName(filename, exact)); return appender; } catch (IOException e) { throw new KettleFileException("Unable to add Kettle file appender to Log4J", e); } } public static final String createFileAppenderName(String filename, boolean exact) { if (!exact) { return "<temp file> : " + filename; } else { return filename; } } public static final Log4jStringAppender createStringAppender() { Log4jStringAppender appender = new Log4jStringAppender(); appender.setLayout(new Log4jKettleLayout(true)); return appender; } public static void setConsoleAppenderDebug() { Enumeration appenders = Logger.getRootLogger().getAllAppenders(); while (appenders.hasMoreElements()) { Object appender = appenders.nextElement(); if (appender instanceof ConsoleAppender || appender instanceof Log4jConsoleAppender) { if (appender instanceof ConsoleAppender) { ((ConsoleAppender) appender).setThreshold(Priority.DEBUG); } } } } public int getType() { return type; } public void setType(int type) { this.type = type; } public boolean close() { boolean retval = true; try { // Close all appenders... Logger logger = Logger.getRootLogger(); Enumeration loggers = logger.getAllAppenders(); while (loggers.hasMoreElements()) { Appender appender = (Appender) loggers.nextElement(); appender.close(); } rootLogger.removeAllAppenders(); logWriter = null; } catch (Exception e) { retval = false; } return retval; } public void setLogLevel(int lvl) { level = lvl; } public void setLogLevel(String lvl) { level = getLogLevel(lvl); } public int getLogLevel() { return level; } public String getLogLevelDesc() { return logLevelDescription[level]; } /** * @deprecated : get the layout and use that object */ public void enableTime() { ((Log4jKettleLayout) layout).setTimeAdded(true); } /** * @deprecated : get the layout and use that object */ public void disableTime() { ((Log4jKettleLayout) layout).setTimeAdded(false); } /** * @deprecated : get the layout and use that object * @return true is the time is added */ public boolean getTime() { return ((Log4jKettleLayout) layout).isTimeAdded(); } /** * @deprecated : get the layout and use that object * @param tim true is the time has to be is added */ public void setTime(boolean tim) { ((Log4jKettleLayout) layout).setTimeAdded(tim); } public void println(int lvl, String msg) { println(lvl, "General", msg); } public void println(int lvl, String subj, String msg) { String subject = subj; if (subject == null) subject = "Kettle"; // Are the message filtered? if (filter != null && filter.length() > 0) { if (subject.indexOf(filter) < 0 && msg.indexOf(filter) < 0) { return; // "filter" not found in row: don't show! } } if (level == 0) return; // Nothing, not even errors... if (level < lvl) return; // not for our eyes. // Where did this come from??? Logger logger = Logger.getLogger(subject); Log4jMessage message = new Log4jMessage(msg, subject, lvl); switch (lvl) { case LOG_LEVEL_ERROR: logger.error(message); break; case LOG_LEVEL_ROWLEVEL: case LOG_LEVEL_DEBUG: logger.debug(message); break; default: logger.info(message); break; } } public void logMinimal(String subject, String message) { println(LOG_LEVEL_MINIMAL, subject, message); } public void logBasic(String subject, String message) { println(LOG_LEVEL_BASIC, subject, message); } public void logDetailed(String subject, String message) { println(LOG_LEVEL_DETAILED, subject, message); } public void logDebug(String subject, String message) { println(LOG_LEVEL_DEBUG, subject, message); } public void logRowlevel(String subject, String message) { println(LOG_LEVEL_ROWLEVEL, subject, message); } public void logError(String subject, String message) { println(LOG_LEVEL_ERROR, subject, message); } /** * @deprecated Please get the file appender yourself and work from there. * */ public Object getStream() { return null; // Will fail so that people fix this. } public void setFilter(String filter) { this.filter = filter; } public String getFilter() { return filter; } public static final int getLogLevel(String lvl) { if (lvl == null) return LOG_LEVEL_ERROR; for (int i = 0; i < logLevelDescription.length; i++) { if (logLevelDescription[i].equalsIgnoreCase(lvl)) return i; } for (int i = 0; i < log_level_desc_long.length; i++) { if (log_level_desc_long[i].equalsIgnoreCase(lvl)) return i; } return LOG_LEVEL_BASIC; } public static final String getLogLevelDesc(int l) { if (l < 0 || l >= logLevelDescription.length) return logLevelDescription[LOG_LEVEL_BASIC]; return logLevelDescription[l]; } /** * Please try to get the file appender yourself using the static constructor and work from there */ public FileInputStream getFileInputStream() throws IOException { return new FileInputStream(fileAppender.getFile()); } /** * Get the file input stream for a certain appender. * The appender is looked up using the filename * @param filename The exact filename (with path: c:\temp\logfile.txt) or just a filename (spoon.log) * @param exact true if this is the exact filename or just the last part of the complete path. * @return The file input stream of the appender * @throws IOException in case the appender ocan't be found */ public FileInputStream getFileInputStream(String filename, boolean exact) throws IOException { Logger logger = Logger.getRootLogger(); Appender appender = logger.getAppender(createFileAppenderName(filename, exact)); if (appender == null) { throw new IOException("Unable to find appender for file: " + filename + " (exact=" + exact + ")"); } return new FileInputStream(((Log4jFileAppender) appender).getFile()); } public boolean isBasic() { return level >= LOG_LEVEL_BASIC; } public boolean isDetailed() { return level >= LOG_LEVEL_DETAILED; } public boolean isDebug() { return level >= LOG_LEVEL_DEBUG; } public boolean isRowLevel() { return level >= LOG_LEVEL_ROWLEVEL; } /** * @return Returns the realFilename. */ public File getRealFilename() { return realFilename; } /** * @param realFilename The realFilename to set. */ public void setRealFilename(File realFilename) { this.realFilename = realFilename; } public void startStringCapture() { Logger logger = Logger.getRootLogger(); logger.addAppender(stringAppender); } public void endStringCapture() { Logger logger = Logger.getRootLogger(); logger.removeAppender(stringAppender); } /** * @deprecated please create your own StringAppender, otherwise this is not thread safe! * @return The logging text from since startStringCapture() is called until endStringCapture(). */ public String getString() { return stringAppender.getBuffer().toString(); } /** * @deprecated please create your own StringAppender, otherwise this is not thread safe! * @param string the string to set on the string appender buffer */ public void setString(String string) { stringAppender.setBuffer(new StringBuffer(string)); } public void addAppender(Appender appender) { Logger logger = Logger.getRootLogger(); logger.addAppender(appender); } public void removeAppender(Appender appender) { Logger logger = Logger.getRootLogger(); logger.removeAppender(appender); } public Log4jConsoleAppender getConsoleAppender() { return consoleAppender; } /** * @deprecated please create your own StringAppender, otherwise this is not thread safe! * @return the string appender */ public Log4jStringAppender getStringAppender() { return stringAppender; } /** * @return the rootLogger */ public Logger getRootLogger() { return rootLogger; } /** * @param rootLogger the rootLogger to set */ public void setRootLogger(Logger rootLogger) { this.rootLogger = rootLogger; } public static void setLayout(Layout layout) { LogWriter.layout = layout; // save for later creation of new files... Enumeration appenders = getInstance().getRootLogger().getAllAppenders(); while (appenders.hasMoreElements()) { Appender appender = (Appender) appenders.nextElement(); if (appender instanceof Log4jConsoleAppender || appender instanceof Log4jFileAppender || appender instanceof Log4jStringAppender) { appender.setLayout(layout); } } } public static Layout getLayout() { return layout; } }