View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
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.FileAppender;
35  import org.apache.logging.log4j.core.config.plugins.Plugin;
36  import org.apache.logging.log4j.status.StatusLogger;
37  import org.w3c.dom.Element;
38  
39  import java.util.Properties;
40  
41  import static org.apache.log4j.builders.BuilderManager.CATEGORY;
42  import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
43  import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
44  import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
45  import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
46  import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
47  import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
48  import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
49  
50  /**
51   * Build a File Appender
52   */
53  @Plugin(name = "org.apache.log4j.FileAppender", category = CATEGORY)
54  public class FileAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
55  
56      private static final Logger LOGGER = StatusLogger.getLogger();
57  
58      public FileAppenderBuilder() {
59      }
60  
61      public FileAppenderBuilder(String prefix, Properties props) {
62          super(prefix, props);
63      }
64  
65      @Override
66      public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
67          String name = appenderElement.getAttribute(NAME_ATTR);
68          Holder<Layout> layout = new Holder<>();
69          Holder<Filter> filter = new Holder<>();
70          Holder<String> fileName = new Holder<>();
71          Holder<String> level = new Holder<>();
72          Holder<Boolean> immediateFlush = new BooleanHolder();
73          Holder<Boolean> append = new BooleanHolder();
74          Holder<Boolean> bufferedIo = new BooleanHolder();
75          Holder<Integer> bufferSize = new Holder<>(8192);
76          forEachElement(appenderElement.getChildNodes(), (currentElement) -> {
77              switch (currentElement.getTagName()) {
78                  case LAYOUT_TAG:
79                      layout.set(config.parseLayout(currentElement));
80                      break;
81                  case FILTER_TAG:
82                      filter.set(config.parseFilters(currentElement));
83                      break;
84                  case PARAM_TAG: {
85                      switch (currentElement.getAttribute(NAME_ATTR)) {
86                          case FILE_PARAM:
87                              fileName.set(currentElement.getAttribute(VALUE_ATTR));
88                              break;
89                          case APPEND_PARAM: {
90                              String bool = currentElement.getAttribute(VALUE_ATTR);
91                              if (bool != null) {
92                                  append.set(Boolean.parseBoolean(bool));
93                              } else {
94                                  LOGGER.warn("No value provided for append parameter");
95                              }
96                              break;
97                          }
98                          case BUFFERED_IO_PARAM: {
99                              String bool = currentElement.getAttribute(VALUE_ATTR);
100                             if (bool != null) {
101                                 bufferedIo.set(Boolean.parseBoolean(bool));
102                             } else {
103                                 LOGGER.warn("No value provided for bufferedIo parameter");
104                             }
105                             break;
106                         }
107                         case BUFFER_SIZE_PARAM: {
108                             String size = currentElement.getAttribute(VALUE_ATTR);
109                             if (size != null) {
110                                 bufferSize.set(Integer.parseInt(size));
111                             } else {
112                                 LOGGER.warn("No value provide for bufferSize parameter");
113                             }
114                             break;
115                         }
116                         case THRESHOLD_PARAM: {
117                             String value = currentElement.getAttribute(VALUE_ATTR);
118                             if (value == null) {
119                                 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
120                             } else {
121                                 level.set(value);
122                             }
123                             break;
124                         }
125                     }
126                     break;
127                 }
128             }
129         });
130 
131         return createAppender(name, config, layout.get(), filter.get(), fileName.get(), level.get(),
132                 immediateFlush.get(), append.get(), bufferedIo.get(), bufferSize.get());
133     }
134 
135 
136     @Override
137     public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
138             final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
139         Layout layout = configuration.parseLayout(layoutPrefix, name, props);
140         Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
141         String level = getProperty(THRESHOLD_PARAM);
142         String fileName = getProperty(FILE_PARAM);
143         boolean append = getBooleanProperty(APPEND_PARAM);
144         boolean immediateFlush = false;
145         boolean bufferedIo = getBooleanProperty(BUFFERED_IO_PARAM);
146         int bufferSize = Integer.parseInt(getProperty(BUFFER_SIZE_PARAM, "8192"));
147         return createAppender(name, configuration, layout, filter, fileName, level, immediateFlush,
148                 append, bufferedIo, bufferSize);
149     }
150 
151     private Appender createAppender(final String name, final Log4j1Configuration configuration, final Layout layout,
152             final Filter filter, final String fileName, String level, boolean immediateFlush, final boolean append,
153             final boolean bufferedIo, final int bufferSize) {
154         org.apache.logging.log4j.core.Layout<?> fileLayout = null;
155         if (bufferedIo) {
156             immediateFlush = true;
157         }
158         if (layout instanceof LayoutWrapper) {
159             fileLayout = ((LayoutWrapper) layout).getLayout();
160         } else if (layout != null) {
161             fileLayout = new LayoutAdapter(layout);
162         }
163         org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
164         if (fileName == null) {
165             LOGGER.warn("Unable to create File Appender, no file name provided");
166             return null;
167         }
168         return new AppenderWrapper(FileAppender.newBuilder()
169                 .setName(name)
170                 .setConfiguration(configuration)
171                 .setLayout(fileLayout)
172                 .setFilter(fileFilter)
173                 .withFileName(fileName)
174                 .withImmediateFlush(immediateFlush)
175                 .withAppend(append)
176                 .withBufferedIo(bufferedIo)
177                 .withBufferSize(bufferSize)
178                 .build());
179     }
180 }