Author: fmeschbe
Date: Thu Jul 23 11:53:01 2009
New Revision: 797030
URL: http://svn.apache.org/viewvc?rev=797030&view=rev
Log:
SLING-1060 Add support for implicit log writer configuration for
logger configurations referring to "unconfigured" log files
Modified:
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerWriter.java
Modified:
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java?rev=797030&r1=797029&r2=797030&view=diff
==============================================================================
---
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java
(original)
+++
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/LogConfigManager.java
Thu Jul 23 11:53:01 2009
@@ -162,7 +162,7 @@
}
}
- // ---------- ILoggerFactory
-----------------------------------------------
+ // ---------- ILoggerFactory
/**
* Returns the name logger. If no logger for the name already exists, it is
@@ -184,7 +184,35 @@
return slingLogger;
}
- // ---------- Configuration support
----------------------------------------
+ // ---------- SlingLogPanel support
+
+ /**
+ * Return configured {...@link SlingLoggerConfig} instances as an iterator.
+ */
+ Iterator<SlingLoggerConfig> getSlingLoggerConfigs() {
+ return configByPid.values().iterator();
+ }
+
+ /**
+ * Return configured and implicit {...@link SlingLoggerWriter} instances as
+ * an iterator.
+ */
+ Iterator<SlingLoggerWriter> getSlingLoggerWriters() {
+ // configured writers
+ Collection<SlingLoggerWriter> writers = new HashSet<SlingLoggerWriter>(
+ writerByPid.values());
+
+ // add implicit writers
+ for (SlingLoggerWriter slw : writerByFileName.values()) {
+ if (slw.getConfigurationPID() == null) {
+ writers.add(slw);
+ }
+ }
+
+ return writers.iterator();
+ }
+
+ // ---------- Configuration support
/**
* Updates or removes the log writer configuration identified by the
@@ -214,7 +242,7 @@
* {...@link LogManager#LOG_FILE_NUMBER_DEFAULT} is assumed. If the writer
* writes standard output this property is ignored.</dd>
* </dl>
- *
+ *
* @param pid The identifier of the log writer to update or remove
* @param configuration New configuration setting for the log writer or
* <code>null</code> to indicate to remove the log writer.
@@ -244,13 +272,22 @@
// ensure unique configuration of the log writer
SlingLoggerWriter existingWriter =
writerByFileName.get(logFileName);
- if (existingWriter != null
- && !existingWriter.getConfigurationPID().equals(pid)) {
- // this file is already configured by another LOG_PID
- throw new ConfigurationException(LogManager.LOG_FILE,
- "LogFile " + logFileName
- + " already configured by configuration "
- + existingWriter.getConfigurationPID());
+ if (existingWriter != null) {
+ if (slw != null) {
+
+ // this is an implicit writer being configured now
+ slw = existingWriter;
+ slw.setConfigurationPID(pid);
+ writerByPid.put(pid, slw);
+
+ } else if
(!existingWriter.getConfigurationPID().equals(pid)) {
+
+ // this file is already configured by another LOG_PID
+ throw new ConfigurationException(LogManager.LOG_FILE,
+ "LogFile " + logFileName
+ + " already configured by configuration "
+ + existingWriter.getConfigurationPID());
+ }
}
}
@@ -266,9 +303,6 @@
// don't care
}
}
- if (fileNum <= 0) {
- fileNum = LogManager.LOG_FILE_NUMBER_DEFAULT;
- }
// get the log file size
Object fileSizeProp = configuration.get(LogManager.LOG_FILE_SIZE);
@@ -276,57 +310,22 @@
if (fileSizeProp != null) {
fileSize = fileSizeProp.toString();
}
- if (fileSize == null || fileSize.length() == 0) {
- fileSize = LogManager.LOG_FILE_SIZE_DEFAULT;
- }
-
- try {
- if (slw == null) {
- slw = new SlingLoggerWriter(pid);
- slw.configure(logFileName, fileNum, fileSize);
- writerByPid.put(pid, slw);
- if (logFileName != null) {
- writerByFileName.put(logFileName, slw);
- }
- } else {
- slw.configure(logFileName, fileNum, fileSize);
- }
- } catch (IOException ioe) {
- internalFailure("Cannot create log file " + logFileName, ioe);
- internalFailure("Logging to the console", null);
+ if (configureLogWriter(slw, pid, logFileName, fileNum, fileSize)
== null) {
throw new ConfigurationException(LogManager.LOG_FILE,
"Cannot create writer for log file " + logFileName);
}
} else {
- SlingLoggerWriter logWriter = writerByPid.remove(pid);
+ final SlingLoggerWriter logWriter = writerByPid.remove(pid);
if (logWriter != null) {
- // if the writer is writing to a file, remove the file mapping
- String path = logWriter.getPath();
- if (path != null) {
- writerByFileName.remove(path);
- }
+ // make the writer implicit
+ logWriter.setConfigurationPID(null);
- // make sure, no configuration is referring to this writer
- // any more
- for (SlingLoggerConfig config : configByPid.values()) {
- if (config.getLogWriter() == logWriter) {
- log.info(
- "updateLogWriter: Resetting configuration {} to
the standard log writer",
- config.getConfigPid());
- config.setLogWriter(defaultWriter);
- }
- }
-
- // close the removed log writer
- try {
- logWriter.close();
- } catch (IOException ioe) {
- // don't care
- }
+ // close if unused, otherwise reconfigure to default values
+ closeIfUnused(logWriter, true);
}
}
}
@@ -364,7 +363,7 @@
* file configured for any log writer or it may be the configuration PID of
* such a writer. If this property is missing or empty or does not refer to
* an existing log writer configuration, the default log writer is
used.</dd>
- *
+ *
* @param pid The name of the configuration to update or remove.
* @param configuration The configuration object.
* @throws ConfigurationException If the log level and logger names
@@ -409,7 +408,7 @@
file = getAbsoluteLogFile(file);
writer = writerByFileName.get(file);
if (writer == null) {
- writer = defaultWriter;
+ writer = configureLogWriter(null, null, file, -1,
null);
}
}
}
@@ -441,25 +440,32 @@
} else {
// remove category to configuration mappings
- Set<String> oldCategories = config.getCategories();
+ final Set<String> oldCategories = config.getCategories();
+
+ // check whether the log writer is to be changed
+ final SlingLoggerWriter oldWriter = config.getLogWriter();
// reconfigure the configuration
config.configure(pattern, categories, logLevel, writer);
if (categories.equals(oldCategories)) {
- // remove the old categories if different from the new ones
- configByCategory.keySet().removeAll(oldCategories);
-
- } else {
-
// no need to change category registrations, clear them
// also no need to reconfigure the loggers
categories.clear();
reconfigureLoggers = false;
+ } else {
+
+ // remove the old categories if different from the new ones
+ configByCategory.keySet().removeAll(oldCategories);
+
}
+ // close the old log writer if replaced and not used any more
+ if (oldWriter != writer) {
+ closeIfUnused(oldWriter, false);
+ }
}
// relink categories
@@ -474,9 +480,12 @@
// remove configuration from pid list
SlingLoggerConfig config = configByPid.remove(pid);
- // remove all configured categories
if (config != null) {
+ // remove all configured categories
configByCategory.keySet().removeAll(config.getCategories());
+
+ // close the writer if unused (and unconfigured)
+ closeIfUnused(config.getLogWriter(), false);
}
}
@@ -495,7 +504,7 @@
* is returned unmodified. Otherwise it is made absolute by resolving it
* relative to the root directory set on this instance by the
* {...@link #setRoot(String)} method.
- *
+ *
* @throws NullPointerException if <code>logFileName</code> is
* <code>null</code>.
*/
@@ -569,7 +578,7 @@
* an array of strings or a collection of strings. Each string may in turn
be a
* comma-separated list of strings. Each entry makes up an entry in the
* resulting set.
- *
+ *
* @param loggers The configuration object to be decomposed. If this is
* <code>null</code>, <code>null</code> is returned
* immediately
@@ -622,4 +631,115 @@
return loggerNames;
}
+ /**
+ * Configures and returns a {...@link SlingLoggerWriter}. If the
+ * <code>pid</code> is not <code>null</code> the writer is also added to
the
+ * by pid map. If the <code>fileName</code> is not <code>null</code> the
+ * writer is also added to the file name map.
+ *
+ * @param writer The {...@link SlingLoggerWriter} to configure. If this is
+ * <code>null</code> a new instance is created.
+ * @param pid The configuration PID to set on the <code>writer</code>. This
+ * may be <code>null</code> to indicate that the logger writer
is
+ * not configured by any configuration.
+ * @param fileName The name of the file to log to.
+ * @param fileNum The number of log files to keep (if rotating by size) or
+ * -1 to assume the default (
+ * {...@link
java.util.logging.LogManager#LOG_FILE_NUMBER_DEFAULT}).
+ * @param threshold The log rotation threashold (size or data/time format
+ * pattern or <code>null</code> to assume the default (
+ * {...@link
java.util.logging.LogManager#LOG_FILE_SIZE_DEFAULT}).
+ * @return The {...@link SlingLoggerWriter} or <code>null</code> if an
error
+ * occurrs configuring the writer.
+ */
+ private SlingLoggerWriter configureLogWriter(SlingLoggerWriter writer,
+ String pid, String fileName, int fileNum, String threshold) {
+
+ // create the writer instance if it is new
+ if (writer == null) {
+ writer = new SlingLoggerWriter(pid);
+ } else {
+ writer.setConfigurationPID(pid);
+ }
+
+ if (fileNum < 0) {
+ fileNum = LogManager.LOG_FILE_NUMBER_DEFAULT;
+ }
+
+ if (threshold == null || threshold.length() == 0) {
+ threshold = LogManager.LOG_FILE_SIZE_DEFAULT;
+ }
+
+ try {
+ writer.configure(fileName, fileNum, threshold);
+ } catch (IOException ioe) {
+ internalFailure("Cannot create log file " + fileName, ioe);
+ internalFailure("Logging to the console", null);
+ return null;
+ }
+
+ // add to maps
+ if (pid != null) {
+ writerByPid.put(pid, writer);
+ }
+ if (fileName != null) {
+ writerByFileName.put(fileName, writer);
+ }
+
+ // everything set and done
+ return writer;
+ }
+
+ /**
+ * Closes or resets the given <code>logWriter</code> if it is not referred
+ * to by any logger config or writer configuration.
+ *
+ * @param logWriter The {...@link SlingLoggerWriter} to close or
(optionally)
+ * reconfigure.
+ * @param reset Whether the log writer should be reset to default values if
+ * it is still referred to by any logger configuration.
+ */
+ private void closeIfUnused(SlingLoggerWriter logWriter, boolean reset) {
+
+ // The log writer is based on configuration, don't touch
+ if (logWriter.getConfigurationPID() != null) {
+ return;
+ }
+
+ // "Implicit" writer : check for references
+ for (SlingLoggerConfig config : configByPid.values()) {
+ if (config.getLogWriter() == logWriter) {
+
+ // optionally reconfigure to default values
+ if (reset) {
+ try {
+ logWriter.configure(logWriter.getPath(),
+ LogManager.LOG_FILE_NUMBER_DEFAULT,
+ LogManager.LOG_FILE_SIZE_DEFAULT);
+ } catch (IOException ioe) {
+ internalFailure(
+ "Cannot reset the log writer to default
configuration",
+ ioe);
+ }
+ }
+
+ // done here...
+ return;
+ }
+ }
+ // invariant: writer is not used and not configured any more
+
+ // remove from the writer file name map
+ String path = logWriter.getPath();
+ if (path != null) {
+ writerByFileName.remove(path);
+ }
+
+ // close it to clean up
+ try {
+ logWriter.close();
+ } catch (IOException ioe) {
+ // don't care
+ }
+ }
}
Modified:
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerWriter.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerWriter.java?rev=797030&r1=797029&r2=797030&view=diff
==============================================================================
---
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerWriter.java
(original)
+++
sling/trunk/bundles/commons/log/src/main/java/org/apache/sling/commons/log/internal/slf4j/SlingLoggerWriter.java
Thu Jul 23 11:53:01 2009
@@ -56,9 +56,10 @@
/**
* The PID of the configuration from which this instance has been
- * configured.
+ * configured. If this is <code>null</code> this instance is an implicitly
+ * created instance which is not tied to any configuration.
*/
- private final String configurationPID;
+ private String configurationPID;
/**
* The actual <code>Writer</code> to which this instance delegates any
@@ -162,14 +163,32 @@
}
}
+ /**
+ * Returns the PID of the configuration configuring this instance. This may
+ * be <code>null</code> if this is an implicitly defined log writer
+ * instance.
+ */
String getConfigurationPID() {
return configurationPID;
}
+ /**
+ * Sets the PID of the configuration configuring this instance. This may be
+ * <code>null</code> if the configuration is removed but the writer is
still
+ * referred to by any logger configuration.
+ */
+ void setConfigurationPID(String configurationPID) {
+ this.configurationPID = configurationPID;
+ }
+
String getPath() {
return path;
}
+ FileRotator getFileRotator() {
+ return fileRotator;
+ }
+
// ---------- Writer Overwrite
---------------------------------------------
@Override