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.LayoutAdapter;
23  import org.apache.log4j.bridge.LayoutWrapper;
24  import org.apache.log4j.builders.AbstractBuilder;
25  import org.apache.log4j.builders.Holder;
26  import org.apache.log4j.config.Log4j1Configuration;
27  import org.apache.log4j.config.PropertiesConfiguration;
28  import org.apache.log4j.spi.Filter;
29  import org.apache.log4j.xml.XmlConfiguration;
30  import org.apache.logging.log4j.Logger;
31  import org.apache.logging.log4j.core.appender.SyslogAppender;
32  import org.apache.logging.log4j.core.config.plugins.Plugin;
33  import org.apache.logging.log4j.core.layout.SyslogLayout;
34  import org.apache.logging.log4j.core.net.Facility;
35  import org.apache.logging.log4j.core.net.Protocol;
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.NAME_ATTR;
46  import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
47  import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
48  import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
49  
50  /**
51   * Build a File Appender
52   */
53  @Plugin(name = "org.apache.log4j.net.SyslogAppender", category = CATEGORY)
54  public class SyslogAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
55  
56      private static final Logger LOGGER = StatusLogger.getLogger();
57      private static final String FACILITY_PARAM = "Facility";
58      private static final String SYSLOG_HOST_PARAM = "SyslogHost";
59      private static int SYSLOG_PORT = 512;
60  
61      public SyslogAppenderBuilder() {
62      }
63  
64      public SyslogAppenderBuilder(String prefix, Properties props) {
65          super(prefix, props);
66      }
67  
68      @Override
69      public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
70          String name = appenderElement.getAttribute(NAME_ATTR);
71          Holder<Layout> layout = new Holder<>();
72          Holder<Filter> filter = new Holder<>();
73          Holder<String> facility = new Holder<>();
74          Holder<String> level = new Holder<>();
75          Holder<String> host = new Holder<>();
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 SYSLOG_HOST_PARAM: {
87                              host.set(currentElement.getAttribute(VALUE_ATTR));
88                              break;
89                          }
90                          case FACILITY_PARAM:
91                              facility.set(currentElement.getAttribute(VALUE_ATTR));
92                              break;
93                          case THRESHOLD_PARAM: {
94                              String value = currentElement.getAttribute(VALUE_ATTR);
95                              if (value == null) {
96                                  LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
97                              } else {
98                                  level.set(value);
99                              }
100                             break;
101                         }
102                     }
103                     break;
104                 }
105             }
106         });
107 
108         return createAppender(name, config, layout.get(), facility.get(), filter.get(), host.get(), level.get());
109     }
110 
111 
112     @Override
113     public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
114             final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
115         Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
116         Layout layout = configuration.parseLayout(layoutPrefix, name, props);
117         String level = getProperty(THRESHOLD_PARAM);
118         String facility = getProperty(FACILITY_PARAM, "LOCAL0");
119         String syslogHost = getProperty(SYSLOG_HOST_PARAM, "localhost:514");
120 
121         return createAppender(name, configuration, layout, facility, filter, syslogHost, level);
122     }
123 
124     private Appender createAppender(final String name, final Log4j1Configuration configuration, Layout layout,
125             String facility, final Filter filter, final String syslogHost, final String level) {
126         Holder<String> host = new Holder<>();
127         Holder<Integer> port = new Holder<>();
128         resolveSyslogHost(syslogHost, host, port);
129         org.apache.logging.log4j.core.Layout appenderLayout;
130         if (layout instanceof LayoutWrapper) {
131             appenderLayout = ((LayoutWrapper) layout).getLayout();
132         } else if (layout != null) {
133             appenderLayout = new LayoutAdapter(layout);
134         } else {
135             appenderLayout = SyslogLayout.newBuilder()
136                     .setFacility(Facility.toFacility(facility))
137                     .setConfiguration(configuration)
138                     .build();
139         }
140 
141         org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
142         return new AppenderWrapper(SyslogAppender.newBuilder()
143                 .setName(name)
144                 .setConfiguration(configuration)
145                 .setLayout(appenderLayout)
146                 .setFilter(fileFilter)
147                 .withPort(port.get())
148                 .withProtocol(Protocol.TCP)
149                 .withHost(host.get())
150                 .build());
151     }
152 
153     private void resolveSyslogHost(String syslogHost, Holder<String> host, Holder<Integer> port) {
154         int urlPort = -1;
155 
156         //
157         //  If not an unbracketed IPv6 address then
158         //      parse as a URL
159         //
160         String[] parts = syslogHost.split(":");
161         if (parts.length == 1) {
162             host.set(parts[0]);
163             port.set(SYSLOG_PORT);
164         } else if (parts.length == 2) {
165             host.set(parts[0]);
166             port.set(Integer.parseInt(parts[1]));
167         } else {
168             LOGGER.warn("Invalid syslogHost setting: {}. Using default", syslogHost);
169             host.set("localhost");
170             port.set(SYSLOG_PORT);
171         }
172     }
173 }