/* Copyright (c) 2001-2019, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb.lib;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.lang.reflect.InvocationTargetException;
A logging framework wrapper that supports java.util.logging and log4j.
Logger hierarchies are stored at the Class level.
Log4j will be used if the Log4j system (not necessarily config files) are
found in the runtime classpath.
Otherwise, java.util.logging will be used.
This is pretty safe because for use cases where multiple hierarchies
are desired, classloader hierarchies will effectively isolate multiple
class-level Logger hierarchies.
Sad as it is, the java.util.logging facility lacks the most basic
developer-side and configuration-side capabilities.
Besides having a non-scalable discovery system, the designers didn't
comprehend the need for a level between WARNING and SEVERE!
Since we don't want to require log4j in Classpath, we have to live
with these constraints.
As with all the popular logging frameworks, if you want to capture a
stack trace, you must use the two-parameters logging methods.
I.e., you must also pass a String, or only toString() from your
throwable will be captured.
Usage example:
private static FrameworkLogger logger =
FrameworkLogger.getLog(SqlTool.class);
...
logger.finer("Doing something log-worthy");
The system level property hsqldb.reconfig_logging=false
is
required to avoid configuration of java.util.logging. Otherwise
configuration takes place.
Author: Blaine Simpson (blaine dot simpson at admc dot com) Version: 2.5.0 Since: 1.9.0
/**
* A logging framework wrapper that supports java.util.logging and log4j.
* <P>
* Logger hierarchies are stored at the Class level.
* Log4j will be used if the Log4j system (not necessarily config files) are
* found in the runtime classpath.
* Otherwise, java.util.logging will be used.
* <P>
* This is pretty safe because for use cases where multiple hierarchies
* are desired, classloader hierarchies will effectively isolate multiple
* class-level Logger hierarchies.
* <P>
* Sad as it is, the java.util.logging facility lacks the most basic
* developer-side and configuration-side capabilities.
* Besides having a non-scalable discovery system, the designers didn't
* comprehend the need for a level between WARNING and SEVERE!
* Since we don't want to require log4j in Classpath, we have to live
* with these constraints.
* <P>
* As with all the popular logging frameworks, if you want to capture a
* stack trace, you must use the two-parameters logging methods.
* I.e., you must also pass a String, or only toString() from your
* throwable will be captured.
* <P>
* Usage example:
*
* <pre><CODE>
* private static FrameworkLogger logger =
* FrameworkLogger.getLog(SqlTool.class);
* ...
* logger.finer("Doing something log-worthy");
* </CODE></pre>
*
* <p>
* The system level property <code>hsqldb.reconfig_logging=false</code> is
* required to avoid configuration of java.util.logging. Otherwise
* configuration takes place.
*
* @author Blaine Simpson (blaine dot simpson at admc dot com)
* @version 2.5.0
* @since 1.9.0
*/
public class FrameworkLogger {
/*
* FrameworkLogger coders: It would be convenient to be able to log
* states and such at debug level in this class.
* I tentatively think that using a logger instance early in the static
* lifecycle is too risky, possibly using the underlying plumbing before
* the application has had a chance to customize, and perhaps before
* classloaders have been re-prioritized, etc.
* Could be that it all works out ok, but make sure you consider all
* situations before logging with FrameworkLogger instances here.
* This is one reason why there are a couple uses of System.err below.
*/
Utility method for integrators. Returns a string representation of the
active Logger instance keys.
Not named similar to 'toString' to avoid ambiguity with instance
method toString.
Returns: String
/**
* Utility method for integrators. Returns a string representation of the
* active Logger instance keys.
*
* <p> Not named similar to 'toString' to avoid ambiguity with instance
* method toString. </p>
*
* @return String
*/
public static synchronized String report() {
return new StringBuilder().append(loggerInstances.size()).append(
" logger instances: ").append(
loggerInstances.keySet()).toString();
}
static private Map loggerInstances = new HashMap();
static private Map jdkToLog4jLevels = new HashMap();
static private Method log4jGetLogger;
static private Method log4jLogMethod;
static private boolean callerFqcnAvailable = false;
private Object log4jLogger;
private Logger jdkLogger;
// No need for more than one static, since we have only one console
static private boolean noopMode; // If true, then logging calls do nothing
static {
try {
reconfigure();
} catch (SecurityException e) {}
}
Frees Logger(s), if any, with the specified category, or that begins with
the specified prefix + dot.
Note that as of today, this depends on the underlying logging
framework implementation to release the underlying Logger instances. JUL
in Sun's JVM uses weak references, so that should be fine. Log4j as of
today seems to use strong references (and no API hooks to free anything),
so this method will probably have little benefit for Log4j.
Params: - prefixToZap – String
/**
* Frees Logger(s), if any, with the specified category, or that begins with
* the specified prefix + dot.
*
* <p> Note that as of today, this depends on the underlying logging
* framework implementation to release the underlying Logger instances. JUL
* in Sun's JVM uses weak references, so that should be fine. Log4j as of
* today seems to use strong references (and no API hooks to free anything),
* so this method will probably have little benefit for Log4j.
*
* @param prefixToZap String
*/
public static synchronized void clearLoggers(String prefixToZap) {
Set targetKeys = new HashSet();
java.util.Iterator it = loggerInstances.keySet().iterator();
String k;
String dottedPrefix = prefixToZap + '.';
while (it.hasNext()) {
k = (String) it.next();
if (k.equals(prefixToZap) || k.startsWith(dottedPrefix)) {
targetKeys.add(k);
}
}
loggerInstances.keySet().removeAll(targetKeys);
}
private static synchronized void
populateJdkToLog4jLevels(String classString)
throws ClassNotFoundException, IllegalAccessException,
NoSuchMethodException, InvocationTargetException {
Method log4jToLevel = Class.forName(classString).getMethod(
"toLevel", new Class[]{ String.class });
jdkToLog4jLevels.put(Level.ALL,
log4jToLevel.invoke(null,
new Object[]{ "ALL" }));
jdkToLog4jLevels.put(Level.FINER,
log4jToLevel.invoke(null,
new Object[]{ "DEBUG" }));
jdkToLog4jLevels.put(Level.WARNING,
log4jToLevel.invoke(null,
new Object[]{ "ERROR" }));
jdkToLog4jLevels.put(Level.SEVERE,
log4jToLevel.invoke(null,
new Object[]{ "FATAL" }));
jdkToLog4jLevels.put(Level.INFO,
log4jToLevel.invoke(null,
new Object[]{ "INFO" }));
jdkToLog4jLevels.put(Level.OFF,
log4jToLevel.invoke(null,
new Object[]{ "OFF" }));
jdkToLog4jLevels.put(Level.FINEST,
log4jToLevel.invoke(null,
new Object[]{ "TRACE" }));
jdkToLog4jLevels.put(Level.WARNING,
log4jToLevel.invoke(null,
new Object[]{ "WARN" }));
}
static void reconfigure() {
noopMode = false;
Class log4jLoggerClass = null;
Class log4jManagerClass = null;
loggerInstances.clear();
jdkToLog4jLevels.clear();
log4jGetLogger = null;
log4jLogMethod = null;
callerFqcnAvailable = false;
// Precedence:
// 1) Use log4j v2 if available and class initialization succeeds
// 2) Use log4j v1 if available and class initialization succeeds
// 3) JUL
try {
// log4j v2 available?
log4jLoggerClass = Class.forName(
"org.apache.logging.log4j.Logger");
log4jManagerClass = Class.forName(
"org.apache.logging.log4j.LogManager");
} catch (Exception e) {
// The class will only load successfully if Log4j v2 thinks it is
// in usable state.
// Intentionally empty.
}
// Attempt to configure log4j v2
if (log4jLoggerClass != null) {
try {
populateJdkToLog4jLevels("org.apache.logging.log4j.Level");
log4jLogMethod = log4jLoggerClass.getMethod("log",
new Class[] {
Class.forName("org.apache.logging.log4j.Level"),
Object.class, Throwable.class
});
log4jGetLogger = log4jManagerClass.getMethod("getLogger",
new Class[]{ String.class });
// This last object is what we toggle on to generate either
// Log4j or Jdk Logger objects (to wrap).
return; // Success for Log4j v2
} catch (Exception e) {
// This is an unexpected problem, because our Log4j try block will
// only be attempted if Log4j itself initialized (even if it
// successfully initialized with warnings due to bad config).
try {
System.err.println(
"<clinit> failure "
+ "instantiating configured Log4j v2 system: " + e);
// It's possible we don't have write access to System.err.
} catch (Throwable t) {
// Intentionally empty. We tried our best to report problem,
// but don't want to throw and prevent JUL from working.
}
}
}
// Reset
log4jLoggerClass = null;
log4jManagerClass = null;
log4jLogMethod = null;
log4jGetLogger = null;
jdkToLog4jLevels.clear();
try {
// log4j v1 available?
log4jLoggerClass = Class.forName("org.apache.log4j.Logger");
log4jManagerClass = log4jLoggerClass;
} catch (Exception e) {
// The class will only load successfully if Log4j v1 thinks it is
// in usable state.
// Intentionally empty.
}
// Attempt to configure log4j v1
if (log4jLoggerClass != null) {
try {
populateJdkToLog4jLevels("org.apache.log4j.Level");
log4jLogMethod = log4jLoggerClass.getMethod("log",
new Class[] {
String.class, Class.forName("org.apache.log4j.Priority"),
Object.class, Throwable.class
});
log4jGetLogger = log4jManagerClass.getMethod("getLogger",
new Class[]{ String.class });
// This last object is what we toggle on to generate either
// Log4j or Jdk Logger objects (to wrap).
callerFqcnAvailable = true;
return; // Success for Log4j v1
} catch (Exception e) {
// This is an unexpected problem, because our Log4j try block will
// only be attempted if Log4j itself initialized (even if it
// successfully initialized with warnings due to bad config).
try {
System.err.println(
"<clinit> failure "
+ "instantiating configured Log4j v1 system: " + e);
// It's possible we don't have write access to System.err.
} catch (Throwable t) {
// Intentionally empty. We tried our best to report problem,
// but don't want to throw and prevent JUL from working.
}
}
}
// Reset
log4jLoggerClass = null;
log4jManagerClass = null;
log4jLogMethod = null;
log4jGetLogger = null;
callerFqcnAvailable = false;
jdkToLog4jLevels.clear();
String propVal = System.getProperty("hsqldb.reconfig_logging");
if (propVal != null && propVal.equalsIgnoreCase("false")) {
return;
}
InputStream istream = null;
Logger cmdlineLogger;
try {
LogManager lm = LogManager.getLogManager();
String path =
"/org/hsqldb/resources/jdklogging-default.properties";
if (isDefaultJdkConfig()) {
lm.reset();
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(
new BasicTextJdkLogFormatter(false));
consoleHandler.setLevel(Level.INFO);
istream = FrameworkLogger.class.getResourceAsStream(path);
lm.readConfiguration(istream);
cmdlineLogger = Logger.getLogger("org.hsqldb.cmdline");
cmdlineLogger.addHandler(consoleHandler);
cmdlineLogger.setUseParentHandlers(false);
} else {
// Do not intervene. Use JDK logging exactly as configured
// by user.
lm.readConfiguration();
// The only bad thing about doing this is that if the app
// has programmatically changed the logging config after
// starting the program but before using FrameworkLogger,
// we will clobber those customizations.
// Set sys srop 'hsqldb.reconfig_logging' to false to
// prevent this.
}
} catch (Exception e) {
noopMode = true;
System.err.println(
"<clinit> failure initializing JDK logging system. "
+ "Continuing without Application logging.");
e.printStackTrace();
} finally {
if (istream != null) {
try {
istream.close();
} catch (IOException ioe) {
System.err.println("Failed to close logging input stream: "
+ ioe);
}
}
}
}
User may not use the constructor.
Params: - s – String
/**
* User may not use the constructor.
*
* @param s String
*/
private FrameworkLogger(String s) {
if (!noopMode) {
if (log4jGetLogger == null) {
jdkLogger = Logger.getLogger(s);
} else {
try {
log4jLogger = log4jGetLogger.invoke(null,
new Object[]{ s });
} catch (Exception e) {
throw new RuntimeException(
"Failed to instantiate Log4j Logger", e);
}
}
}
synchronized (FrameworkLogger.class) {
loggerInstances.put(s, this);
}
}
User's entry-point into this logging system. You normally want to
work with static (class-level) pointers to logger instances, for
performance efficiency. See the class-level JavaDoc for a usage example.
Params: - c – Class
See Also: - FrameworkLogger
Returns: FrameworkLogger
/**
* User's entry-point into this logging system. <P> You normally want to
* work with static (class-level) pointers to logger instances, for
* performance efficiency. See the class-level JavaDoc for a usage example.
*
* @see FrameworkLogger
* @param c Class
* @return FrameworkLogger
*/
public static FrameworkLogger getLog(Class c) {
return getLog(c.getName());
}
This method just defers to the getLog(Class) method unless default (no
local configuration) JDK logging is being used; In that case, this method
assures that the returned logger has an associated FileHander using the
supplied String identifier.
Params: - c – Class
- contextId – String
Returns: FrameworkLogger
/**
* This method just defers to the getLog(Class) method unless default (no
* local configuration) JDK logging is being used; In that case, this method
* assures that the returned logger has an associated FileHander using the
* supplied String identifier.
*
* @param c Class
* @param contextId String
* @return FrameworkLogger
*/
public static FrameworkLogger getLog(Class c, String contextId) {
return (contextId == null) ? getLog(c)
: getLog(contextId + '.' + c.getName());
}
This method just defers to the getLog(String) method unless default (no
local configuration) JDK logging is being used; In that case, this method
assures that the returned logger has an associated FileHander using the
supplied String identifier.
Params: - baseId – String
- contextId – String
Returns: FrameworkLogger
/**
* This method just defers to the getLog(String) method unless default (no
* local configuration) JDK logging is being used; In that case, this method
* assures that the returned logger has an associated FileHander using the
* supplied String identifier.
*
* @param baseId String
* @param contextId String
* @return FrameworkLogger
*/
public static FrameworkLogger getLog(String baseId, String contextId) {
return (contextId == null) ? getLog(baseId)
: getLog(contextId + '.' + baseId);
}
Alternative entry-point into this logging system, for cases where you
want to share a single logger instance among multiple classes, or you
want to use multiple logger instances from a single class.
Params: - s – String
See Also: - getLog(Class)
Returns: FrameworkLogger
/**
* Alternative entry-point into this logging system, for cases where you
* want to share a single logger instance among multiple classes, or you
* want to use multiple logger instances from a single class.
*
* @see #getLog(Class)
* @param s String
* @return FrameworkLogger
*/
public static synchronized FrameworkLogger getLog(String s) {
if (loggerInstances.containsKey(s)) {
return (FrameworkLogger) loggerInstances.get(s);
}
return new FrameworkLogger(s);
}
Just like FrameworkLogger.log(Level, String),
but also logs a stack trace.
Params: - level – java.util.logging.Level level to filter and log at
- message – Message to be logged
- t – Throwable whose stack trace will be logged.
See Also:
/**
* Just like FrameworkLogger.log(Level, String),
* but also logs a stack trace.
*
* @param level java.util.logging.Level level to filter and log at
* @param message Message to be logged
* @param t Throwable whose stack trace will be logged.
* @see #log(Level, String)
* @see Logger#log(Level, String)
* @see Level
*/
public void log(Level level, String message, Throwable t) {
privlog(level, message, t, 2, FrameworkLogger.class);
}
The "priv" prefix is historical. This is for special usage when you need
to modify the reported call stack. If you don't know that you want to do
this, then you should not use this method.
Params: - level – Level
- message – String
- t – Throwable
- revertMethods – int
- skipClass – Class
/**
* The "priv" prefix is historical. This is for special usage when you need
* to modify the reported call stack. If you don't know that you want to do
* this, then you should not use this method.
*
* @param level Level
* @param message String
* @param t Throwable
* @param revertMethods int
* @param skipClass Class
*/
public void privlog(Level level, String message, Throwable t,
int revertMethods, Class skipClass) {
if (noopMode) {
return;
}
if (log4jLogger == null) {
StackTraceElement[] elements = new Throwable().getStackTrace();
String c = "";
String m = "";
if (elements.length > revertMethods) {
c = elements[revertMethods].getClassName();
m = elements[revertMethods].getMethodName();
}
if (t == null) {
jdkLogger.logp(level, c, m, message);
} else {
jdkLogger.logp(level, c, m, message, t);
}
} else {
try {
log4jLogMethod.invoke(log4jLogger, callerFqcnAvailable
? new Object[] {
skipClass.getName(), jdkToLog4jLevels.get(level),
message, t}
: new Object[] {
jdkToLog4jLevels.get(level), message, t}
);
} catch (Exception e) {
throw new RuntimeException(
"Logging failed when attempting to log: " + message, e);
}
}
}
public void enduserlog(Level level, String message) {
/* This method is SqlTool-specific, which is where this class began at.
* Need to move this back there, but it needs access to the logging
* structures private to this class. Thinking...
*/
if (noopMode) {
return;
}
if (log4jLogger == null) {
String c = FrameworkLogger.class.getName();
String m = "\\l";
jdkLogger.logp(level, c, m, message);
} else {
try {
log4jLogMethod.invoke(log4jLogger, callerFqcnAvailable
? new Object[] {
FrameworkLogger.class.getName(),
jdkToLog4jLevels.get(level), message, null}
: new Object[] {
jdkToLog4jLevels.get(level), message, null}
);
// Test where SqlFile correct here.
} catch (Exception e) {
throw new RuntimeException(
"Logging failed when attempting to log: " + message, e);
}
}
}
// Wrappers
Params: - level – java.util.logging.Level level to filter and log at
- message – Message to be logged
See Also:
/**
* @param level java.util.logging.Level level to filter and log at
* @param message Message to be logged
* @see Logger#log(Level, String)
* @see Level
*/
public void log(Level level, String message) {
privlog(level, message, null, 2, FrameworkLogger.class);
}
Params: - message – Message to be logged
See Also:
/**
* @param message Message to be logged
* @see Logger#finer(String)
*/
public void finer(String message) {
privlog(Level.FINER, message, null, 2, FrameworkLogger.class);
}
Params: - message – Message to be logged
See Also:
/**
* @param message Message to be logged
* @see Logger#warning(String)
*/
public void warning(String message) {
privlog(Level.WARNING, message, null, 2, FrameworkLogger.class);
}
Params: - message – Message to be logged
See Also:
/**
* @param message Message to be logged
* @see Logger#severe(String)
*/
public void severe(String message) {
privlog(Level.SEVERE, message, null, 2, FrameworkLogger.class);
}
Params: - message – Message to be logged
See Also:
/**
* @param message Message to be logged
* @see Logger#info(String)
*/
public void info(String message) {
privlog(Level.INFO, message, null, 2, FrameworkLogger.class);
}
Params: - message – Message to be logged
See Also:
/**
* @param message Message to be logged
* @see Logger#finest(String)
*/
public void finest(String message) {
privlog(Level.FINEST, message, null, 2, FrameworkLogger.class);
}
This is just a wrapper for FrameworkLogger.warning(), because
java.util.logging lacks a method for this critical purpose.
Params: - message – Message to be logged
See Also:
/**
* This is just a wrapper for FrameworkLogger.warning(), because
* java.util.logging lacks a method for this critical purpose.
*
* @param message Message to be logged
* @see #warning(String)
*/
public void error(String message) {
privlog(Level.WARNING, message, null, 2, FrameworkLogger.class);
}
Just like FrameworkLogger.finer(String), but also logs a stack trace.
Params: - message – String
- t – Throwable whose stack trace will be logged.
See Also:
/**
* Just like FrameworkLogger.finer(String), but also logs a stack trace.
*
* @param message String
* @param t Throwable whose stack trace will be logged.
* @see #finer(String)
*/
public void finer(String message, Throwable t) {
privlog(Level.FINER, message, t, 2, FrameworkLogger.class);
}
Just like FrameworkLogger.warning(String), but also logs a stack trace.
Params: - message – String
- t – Throwable whose stack trace will be logged.
See Also:
/**
* Just like FrameworkLogger.warning(String), but also logs a stack trace.
*
* @param message String
* @param t Throwable whose stack trace will be logged.
* @see #warning(String)
*/
public void warning(String message, Throwable t) {
privlog(Level.WARNING, message, t, 2, FrameworkLogger.class);
}
Just like FrameworkLogger.severe(String), but also logs a stack trace.
Params: - message – String
- t – Throwable whose stack trace will be logged.
See Also:
/**
* Just like FrameworkLogger.severe(String), but also logs a stack trace.
*
* @param message String
* @param t Throwable whose stack trace will be logged.
* @see #severe(String)
*/
public void severe(String message, Throwable t) {
privlog(Level.SEVERE, message, t, 2, FrameworkLogger.class);
}
Just like FrameworkLogger.info(String), but also logs a stack trace.
Params: - message – String
- t – Throwable whose stack trace will be logged.
See Also:
/**
* Just like FrameworkLogger.info(String), but also logs a stack trace.
*
* @param message String
* @param t Throwable whose stack trace will be logged.
* @see #info(String)
*/
public void info(String message, Throwable t) {
privlog(Level.INFO, message, t, 2, FrameworkLogger.class);
}
Just like FrameworkLogger.finest(String), but also logs a stack trace.
Params: - message – String
- t – Throwable whose stack trace will be logged.
See Also:
/**
* Just like FrameworkLogger.finest(String), but also logs a stack trace.
*
* @param message String
* @param t Throwable whose stack trace will be logged.
* @see #finest(String)
*/
public void finest(String message, Throwable t) {
privlog(Level.FINEST, message, t, 2, FrameworkLogger.class);
}
Just like FrameworkLogger.error(String), but also logs a stack trace.
Params: - message – String
- t – Throwable whose stack trace will be logged.
See Also:
/**
* Just like FrameworkLogger.error(String), but also logs a stack trace.
*
* @param message String
* @param t Throwable whose stack trace will be logged.
* @see #error(String)
*/
public void error(String message, Throwable t) {
privlog(Level.WARNING, message, t, 2, FrameworkLogger.class);
}
Whether this JVM is configured with java.util.logging defaults. If the
JRE-provided config file is not in the expected place, then we return
false.
Returns: boolean
/**
* Whether this JVM is configured with java.util.logging defaults. If the
* JRE-provided config file is not in the expected place, then we return
* false.
*
* @return boolean
*/
public static boolean isDefaultJdkConfig() {
File globalCfgFile = new File(System.getProperty("java.home"),
"lib/logging.properties");
if (!globalCfgFile.isFile()) {
return false;
}
FileInputStream fis = null;
LogManager lm = LogManager.getLogManager();
try {
fis = new FileInputStream(globalCfgFile);
Properties defaultProps = new Properties();
defaultProps.load(fis);
Enumeration names = defaultProps.propertyNames();
int i = 0;
String name;
String liveVal;
while (names.hasMoreElements()) {
i++;
name = (String) names.nextElement();
liveVal = lm.getProperty(name);
if (liveVal == null) {
return false;
}
if (!lm.getProperty(name).equals(liveVal)) {
return false;
}
}
return true;
} catch (IOException ioe) {
return false;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ioe) {
// Intentional no-op
}
}
}
}
}