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 org.apache.log4j.Appender;
20 import org.apache.log4j.Layout;
21 import org.apache.log4j.bridge.AppenderWrapper;
22 import org.apache.log4j.bridge.FilterAdapter;
23 import org.apache.log4j.bridge.FilterWrapper;
24 import org.apache.log4j.bridge.LayoutAdapter;
25 import org.apache.log4j.bridge.LayoutWrapper;
26 import org.apache.log4j.builders.AbstractBuilder;
27 import org.apache.log4j.builders.BooleanHolder;
28 import org.apache.log4j.builders.Holder;
29 import org.apache.log4j.config.Log4j1Configuration;
30 import org.apache.log4j.config.PropertiesConfiguration;
31 import org.apache.log4j.spi.Filter;
32 import org.apache.log4j.xml.XmlConfiguration;
33 import org.apache.logging.log4j.Logger;
34 import org.apache.logging.log4j.core.appender.RollingFileAppender;
35 import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
36 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
37 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
38 import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
39 import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
40 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
41 import org.apache.logging.log4j.core.config.plugins.Plugin;
42 import org.apache.logging.log4j.status.StatusLogger;
43 import org.w3c.dom.Element;
44
45 import java.util.Properties;
46
47 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
48 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
49 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
50 import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
51 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
52 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
53 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
54 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
55
56
57
58
59
60 @Plugin(name = "org.apache.log4j.RollingFileAppender", category = CATEGORY)
61 public class RollingFileAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
62
63 private static final Logger LOGGER = StatusLogger.getLogger();
64
65 public RollingFileAppenderBuilder() {
66 }
67
68 public RollingFileAppenderBuilder(String prefix, Properties props) {
69 super(prefix, props);
70 }
71
72 @Override
73 public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
74 String name = appenderElement.getAttribute(NAME_ATTR);
75 Holder<Layout> layout = new Holder<>();
76 Holder<Filter> filter = new Holder<>();
77 Holder<String> fileName = new Holder<>();
78 Holder<Boolean> immediateFlush = new BooleanHolder();
79 Holder<Boolean> append = new BooleanHolder();
80 Holder<Boolean> bufferedIo = new BooleanHolder();
81 Holder<Integer> bufferSize = new Holder<>(8192);
82 Holder<String> maxSize = new Holder<>();
83 Holder<String> maxBackups = new Holder<>();
84 Holder<String> level = new Holder<>();
85 forEachElement(appenderElement.getChildNodes(), (currentElement) -> {
86 switch (currentElement.getTagName()) {
87 case LAYOUT_TAG:
88 layout.set(config.parseLayout(currentElement));
89 break;
90 case FILTER_TAG:
91 filter.set(config.parseFilters(currentElement));
92 break;
93 case PARAM_TAG: {
94 switch (currentElement.getAttribute(NAME_ATTR)) {
95 case FILE_PARAM:
96 fileName.set(currentElement.getAttribute(VALUE_ATTR));
97 break;
98 case APPEND_PARAM: {
99 String bool = currentElement.getAttribute(VALUE_ATTR);
100 if (bool != null) {
101 append.set(Boolean.parseBoolean(bool));
102 } else {
103 LOGGER.warn("No value provided for append parameter");
104 }
105 break;
106 }
107 case BUFFERED_IO_PARAM: {
108 String bool = currentElement.getAttribute(VALUE_ATTR);
109 if (bool != null) {
110 bufferedIo.set(Boolean.parseBoolean(bool));
111 } else {
112 LOGGER.warn("No value provided for bufferedIo parameter");
113 }
114 break;
115 }
116 case BUFFER_SIZE_PARAM: {
117 String size = currentElement.getAttribute(VALUE_ATTR);
118 if (size != null) {
119 bufferSize.set(Integer.parseInt(size));
120 } else {
121 LOGGER.warn("No value provide for bufferSize parameter");
122 }
123 break;
124 }
125 case MAX_BACKUP_INDEX: {
126 String size = currentElement.getAttribute(VALUE_ATTR);
127 if (size != null) {
128 maxBackups.set(size);
129 } else {
130 LOGGER.warn("No value provide for maxBackupIndex parameter");
131 }
132 break;
133 }
134 case MAX_SIZE_PARAM: {
135 String size = currentElement.getAttribute(VALUE_ATTR);
136 if (size != null) {
137 maxSize.set(size);
138 } else {
139 LOGGER.warn("No value provide for bufferSize parameter");
140 }
141 break;
142 }
143 case THRESHOLD_PARAM: {
144 String value = currentElement.getAttribute(VALUE_ATTR);
145 if (value == null) {
146 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
147 } else {
148 level.set(value);
149 }
150 break;
151 }
152 }
153 break;
154 }
155 }
156 });
157 return createAppender(name, config, layout.get(), filter.get(), bufferedIo.get(), immediateFlush.get(),
158 fileName.get(), level.get(), maxSize.get(), maxBackups.get());
159 }
160
161
162 @Override
163 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
164 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
165 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
166 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
167 String fileName = getProperty(FILE_PARAM);
168 String level = getProperty(THRESHOLD_PARAM);
169 boolean immediateFlush = false;
170 boolean bufferedIo = getBooleanProperty(BUFFERED_IO_PARAM);
171 String maxSize = getProperty(MAX_SIZE_PARAM);
172 String maxBackups = getProperty(MAX_BACKUP_INDEX);
173 return createAppender(name, configuration, layout, filter, bufferedIo, immediateFlush, fileName, level, maxSize,
174 maxBackups);
175 }
176
177 private Appender createAppender(final String name, final Log4j1Configuration config, final Layout layout,
178 final Filter filter, final boolean bufferedIo, boolean immediateFlush, final String fileName,
179 final String level, final String maxSize, final String maxBackups) {
180 org.apache.logging.log4j.core.Layout<?> fileLayout = null;
181 if (bufferedIo) {
182 immediateFlush = true;
183 }
184 if (layout instanceof LayoutWrapper) {
185 fileLayout = ((LayoutWrapper) layout).getLayout();
186 } else if (layout != null) {
187 fileLayout = new LayoutAdapter(layout);
188 }
189 org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
190 if (fileName == null) {
191 LOGGER.warn("Unable to create File Appender, no file name provided");
192 return null;
193 }
194 String filePattern = fileName +"%d{yyy-MM-dd}";
195 TriggeringPolicy timePolicy = TimeBasedTriggeringPolicy.newBuilder().withModulate(true).build();
196 SizeBasedTriggeringPolicy sizePolicy = SizeBasedTriggeringPolicy.createPolicy(maxSize);
197 CompositeTriggeringPolicy policy = CompositeTriggeringPolicy.createPolicy(sizePolicy, timePolicy);
198 RolloverStrategy strategy = DefaultRolloverStrategy.newBuilder()
199 .withConfig(config)
200 .withMax(maxBackups)
201 .build();
202 return new AppenderWrapper(RollingFileAppender.newBuilder()
203 .setName(name)
204 .setConfiguration(config)
205 .setLayout(fileLayout)
206 .setFilter(fileFilter)
207 .withBufferedIo(bufferedIo)
208 .withImmediateFlush(immediateFlush)
209 .withFileName(fileName)
210 .withFilePattern(filePattern)
211 .withPolicy(policy)
212 .withStrategy(strategy)
213 .build());
214 }
215 }