1 /*
 2  * Autopsy Forensic Browser
 3  *
 4  * Copyright 2012-2015 Basis Technology Corp.
 5  * Contact: carrier <at> sleuthkit <dot> org
 6  *
 7  * Licensed under the Apache License, Version 2.0 (the "License");
 8  * you may not use this file except in compliance with the License.
 9  * You may obtain a copy of the License at
 10  *
 11  * http://www.apache.org/licenses/LICENSE-2.0
 12  *
 13  * Unless required by applicable law or agreed to in writing, software
 14  * distributed under the License is distributed on an "AS IS" BASIS,
 15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16  * See the License for the specific language governing permissions and
 17  * limitations under the License.
 18  */
 19 package org.sleuthkit.autopsy.coreutils;
 20 
 21 import java.io.IOException;
 22 import java.nio.file.Paths;
 23 import java.util.logging.FileHandler;
 24 import java.util.logging.Formatter;
 25 import java.util.logging.Handler;
 26 import java.sql.Timestamp;
 27 import java.util.Date;
 28 import java.util.HashMap;
 29 import java.util.Map;
 30 import java.util.logging.LogRecord;
 31 
 37 
 39   private static final int LOG_SIZE = 0; 
// In bytes, zero is unlimited 
 44   private static final Handler 
consoleHandler = 
new java.util.logging.ConsoleHandler();
 
 47 
 57  String logFilePath = Paths.get(logDirectory, LOG_WITHOUT_STACK_TRACES).toString();
 58  try {
 59  FileHandler fileHandler = new FileHandler(logFilePath, LOG_SIZE, LOG_FILE_COUNT);
 60  fileHandler.setEncoding(LOG_ENCODING);
 61  fileHandler.setFormatter(new Formatter() {
 62  @Override
 63  public String format(LogRecord record) {
 64  return (new Date(record.getMillis())).toString() + " "
 65  + record.getSourceClassName() + " "
 66  + record.getSourceMethodName() + "\n"
 67  + record.getLevel() + ": "
 68  + this.formatMessage(record) + "\n";
 69  }
 70  });
 71  return fileHandler;
 72  } catch (IOException ex) {
 73  throw new RuntimeException(String.format("Error initializing file handler for %s", logFilePath), ex); //NON-NLS
 74  }
 75  }
 76 
 86  String logFilePath = Paths.get(logDirectory, LOG_WITH_STACK_TRACES).toString();
 87  try {
 88  FileHandler fileHandler = new FileHandler(logFilePath, LOG_SIZE, LOG_FILE_COUNT);
 89  fileHandler.setEncoding(LOG_ENCODING);
 90  fileHandler.setFormatter(new Formatter() {
 91  @Override
 92  public String format(LogRecord record) {
 93  Throwable thrown = record.getThrown();
 94  String stackTrace = ""; //NON-NLS
 95  while (thrown != null) {
 96  stackTrace += thrown.toString() + "\n";
 97  for (StackTraceElement traceElem : record.getThrown().getStackTrace()) {
 98  stackTrace += "\t" + traceElem.toString() + "\n"; //NON-NLS
 99  }
 100  thrown = thrown.getCause();
 101  }
 102  return (new Timestamp(record.getMillis())).toString() + " " //NON-NLS
 103  + record.getSourceClassName() + " " //NON-NLS
 104  + record.getSourceMethodName() + "\n" //NON-NLS
 105  + record.getLevel() + ": " //NON-NLS
 106  + this.formatMessage(record) + "\n" //NON-NLS
 107  + stackTrace;
 108  }
 109  });
 110  return fileHandler;
 111  } catch (IOException ex) {
 112  throw new RuntimeException(String.format("Error initializing file handler for %s", logFilePath), ex); //NON-NLS
 113  }
 114  }
 115 
 122  /*
 123  * Create file handlers for the new directory and swap them into all of
 124  * the existing loggers using thread-safe Logger methods. The new
 125  * handlers are added before the old handlers so that no messages will
 126  * be lost, but this makes it possible for log messages to be written
 127  * via the old handlers if logging calls are interleaved with the
 128  * add/remove handler calls (currently, the base class handlers
 129  * collection is a CopyOnWriteArrayList).
 130  */
 133  for (
Logger logger : namesToLoggers.values()) {
 
 134  logger.addHandler(newUserFriendlyHandler);
 135  logger.addHandler(newDeveloperFriendlyHandler);
 136  logger.removeHandler(userFriendlyHandler);
 137  logger.removeHandler(userFriendlyHandler);
 138  }
 139 
 140  /*
 141  * Close the old file handlers and save references to the new handlers
 142  * so they can be added to any new loggers. This swap is why this method
 143  * and the two overloads of getLogger() are synchronized, serializing
 144  * access to userFriendlyHandler and developerFriendlyHandler.
 145  */
 146  userFriendlyHandler.close();
 147  userFriendlyHandler = newUserFriendlyHandler;
 148  developerFriendlyHandler.close();
 149  developerFriendlyHandler = newDeveloperFriendlyHandler;
 150  }
 151 
 163  }
 164 
 179  if (!namesToLoggers.containsKey(name)) {
 181  logger.addHandler(userFriendlyHandler);
 182  logger.addHandler(developerFriendlyHandler);
 183  namesToLoggers.put(name, logger);
 184  }
 185  return namesToLoggers.get(name);
 186  }
 187 
 198   private Logger(String name, String resourceBundleName) {
 
 199  super(name, resourceBundleName);
 200  super.setUseParentHandlers(false);
 202  super.addHandler(consoleHandler);
 203  }
 204  }
 205 }
static Version.Type getBuildType()
static final int LOG_SIZE
static final String LOG_WITHOUT_STACK_TRACES
synchronized static void setLogDirectory(String directoryPath)
Logger(String name, String resourceBundleName)
static final int LOG_FILE_COUNT
static FileHandler userFriendlyHandler
static final String LOG_ENCODING
static FileHandler developerFriendlyHandler
static final Handler consoleHandler
static FileHandler createFileHandlerWithTraces(String logDirectory)
static final Map< String, Logger > namesToLoggers
synchronized static Logger getLogger(String name)
static final String LOG_WITH_STACK_TRACES
synchronized static Logger getLogger(String name, String resourceBundleName)
static FileHandler createFileHandlerWithoutTraces(String logDirectory)