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 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   * Build a File Appender
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 }