This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/2.x by this push:
new 4b7065b8b3 Simplify file manager registry factory pattern (#3968)
4b7065b8b3 is described below
commit 4b7065b8b3818cabb88cf1d553da33897b733413
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Tue Nov 11 22:12:22 2025 +0100
Simplify file manager registry factory pattern (#3968)
* Simplify file manager registry factory pattern
The current factory pattern used with the `AbstractManager` registry is
unnecessarily complex. It relies on:
* **Stateless factory classes** to create managers of each type,
* **Separate `FactoryData` parameter objects** to pass construction data
#### What this PR does
This PR simplifies the registry factory mechanism by:
* Replacing the factory classes with **inline lambda factories**
* Allowing **stateful factory lambdas**, removing boilerplate `FactoryData`
classes in most cases
* Keeping factory logic **localized and easier to follow** within the
registry call site
This is a **pure refactoring**, it does not change behavior. It improves
code readability and maintainability by reducing indirection and eliminating
unnecessary types.
#### Notes
`FactoryData` parameter objects are still used where necessary:
* **`RollingFileManager`** and **`RollingRandomAccessFileManager`** still
require parameter objects since they update state on each retrieval, not just
during initialization.
* Other managers still pass `Configuration` through
`ConfigurationFactoryData` to access `getLoggerContext()`, which remains useful.
* fix: add reference to PR number
* Apply suggestions from code review
Co-authored-by: Volkan Yazıcı <[email protected]>
---------
Co-authored-by: Volkan Yazıcı <[email protected]>
---
.../log4j/core/appender/AbstractManager.java | 1 +
.../logging/log4j/core/appender/FileManager.java | 162 +++-----------
.../core/appender/MemoryMappedFileManager.java | 85 +++----
.../core/appender/RandomAccessFileManager.java | 120 +++-------
.../core/appender/rolling/RollingFileManager.java | 227 +++++--------------
.../rolling/RollingRandomAccessFileManager.java | 249 ++++++---------------
.../.2.x.x/3968_refactor_manager_factories.xml | 12 +
7 files changed, 242 insertions(+), 614 deletions(-)
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
index 4049419542..593f8f5ff3 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
@@ -133,6 +133,7 @@ public abstract class AbstractManager implements
AutoCloseable {
* @param <M> The Type of the Manager to be created.
* @param <T> The type of the Factory data.
* @return A Manager with the specified name and type.
+ * @throws IllegalStateException if the factory is unable to create the
manager
*/
// @SuppressWarnings("resource"): this is a factory method, the resource
is allocated and released elsewhere.
@SuppressWarnings("resource")
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
index 46123ce074..75f933790d 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
@@ -50,8 +50,6 @@ import org.apache.logging.log4j.core.util.FileUtils;
*/
public class FileManager extends OutputStreamManager {
- private static final FileManagerFactory FACTORY = new FileManagerFactory();
-
private final boolean isAppend;
private final boolean createOnDemand;
private final boolean isLocking;
@@ -194,7 +192,7 @@ public class FileManager extends OutputStreamManager {
* @param locking true if the file should be locked while writing, false
otherwise.
* @param bufferedIo true if the contents should be buffered as they are
written.
* @param createOnDemand true if you want to lazy-create the file (a.k.a.
on-demand.)
- * @param advertiseUri the URI to use when advertising the file
+ * @param advertiseURI the URI to use when advertising the file
* @param layout The layout
* @param bufferSize buffer size for buffered IO
* @param filePermissions File permissions
@@ -209,34 +207,52 @@ public class FileManager extends OutputStreamManager {
boolean locking,
final boolean bufferedIo,
final boolean createOnDemand,
- final String advertiseUri,
+ final String advertiseURI,
final Layout<? extends Serializable> layout,
final int bufferSize,
final String filePermissions,
final String fileOwner,
final String fileGroup,
final Configuration configuration) {
-
- if (locking && bufferedIo) {
- locking = false;
- }
+ // Disable locking if buffered IO is enabled
+ boolean actualLocking = !bufferedIo && locking;
+ int actualBufferSize = bufferedIo ? bufferSize :
Constants.ENCODER_BYTE_BUFFER_SIZE;
return narrow(
FileManager.class,
getManager(
fileName,
- new FactoryData(
- append,
- locking,
- bufferedIo,
- bufferSize,
- createOnDemand,
- advertiseUri,
- layout,
- filePermissions,
- fileOwner,
- fileGroup,
- configuration),
- FACTORY));
+ (name, data) -> {
+ Objects.requireNonNull(name, "filename is
missing");
+ final File file = new File(name);
+ try {
+ FileUtils.makeParentDirs(file);
+ final boolean writeHeader = !append ||
!file.exists();
+ final ByteBuffer byteBuffer =
ByteBuffer.allocate(actualBufferSize);
+ final FileOutputStream fos = createOnDemand ?
null : new FileOutputStream(file, append);
+ final FileManager fm = new FileManager(
+ data.getLoggerContext(),
+ name,
+ fos,
+ append,
+ actualLocking,
+ createOnDemand,
+ advertiseURI,
+ layout,
+ filePermissions,
+ fileOwner,
+ fileGroup,
+ writeHeader,
+ byteBuffer);
+ if (fos != null && fm.attributeViewEnabled) {
+ fm.defineAttributeView(file.toPath());
+ }
+ return fm;
+ } catch (final IOException ex) {
+ LOGGER.error("FileManager ({}): {}", name, ex);
+ }
+ return null;
+ },
+ new ConfigurationFactoryData(configuration)));
}
@Override
@@ -426,108 +442,4 @@ public class FileManager extends OutputStreamManager {
result.put("fileURI", advertiseURI);
return result;
}
-
- /**
- * Factory Data.
- */
- private static class FactoryData extends ConfigurationFactoryData {
- private final boolean append;
- private final boolean locking;
- private final boolean bufferedIo;
- private final int bufferSize;
- private final boolean createOnDemand;
- private final String advertiseURI;
- private final Layout<? extends Serializable> layout;
- private final String filePermissions;
- private final String fileOwner;
- private final String fileGroup;
-
- /**
- * Constructor.
- * @param append Append status.
- * @param locking Locking status.
- * @param bufferedIo Buffering flag.
- * @param bufferSize Buffer size.
- * @param createOnDemand if you want to lazy-create the file (a.k.a.
on-demand.)
- * @param advertiseURI the URI to use when advertising the file
- * @param layout The layout
- * @param filePermissions File permissions
- * @param fileOwner File owner
- * @param fileGroup File group
- * @param configuration the configuration
- */
- public FactoryData(
- final boolean append,
- final boolean locking,
- final boolean bufferedIo,
- final int bufferSize,
- final boolean createOnDemand,
- final String advertiseURI,
- final Layout<? extends Serializable> layout,
- final String filePermissions,
- final String fileOwner,
- final String fileGroup,
- final Configuration configuration) {
- super(configuration);
- this.append = append;
- this.locking = locking;
- this.bufferedIo = bufferedIo;
- this.bufferSize = bufferSize;
- this.createOnDemand = createOnDemand;
- this.advertiseURI = advertiseURI;
- this.layout = layout;
- this.filePermissions = filePermissions;
- this.fileOwner = fileOwner;
- this.fileGroup = fileGroup;
- }
- }
-
- /**
- * Factory to create a FileManager.
- */
- private static class FileManagerFactory implements
ManagerFactory<FileManager, FactoryData> {
-
- /**
- * Creates a FileManager.
- * @param name The name of the File.
- * @param data The FactoryData
- * @return The FileManager for the File.
- */
- @Override
- @SuppressFBWarnings(
- value = "PATH_TRAVERSAL_IN",
- justification = "The destination file should be specified in
the configuration file.")
- public FileManager createManager(final String name, final FactoryData
data) {
- Objects.requireNonNull(name, "filename is missing");
- final File file = new File(name);
- try {
- FileUtils.makeParentDirs(file);
- final boolean writeHeader = !data.append || !file.exists();
- final int actualSize = data.bufferedIo ? data.bufferSize :
Constants.ENCODER_BYTE_BUFFER_SIZE;
- final ByteBuffer byteBuffer = ByteBuffer.wrap(new
byte[actualSize]);
- final FileOutputStream fos = data.createOnDemand ? null : new
FileOutputStream(file, data.append);
- final FileManager fm = new FileManager(
- data.getLoggerContext(),
- name,
- fos,
- data.append,
- data.locking,
- data.createOnDemand,
- data.advertiseURI,
- data.layout,
- data.filePermissions,
- data.fileOwner,
- data.fileGroup,
- writeHeader,
- byteBuffer);
- if (fos != null && fm.attributeViewEnabled) {
- fm.defineAttributeView(file.toPath());
- }
- return fm;
- } catch (final IOException ex) {
- LOGGER.error("FileManager (" + name + ") " + ex, ex);
- }
- return null;
- }
- }
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
index d5f8949adb..595072ee3f 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/MemoryMappedFileManager.java
@@ -16,7 +16,6 @@
*/
package org.apache.logging.log4j.core.appender;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
@@ -58,7 +57,6 @@ public class MemoryMappedFileManager extends
OutputStreamManager {
static final int DEFAULT_REGION_LENGTH = 32 * 1024 * 1024;
private static final int MAX_REMAP_COUNT = 10;
- private static final MemoryMappedFileManagerFactory FACTORY = new
MemoryMappedFileManagerFactory();
private static final double NANOS_PER_MILLISEC = 1000.0 * 1000.0;
private final boolean immediateFlush;
@@ -111,8 +109,37 @@ public class MemoryMappedFileManager extends
OutputStreamManager {
MemoryMappedFileManager.class,
getManager(
fileName,
- new FactoryData(append, immediateFlush, regionLength,
advertiseURI, layout),
- FACTORY));
+ (name, ignored) -> {
+ final File file = new File(name);
+ if (!append) {
+ file.delete();
+ }
+
+ final boolean writeHeader = !append ||
!file.exists();
+ final OutputStream os =
NullOutputStream.getInstance();
+ RandomAccessFile raf = null;
+ try {
+ FileUtils.makeParentDirs(file);
+ raf = new RandomAccessFile(name, "rw");
+ final long position = (append) ? raf.length()
: 0;
+ raf.setLength(position + regionLength);
+ return new MemoryMappedFileManager(
+ raf,
+ name,
+ os,
+ immediateFlush,
+ position,
+ regionLength,
+ advertiseURI,
+ layout,
+ writeHeader);
+ } catch (final Exception ex) {
+ LOGGER.error("MemoryMappedFileManager (" +
name + ") " + ex, ex);
+ Closer.closeSilently(raf);
+ }
+ return null;
+ },
+ (Void) null));
}
/**
@@ -341,54 +368,4 @@ public class MemoryMappedFileManager extends
OutputStreamManager {
this.layout = layout;
}
}
-
- /**
- * Factory to create a MemoryMappedFileManager.
- */
- private static class MemoryMappedFileManagerFactory
- implements ManagerFactory<MemoryMappedFileManager, FactoryData> {
-
- /**
- * Create a MemoryMappedFileManager.
- *
- * @param name The name of the File.
- * @param data The FactoryData
- * @return The MemoryMappedFileManager for the File.
- */
- @SuppressWarnings("resource")
- @Override
- @SuppressFBWarnings(
- value = "PATH_TRAVERSAL_IN",
- justification = "The destination file should be specified in
the configuration file.")
- public MemoryMappedFileManager createManager(final String name, final
FactoryData data) {
- final File file = new File(name);
- if (!data.append) {
- file.delete();
- }
-
- final boolean writeHeader = !data.append || !file.exists();
- final OutputStream os = NullOutputStream.getInstance();
- RandomAccessFile raf = null;
- try {
- FileUtils.makeParentDirs(file);
- raf = new RandomAccessFile(name, "rw");
- final long position = (data.append) ? raf.length() : 0;
- raf.setLength(position + data.regionLength);
- return new MemoryMappedFileManager(
- raf,
- name,
- os,
- data.immediateFlush,
- position,
- data.regionLength,
- data.advertiseURI,
- data.layout,
- writeHeader);
- } catch (final Exception ex) {
- LOGGER.error("MemoryMappedFileManager (" + name + ") " + ex,
ex);
- Closer.closeSilently(raf);
- }
- return null;
- }
- }
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/RandomAccessFileManager.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/RandomAccessFileManager.java
index 41d503d0b1..bb94e9fb42 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/RandomAccessFileManager.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/RandomAccessFileManager.java
@@ -16,7 +16,6 @@
*/
package org.apache.logging.log4j.core.appender;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
@@ -39,8 +38,6 @@ import org.apache.logging.log4j.core.util.NullOutputStream;
public class RandomAccessFileManager extends OutputStreamManager {
static final int DEFAULT_BUFFER_SIZE = 256 * 1024;
- private static final RandomAccessFileManagerFactory FACTORY = new
RandomAccessFileManagerFactory();
-
private final String advertiseURI;
private final RandomAccessFile randomAccessFile;
@@ -84,8 +81,38 @@ public class RandomAccessFileManager extends
OutputStreamManager {
RandomAccessFileManager.class,
getManager(
fileName,
- new FactoryData(append, immediateFlush, bufferSize,
advertiseURI, layout, configuration),
- FACTORY));
+ (name, data) -> {
+ final File file = new File(name);
+ if (!append) {
+ file.delete();
+ }
+
+ final boolean writeHeader = !append ||
!file.exists();
+ final OutputStream os =
NullOutputStream.getInstance();
+ RandomAccessFile raf;
+ try {
+ FileUtils.makeParentDirs(file);
+ raf = new RandomAccessFile(name, "rw");
+ if (append) {
+ raf.seek(raf.length());
+ } else {
+ raf.setLength(0);
+ }
+ return new RandomAccessFileManager(
+ data.getLoggerContext(),
+ raf,
+ name,
+ os,
+ bufferSize,
+ advertiseURI,
+ layout,
+ writeHeader);
+ } catch (final Exception ex) {
+ LOGGER.error("RandomAccessFileManager (" +
name + ") " + ex, ex);
+ }
+ return null;
+ },
+ new ConfigurationFactoryData(configuration)));
}
/**
@@ -164,87 +191,4 @@ public class RandomAccessFileManager extends
OutputStreamManager {
result.put("fileURI", advertiseURI);
return result;
}
-
- /**
- * Factory Data.
- */
- private static class FactoryData extends ConfigurationFactoryData {
- private final boolean append;
- private final boolean immediateFlush;
- private final int bufferSize;
- private final String advertiseURI;
- private final Layout<? extends Serializable> layout;
-
- /**
- * Constructor.
- *
- * @param append Append status.
- * @param bufferSize size of the buffer
- * @param configuration The configuration.
- */
- public FactoryData(
- final boolean append,
- final boolean immediateFlush,
- final int bufferSize,
- final String advertiseURI,
- final Layout<? extends Serializable> layout,
- final Configuration configuration) {
- super(configuration);
- this.append = append;
- this.immediateFlush = immediateFlush;
- this.bufferSize = bufferSize;
- this.advertiseURI = advertiseURI;
- this.layout = layout;
- }
- }
-
- /**
- * Factory to create a RandomAccessFileManager.
- */
- private static class RandomAccessFileManagerFactory
- implements ManagerFactory<RandomAccessFileManager, FactoryData> {
-
- /**
- * Create a RandomAccessFileManager.
- *
- * @param name The name of the File.
- * @param data The FactoryData
- * @return The RandomAccessFileManager for the File.
- */
- @Override
- @SuppressFBWarnings(
- value = "PATH_TRAVERSAL_IN",
- justification = "The destination file should be specified in
the configuration file.")
- public RandomAccessFileManager createManager(final String name, final
FactoryData data) {
- final File file = new File(name);
- if (!data.append) {
- file.delete();
- }
-
- final boolean writeHeader = !data.append || !file.exists();
- final OutputStream os = NullOutputStream.getInstance();
- RandomAccessFile raf;
- try {
- FileUtils.makeParentDirs(file);
- raf = new RandomAccessFile(name, "rw");
- if (data.append) {
- raf.seek(raf.length());
- } else {
- raf.setLength(0);
- }
- return new RandomAccessFileManager(
- data.getLoggerContext(),
- raf,
- name,
- os,
- data.bufferSize,
- data.advertiseURI,
- data.layout,
- writeHeader);
- } catch (final Exception ex) {
- LOGGER.error("RandomAccessFileManager (" + name + ") " + ex,
ex);
- }
- return null;
- }
- }
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
index 7aec034036..8be7dd4f9c 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
@@ -43,7 +43,6 @@ import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConfigurationFactoryData;
import org.apache.logging.log4j.core.appender.FileManager;
-import org.apache.logging.log4j.core.appender.ManagerFactory;
import org.apache.logging.log4j.core.appender.rolling.action.AbstractAction;
import org.apache.logging.log4j.core.appender.rolling.action.Action;
import org.apache.logging.log4j.core.config.Configuration;
@@ -56,7 +55,6 @@ import org.apache.logging.log4j.core.util.Log4jThreadFactory;
*/
public class RollingFileManager extends FileManager {
- private static RollingFileManagerFactory factory = new
RollingFileManagerFactory();
private static final int MAX_TRIES = 3;
private static final int MIN_DURATION = 100;
private static final FileTime EPOCH = FileTime.fromMillis(0);
@@ -296,33 +294,71 @@ public class RollingFileManager extends FileManager {
final String fileOwner,
final String fileGroup,
final Configuration configuration) {
-
if (strategy instanceof DirectWriteRolloverStrategy && fileName !=
null) {
LOGGER.error("The fileName attribute must not be specified with
the DirectWriteRolloverStrategy");
return null;
}
- final String name = fileName == null ? pattern : fileName;
+ String actualName = fileName == null ? pattern : fileName;
+ int actualBufferSize = bufferedIO ? bufferSize :
Constants.ENCODER_BYTE_BUFFER_SIZE;
return narrow(
RollingFileManager.class,
getManager(
- name,
- new FactoryData(
- fileName,
- pattern,
- append,
- bufferedIO,
- policy,
- strategy,
- advertiseURI,
- layout,
- bufferSize,
- immediateFlush,
- createOnDemand,
- filePermissions,
- fileOwner,
- fileGroup,
- configuration),
- factory));
+ actualName,
+ (name, data) -> {
+ long size = 0;
+ File file = null;
+ if (fileName != null) {
+ file = new File(fileName);
+
+ try {
+ FileUtils.makeParentDirs(file);
+ final boolean created = createOnDemand ?
false : file.createNewFile();
+ LOGGER.trace("New file '{}' created = {}",
name, created);
+ } catch (final IOException ioe) {
+ LOGGER.error("Unable to create file {}",
name, ioe);
+ return null;
+ }
+ size = append ? file.length() : 0;
+ }
+
+ try {
+ final ByteBuffer buffer =
ByteBuffer.allocate(actualBufferSize);
+ final OutputStream os = createOnDemand ||
fileName == null
+ ? null
+ : new FileOutputStream(fileName,
append);
+ // LOG4J2-531 create file first so time has
valid value.
+ final long initialTime = file == null ||
!file.exists() ? 0 : initialFileTime(file);
+ final boolean writeHeader = file != null &&
file.exists() && file.length() == 0;
+
+ final RollingFileManager rm = new
RollingFileManager(
+ data.getLoggerContext(),
+ fileName,
+ data.getPattern(),
+ os,
+ append,
+ createOnDemand,
+ size,
+ initialTime,
+ data.getTriggeringPolicy(),
+ data.getRolloverStrategy(),
+ advertiseURI,
+ layout,
+ filePermissions,
+ fileOwner,
+ fileGroup,
+ writeHeader,
+ buffer);
+ if (os != null && rm.isAttributeViewEnabled())
{
+ rm.defineAttributeView(file.toPath());
+ }
+
+ return rm;
+ } catch (final IOException ex) {
+ LOGGER.error("RollingFileManager ({}): {}",
name, ex.getMessage(), ex);
+ }
+ return null;
+ },
+ new FactoryData(pattern, policy, strategy,
configuration)));
}
/**
@@ -718,69 +754,28 @@ public class RollingFileManager extends FileManager {
/**
* Factory data.
+ *
+ * <p>This is also used by {@link RollingRandomAccessFileManager}.</p>
*/
- private static class FactoryData extends ConfigurationFactoryData {
- private final String fileName;
+ static class FactoryData extends ConfigurationFactoryData {
private final String pattern;
- private final boolean append;
- private final boolean bufferedIO;
- private final int bufferSize;
- private final boolean immediateFlush;
- private final boolean createOnDemand;
private final TriggeringPolicy policy;
private final RolloverStrategy strategy;
- private final String advertiseURI;
- private final Layout<? extends Serializable> layout;
- private final String filePermissions;
- private final String fileOwner;
- private final String fileGroup;
/**
* Creates the data for the factory.
* @param pattern The pattern.
- * @param append The append flag.
- * @param bufferedIO The bufferedIO flag.
- * @param advertiseURI
- * @param layout The Layout.
- * @param bufferSize the buffer size
- * @param immediateFlush flush on every write or not
- * @param createOnDemand true if you want to lazy-create the file
(a.k.a. on-demand.)
- * @param filePermissions File permissions
- * @param fileOwner File owner
- * @param fileGroup File group
* @param configuration The configuration
*/
public FactoryData(
- final String fileName,
final String pattern,
- final boolean append,
- final boolean bufferedIO,
final TriggeringPolicy policy,
final RolloverStrategy strategy,
- final String advertiseURI,
- final Layout<? extends Serializable> layout,
- final int bufferSize,
- final boolean immediateFlush,
- final boolean createOnDemand,
- final String filePermissions,
- final String fileOwner,
- final String fileGroup,
final Configuration configuration) {
super(configuration);
- this.fileName = fileName;
this.pattern = pattern;
- this.append = append;
- this.bufferedIO = bufferedIO;
- this.bufferSize = bufferSize;
this.policy = policy;
this.strategy = strategy;
- this.advertiseURI = advertiseURI;
- this.layout = layout;
- this.immediateFlush = immediateFlush;
- this.createOnDemand = createOnDemand;
- this.filePermissions = filePermissions;
- this.fileOwner = fileOwner;
- this.fileGroup = fileGroup;
}
public TriggeringPolicy getTriggeringPolicy() {
@@ -794,34 +789,6 @@ public class RollingFileManager extends FileManager {
public String getPattern() {
return pattern;
}
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append(super.toString());
- builder.append("[pattern=");
- builder.append(pattern);
- builder.append(", append=");
- builder.append(append);
- builder.append(", bufferedIO=");
- builder.append(bufferedIO);
- builder.append(", bufferSize=");
- builder.append(bufferSize);
- builder.append(", policy=");
- builder.append(policy);
- builder.append(", strategy=");
- builder.append(strategy);
- builder.append(", advertiseURI=");
- builder.append(advertiseURI);
- builder.append(", layout=");
- builder.append(layout);
- builder.append(", filePermissions=");
- builder.append(filePermissions);
- builder.append(", fileOwner=");
- builder.append(fileOwner);
- builder.append("]");
- return builder.toString();
- }
}
/**
@@ -838,78 +805,6 @@ public class RollingFileManager extends FileManager {
setTriggeringPolicy(factoryData.getTriggeringPolicy());
}
- /**
- * Factory to create a RollingFileManager.
- */
- private static class RollingFileManagerFactory implements
ManagerFactory<RollingFileManager, FactoryData> {
-
- /**
- * Creates a RollingFileManager.
- * @param name The name of the entity to manage.
- * @param data The data required to create the entity.
- * @return a RollingFileManager.
- */
- @Override
- @SuppressFBWarnings(
- value = {"PATH_TRAVERSAL_IN", "PATH_TRAVERSAL_OUT"},
- justification = "The destination file should be specified in
the configuration file.")
- public RollingFileManager createManager(final String name, final
FactoryData data) {
- long size = 0;
- File file = null;
- if (data.fileName != null) {
- file = new File(data.fileName);
-
- try {
- FileUtils.makeParentDirs(file);
- final boolean created = data.createOnDemand ? false :
file.createNewFile();
- LOGGER.trace("New file '{}' created = {}", name, created);
- } catch (final IOException ioe) {
- LOGGER.error("Unable to create file " + name, ioe);
- return null;
- }
- size = data.append ? file.length() : 0;
- }
-
- try {
- final int actualSize = data.bufferedIO ? data.bufferSize :
Constants.ENCODER_BYTE_BUFFER_SIZE;
- final ByteBuffer buffer = ByteBuffer.wrap(new
byte[actualSize]);
- final OutputStream os = data.createOnDemand || data.fileName
== null
- ? null
- : new FileOutputStream(data.fileName, data.append);
- // LOG4J2-531 create file first so time has valid value.
- final long initialTime = file == null || !file.exists() ? 0 :
initialFileTime(file);
- final boolean writeHeader = file != null && file.exists() &&
file.length() == 0;
-
- final RollingFileManager rm = new RollingFileManager(
- data.getLoggerContext(),
- data.fileName,
- data.pattern,
- os,
- data.append,
- data.createOnDemand,
- size,
- initialTime,
- data.policy,
- data.strategy,
- data.advertiseURI,
- data.layout,
- data.filePermissions,
- data.fileOwner,
- data.fileGroup,
- writeHeader,
- buffer);
- if (os != null && rm.isAttributeViewEnabled()) {
- rm.defineAttributeView(file.toPath());
- }
-
- return rm;
- } catch (final IOException ex) {
- LOGGER.error("RollingFileManager (" + name + ") " + ex, ex);
- }
- return null;
- }
- }
-
static long initialFileTime(final File file) {
final Path path = file.toPath();
if (Files.exists(path)) {
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
index 047e397dd1..bd41ce31c7 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
@@ -27,8 +27,6 @@ import java.nio.file.Paths;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.AppenderLoggingException;
-import org.apache.logging.log4j.core.appender.ConfigurationFactoryData;
-import org.apache.logging.log4j.core.appender.ManagerFactory;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.util.FileUtils;
import org.apache.logging.log4j.core.util.NullOutputStream;
@@ -43,8 +41,6 @@ public class RollingRandomAccessFileManager extends
RollingFileManager {
*/
public static final int DEFAULT_BUFFER_SIZE = 256 * 1024;
- private static final RollingRandomAccessFileManagerFactory FACTORY = new
RollingRandomAccessFileManagerFactory();
-
private RandomAccessFile randomAccessFile;
@Deprecated
@@ -153,7 +149,7 @@ public class RollingRandomAccessFileManager extends
RollingFileManager {
public static RollingRandomAccessFileManager
getRollingRandomAccessFileManager(
final String fileName,
final String filePattern,
- final boolean isAppend,
+ final boolean append,
final boolean immediateFlush,
final int bufferSize,
final TriggeringPolicy policy,
@@ -168,26 +164,76 @@ public class RollingRandomAccessFileManager extends
RollingFileManager {
LOGGER.error("The fileName attribute must not be specified with
the DirectWriteRolloverStrategy");
return null;
}
- final String name = fileName == null ? filePattern : fileName;
+ final String actualName = fileName == null ? filePattern : fileName;
return narrow(
RollingRandomAccessFileManager.class,
getManager(
- name,
- new FactoryData(
- fileName,
- filePattern,
- isAppend,
- immediateFlush,
- bufferSize,
- policy,
- strategy,
- advertiseURI,
- layout,
- filePermissions,
- fileOwner,
- fileGroup,
- configuration),
- FACTORY));
+ actualName,
+ (name, data) -> {
+ File file = null;
+ long size = 0;
+ long time = System.currentTimeMillis();
+ RandomAccessFile raf = null;
+ if (fileName != null) {
+ file = new File(name);
+
+ if (!append) {
+ file.delete();
+ }
+ size = append ? file.length() : 0;
+ if (file.exists()) {
+ time = file.lastModified();
+ }
+ try {
+ FileUtils.makeParentDirs(file);
+ raf = new RandomAccessFile(name, "rw");
+ if (append) {
+ final long length = raf.length();
+ LOGGER.trace("RandomAccessFile {} seek
to {}", name, length);
+ raf.seek(length);
+ } else {
+ LOGGER.trace("RandomAccessFile {} set
length to 0", name);
+ raf.setLength(0);
+ }
+ } catch (final IOException ex) {
+ LOGGER.error("Cannot access
RandomAccessFile " + ex, ex);
+ if (raf != null) {
+ try {
+ raf.close();
+ } catch (final IOException e) {
+ LOGGER.error("Cannot close
RandomAccessFile {}", name, e);
+ }
+ }
+ return null;
+ }
+ }
+ final boolean writeHeader = !append || file ==
null || !file.exists();
+
+ final RollingRandomAccessFileManager rrm = new
RollingRandomAccessFileManager(
+ data.getLoggerContext(),
+ raf,
+ name,
+ data.getPattern(),
+ NullOutputStream.getInstance(),
+ append,
+ immediateFlush,
+ bufferSize,
+ size,
+ time,
+ data.getTriggeringPolicy(),
+ data.getRolloverStrategy(),
+ advertiseURI,
+ layout,
+ filePermissions,
+ fileOwner,
+ fileGroup,
+ writeHeader);
+ if (rrm.isAttributeViewEnabled()) {
+ rrm.defineAttributeView(file.toPath());
+ }
+ return rrm;
+ },
+ new FactoryData(filePattern, policy, strategy,
configuration)));
}
/**
@@ -284,165 +330,6 @@ public class RollingRandomAccessFileManager extends
RollingFileManager {
return byteBuffer.capacity();
}
- /**
- * Factory to create a RollingRandomAccessFileManager.
- */
- private static class RollingRandomAccessFileManagerFactory
- implements ManagerFactory<RollingRandomAccessFileManager,
FactoryData> {
-
- /**
- * Create the RollingRandomAccessFileManager.
- *
- * @param name The name of the entity to manage.
- * @param data The data required to create the entity.
- * @return a RollingFileManager.
- */
- @Override
- @SuppressFBWarnings(
- value = "PATH_TRAVERSAL_IN",
- justification = "The name of the accessed files is based on a
configuration value.")
- public RollingRandomAccessFileManager createManager(final String name,
final FactoryData data) {
- File file = null;
- long size = 0;
- long time = System.currentTimeMillis();
- RandomAccessFile raf = null;
- if (data.fileName != null) {
- file = new File(name);
-
- if (!data.append) {
- file.delete();
- }
- size = data.append ? file.length() : 0;
- if (file.exists()) {
- time = file.lastModified();
- }
- try {
- FileUtils.makeParentDirs(file);
- raf = new RandomAccessFile(name, "rw");
- if (data.append) {
- final long length = raf.length();
- LOGGER.trace("RandomAccessFile {} seek to {}", name,
length);
- raf.seek(length);
- } else {
- LOGGER.trace("RandomAccessFile {} set length to 0",
name);
- raf.setLength(0);
- }
- } catch (final IOException ex) {
- LOGGER.error("Cannot access RandomAccessFile " + ex, ex);
- if (raf != null) {
- try {
- raf.close();
- } catch (final IOException e) {
- LOGGER.error("Cannot close RandomAccessFile {}",
name, e);
- }
- }
- return null;
- }
- }
- final boolean writeHeader = !data.append || file == null ||
!file.exists();
-
- final RollingRandomAccessFileManager rrm = new
RollingRandomAccessFileManager(
- data.getLoggerContext(),
- raf,
- name,
- data.pattern,
- NullOutputStream.getInstance(),
- data.append,
- data.immediateFlush,
- data.bufferSize,
- size,
- time,
- data.policy,
- data.strategy,
- data.advertiseURI,
- data.layout,
- data.filePermissions,
- data.fileOwner,
- data.fileGroup,
- writeHeader);
- if (rrm.isAttributeViewEnabled()) {
- rrm.defineAttributeView(file.toPath());
- }
- return rrm;
- }
- }
-
- /**
- * Factory data.
- */
- private static class FactoryData extends ConfigurationFactoryData {
- private final String fileName;
- private final String pattern;
- private final boolean append;
- private final boolean immediateFlush;
- private final int bufferSize;
- private final TriggeringPolicy policy;
- private final RolloverStrategy strategy;
- private final String advertiseURI;
- private final Layout<? extends Serializable> layout;
- private final String filePermissions;
- private final String fileOwner;
- private final String fileGroup;
-
- /**
- * Create the data for the factory.
- *
- * @param fileName The file name.
- * @param pattern The pattern.
- * @param append The append flag.
- * @param immediateFlush
- * @param bufferSize
- * @param policy
- * @param strategy
- * @param advertiseURI
- * @param layout
- * @param filePermissions File permissions
- * @param fileOwner File owner
- * @param fileGroup File group
- * @param configuration
- */
- public FactoryData(
- final String fileName,
- final String pattern,
- final boolean append,
- final boolean immediateFlush,
- final int bufferSize,
- final TriggeringPolicy policy,
- final RolloverStrategy strategy,
- final String advertiseURI,
- final Layout<? extends Serializable> layout,
- final String filePermissions,
- final String fileOwner,
- final String fileGroup,
- final Configuration configuration) {
- super(configuration);
- this.fileName = fileName;
- this.pattern = pattern;
- this.append = append;
- this.immediateFlush = immediateFlush;
- this.bufferSize = bufferSize;
- this.policy = policy;
- this.strategy = strategy;
- this.advertiseURI = advertiseURI;
- this.layout = layout;
- this.filePermissions = filePermissions;
- this.fileOwner = fileOwner;
- this.fileGroup = fileGroup;
- }
-
- public String getPattern() {
- return pattern;
- }
-
- public TriggeringPolicy getTriggeringPolicy() {
- return this.policy;
- }
-
- public RolloverStrategy getRolloverStrategy() {
- return this.strategy;
- }
- }
-
/**
* Updates the RollingFileManager's data during a reconfiguration. This
method should be considered private.
* It is not thread safe and calling it outside of a reconfiguration may
lead to errors. This method may be
diff --git a/src/changelog/.2.x.x/3968_refactor_manager_factories.xml
b/src/changelog/.2.x.x/3968_refactor_manager_factories.xml
new file mode 100644
index 0000000000..887d4bf1d6
--- /dev/null
+++ b/src/changelog/.2.x.x/3968_refactor_manager_factories.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="https://logging.apache.org/xml/ns"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ https://logging.apache.org/xml/ns
+ https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
+ type="changed">
+ <issue id="3968"
link="https://github.com/apache/logging-log4j2/pull/3968"/>
+ <description format="asciidoc">
+ Simplify file manager registry factory methods
+ </description>
+</entry>