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.io.Serializable;
29 import java.util.Properties;
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.SocketAppender;
45 import org.apache.logging.log4j.core.config.plugins.Plugin;
46 import org.apache.logging.log4j.core.layout.SyslogLayout;
47 import org.apache.logging.log4j.core.net.Facility;
48 import org.apache.logging.log4j.core.net.Protocol;
49 import org.apache.logging.log4j.status.StatusLogger;
50 import org.w3c.dom.Element;
51
52
53
54
55 @Plugin(name = "org.apache.log4j.net.SyslogAppender", category = CATEGORY)
56 public class SyslogAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
57
58 private static final String DEFAULT_HOST = "localhost";
59 private static int DEFAULT_PORT = 514;
60 private static final String DEFAULT_FACILITY = "LOCAL0";
61
62 private static final Logger LOGGER = StatusLogger.getLogger();
63 private static final String FACILITY_PARAM = "Facility";
64 private static final String SYSLOG_HOST_PARAM = "SyslogHost";
65 private static final String PROTOCOL_PARAM = "protocol";
66
67
68 public SyslogAppenderBuilder() {
69 }
70
71 public SyslogAppenderBuilder(String prefix, Properties props) {
72 super(prefix, props);
73 }
74
75 @Override
76 public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
77 String name = appenderElement.getAttribute(NAME_ATTR);
78 AtomicReference<Layout> layout = new AtomicReference<>();
79 AtomicReference<Filter> filter = new AtomicReference<>();
80 AtomicReference<String> facility = new AtomicReference<>();
81 AtomicReference<String> level = new AtomicReference<>();
82 AtomicReference<String> host = new AtomicReference<>();
83 AtomicReference<Protocol> protocol = new AtomicReference<>();
84 forEachElement(appenderElement.getChildNodes(), currentElement -> {
85 switch (currentElement.getTagName()) {
86 case LAYOUT_TAG:
87 layout.set(config.parseLayout(currentElement));
88 break;
89 case FILTER_TAG:
90 filter.set(config.parseFilters(currentElement));
91 break;
92 case PARAM_TAG: {
93 switch (currentElement.getAttribute(NAME_ATTR)) {
94 case SYSLOG_HOST_PARAM: {
95 host.set(currentElement.getAttribute(VALUE_ATTR));
96 break;
97 }
98 case FACILITY_PARAM:
99 facility.set(currentElement.getAttribute(VALUE_ATTR));
100 break;
101 case THRESHOLD_PARAM: {
102 String value = currentElement.getAttribute(VALUE_ATTR);
103 if (value == null) {
104 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
105 } else {
106 level.set(value);
107 }
108 break;
109 }
110 case PROTOCOL_PARAM:
111 protocol.set(Protocol.valueOf(currentElement.getAttribute(VALUE_ATTR)));
112 break;
113 }
114 break;
115 }
116 }
117 });
118
119 return createAppender(name, config, layout.get(), facility.get(), filter.get(), host.get(), level.get(), protocol.get());
120 }
121
122
123 @Override
124 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
125 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
126 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
127 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
128 String level = getProperty(THRESHOLD_PARAM);
129 String facility = getProperty(FACILITY_PARAM, DEFAULT_FACILITY);
130 String syslogHost = getProperty(SYSLOG_HOST_PARAM, DEFAULT_HOST + ":" + DEFAULT_PORT);
131 String protocol = getProperty(PROTOCOL_PARAM, Protocol.TCP.name());
132
133 return createAppender(name, configuration, layout, facility, filter, syslogHost, level, Protocol.valueOf(protocol));
134 }
135
136 private Appender createAppender(final String name, final Log4j1Configuration configuration, Layout layout,
137 String facility, final Filter filter, final String syslogHost, final String level, final Protocol protocol) {
138 AtomicReference<String> host = new AtomicReference<>();
139 AtomicInteger port = new AtomicInteger();
140 resolveSyslogHost(syslogHost, host, port);
141 org.apache.logging.log4j.core.Layout<? extends Serializable> appenderLayout;
142 if (layout instanceof LayoutWrapper) {
143 appenderLayout = ((LayoutWrapper) layout).getLayout();
144 } else if (layout != null) {
145 appenderLayout = new LayoutAdapter(layout);
146 } else {
147 appenderLayout = SyslogLayout.newBuilder()
148 .setFacility(Facility.toFacility(facility))
149 .setConfiguration(configuration)
150 .build();
151 }
152
153 org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
154 return new AppenderWrapper(SocketAppender.newBuilder()
155 .setName(name)
156 .setConfiguration(configuration)
157 .setLayout(appenderLayout)
158 .setFilter(fileFilter)
159 .withPort(port.get())
160 .withProtocol(protocol)
161 .withHost(host.get())
162 .build());
163 }
164
165 private void resolveSyslogHost(String syslogHost, AtomicReference<String> host, AtomicInteger port) {
166
167
168
169
170 String[] parts = syslogHost.split(":");
171 if (parts.length == 1) {
172 host.set(parts[0]);
173 port.set(DEFAULT_PORT);
174 } else if (parts.length == 2) {
175 host.set(parts[0]);
176 port.set(Integer.parseInt(parts[1]));
177 } else {
178 LOGGER.warn("Invalid {} setting: {}. Using default.", SYSLOG_HOST_PARAM, syslogHost);
179 host.set(DEFAULT_HOST);
180 port.set(DEFAULT_PORT);
181 }
182 }
183 }