1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.builders.appender;
18
19 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
20 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
21 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
22 import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
23 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
24 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
25 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
26 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
27
28 import java.util.Properties;
29 import java.util.concurrent.atomic.AtomicBoolean;
30 import java.util.concurrent.atomic.AtomicInteger;
31 import java.util.concurrent.atomic.AtomicReference;
32
33 import org.apache.log4j.Appender;
34 import org.apache.log4j.Layout;
35 import org.apache.log4j.bridge.AppenderWrapper;
36 import org.apache.log4j.bridge.LayoutAdapter;
37 import org.apache.log4j.bridge.LayoutWrapper;
38 import org.apache.log4j.builders.AbstractBuilder;
39 import org.apache.log4j.config.Log4j1Configuration;
40 import org.apache.log4j.config.PropertiesConfiguration;
41 import org.apache.log4j.spi.Filter;
42 import org.apache.log4j.xml.XmlConfiguration;
43 import org.apache.logging.log4j.Logger;
44 import org.apache.logging.log4j.core.appender.FileAppender;
45 import org.apache.logging.log4j.core.config.plugins.Plugin;
46 import org.apache.logging.log4j.status.StatusLogger;
47 import org.w3c.dom.Element;
48
49
50
51
52 @Plugin(name = "org.apache.log4j.FileAppender", category = CATEGORY)
53 public class FileAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
54
55 private static final Logger LOGGER = StatusLogger.getLogger();
56
57 public FileAppenderBuilder() {
58 }
59
60 public FileAppenderBuilder(String prefix, Properties props) {
61 super(prefix, props);
62 }
63
64 @Override
65 public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
66 String name = appenderElement.getAttribute(NAME_ATTR);
67 AtomicReference<Layout> layout = new AtomicReference<>();
68 AtomicReference<Filter> filter = new AtomicReference<>();
69 AtomicReference<String> fileName = new AtomicReference<>();
70 AtomicReference<String> level = new AtomicReference<>();
71 AtomicBoolean immediateFlush = new AtomicBoolean();
72 AtomicBoolean append = new AtomicBoolean();
73 AtomicBoolean bufferedIo = new AtomicBoolean();
74 AtomicInteger bufferSize = new AtomicInteger(8192);
75 forEachElement(appenderElement.getChildNodes(), currentElement -> {
76 switch (currentElement.getTagName()) {
77 case LAYOUT_TAG:
78 layout.set(config.parseLayout(currentElement));
79 break;
80 case FILTER_TAG:
81 filter.set(config.parseFilters(currentElement));
82 break;
83 case PARAM_TAG: {
84 switch (currentElement.getAttribute(NAME_ATTR)) {
85 case FILE_PARAM:
86 fileName.set(currentElement.getAttribute(VALUE_ATTR));
87 break;
88 case APPEND_PARAM: {
89 String bool = currentElement.getAttribute(VALUE_ATTR);
90 if (bool != null) {
91 append.set(Boolean.parseBoolean(bool));
92 } else {
93 LOGGER.warn("No value provided for append parameter");
94 }
95 break;
96 }
97 case BUFFERED_IO_PARAM: {
98 String bool = currentElement.getAttribute(VALUE_ATTR);
99 if (bool != null) {
100 bufferedIo.set(Boolean.parseBoolean(bool));
101 } else {
102 LOGGER.warn("No value provided for bufferedIo parameter");
103 }
104 break;
105 }
106 case BUFFER_SIZE_PARAM: {
107 String size = currentElement.getAttribute(VALUE_ATTR);
108 if (size != null) {
109 bufferSize.set(Integer.parseInt(size));
110 } else {
111 LOGGER.warn("No value provide for bufferSize parameter");
112 }
113 break;
114 }
115 case THRESHOLD_PARAM: {
116 String value = currentElement.getAttribute(VALUE_ATTR);
117 if (value == null) {
118 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
119 } else {
120 level.set(value);
121 }
122 break;
123 }
124 }
125 break;
126 }
127 }
128 });
129
130 return createAppender(name, config, layout.get(), filter.get(), fileName.get(), level.get(),
131 immediateFlush.get(), append.get(), bufferedIo.get(), bufferSize.get());
132 }
133
134
135 @Override
136 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
137 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
138 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
139 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
140 String level = getProperty(THRESHOLD_PARAM);
141 String fileName = getProperty(FILE_PARAM);
142 boolean append = getBooleanProperty(APPEND_PARAM);
143 boolean immediateFlush = false;
144 boolean bufferedIo = getBooleanProperty(BUFFERED_IO_PARAM);
145 int bufferSize = Integer.parseInt(getProperty(BUFFER_SIZE_PARAM, "8192"));
146 return createAppender(name, configuration, layout, filter, fileName, level, immediateFlush,
147 append, bufferedIo, bufferSize);
148 }
149
150 private Appender createAppender(final String name, final Log4j1Configuration configuration, final Layout layout,
151 final Filter filter, final String fileName, String level, boolean immediateFlush, final boolean append,
152 final boolean bufferedIo, final int bufferSize) {
153 org.apache.logging.log4j.core.Layout<?> fileLayout = null;
154 if (bufferedIo) {
155 immediateFlush = true;
156 }
157 if (layout instanceof LayoutWrapper) {
158 fileLayout = ((LayoutWrapper) layout).getLayout();
159 } else if (layout != null) {
160 fileLayout = new LayoutAdapter(layout);
161 }
162 org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
163 if (fileName == null) {
164 LOGGER.warn("Unable to create File Appender, no file name provided");
165 return null;
166 }
167 return new AppenderWrapper(FileAppender.newBuilder()
168 .setName(name)
169 .setConfiguration(configuration)
170 .setLayout(fileLayout)
171 .setFilter(fileFilter)
172 .withFileName(fileName)
173 .withImmediateFlush(immediateFlush)
174 .withAppend(append)
175 .withBufferedIo(bufferedIo)
176 .withBufferSize(bufferSize)
177 .build());
178 }
179 }