1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.logging.log4j.core.appender.mom;
19
20 import java.io.Serializable;
21 import java.util.Properties;
22 import java.util.concurrent.TimeUnit;
23
24 import javax.jms.JMSException;
25
26 import org.apache.logging.log4j.core.Appender;
27 import org.apache.logging.log4j.core.Filter;
28 import org.apache.logging.log4j.core.Layout;
29 import org.apache.logging.log4j.core.LogEvent;
30 import org.apache.logging.log4j.core.appender.AbstractAppender;
31 import org.apache.logging.log4j.core.appender.AbstractManager;
32 import org.apache.logging.log4j.core.appender.mom.JmsManager.JmsManagerConfiguration;
33 import org.apache.logging.log4j.core.config.Node;
34 import org.apache.logging.log4j.core.config.plugins.Plugin;
35 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
36 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
37 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
38 import org.apache.logging.log4j.core.config.plugins.PluginElement;
39 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
40 import org.apache.logging.log4j.core.net.JndiManager;
41
42
43
44
45
46 @Plugin(name = "JMS", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
47 @PluginAliases({ "JMSQueue", "JMSTopic" })
48 public class JmsAppender extends AbstractAppender {
49
50 public static class Builder implements org.apache.logging.log4j.core.util.Builder<JmsAppender> {
51
52 public static final int DEFAULT_RECONNECT_INTERVAL_MILLIS = 5000;
53
54 @PluginBuilderAttribute
55 @Required(message = "A name for the JmsAppender must be specified")
56 private String name;
57
58 @PluginBuilderAttribute
59 private String factoryName;
60
61 @PluginBuilderAttribute
62 private String providerUrl;
63
64 @PluginBuilderAttribute
65 private String urlPkgPrefixes;
66
67 @PluginBuilderAttribute
68 private String securityPrincipalName;
69
70 @PluginBuilderAttribute(sensitive = true)
71 private String securityCredentials;
72
73 @PluginBuilderAttribute
74 @Required(message = "A javax.jms.ConnectionFactory JNDI name must be specified")
75 private String factoryBindingName;
76
77 @PluginBuilderAttribute
78 @PluginAliases({ "queueBindingName", "topicBindingName" })
79 @Required(message = "A javax.jms.Destination JNDI name must be specified")
80 private String destinationBindingName;
81
82 @PluginBuilderAttribute
83 private String userName;
84
85 @PluginBuilderAttribute(sensitive = true)
86 private char[] password;
87
88 @PluginElement("Layout")
89 private Layout<? extends Serializable> layout;
90
91 @PluginElement("Filter")
92 private Filter filter;
93
94 private long reconnectIntervalMillis = DEFAULT_RECONNECT_INTERVAL_MILLIS;
95
96 @PluginBuilderAttribute
97 private boolean ignoreExceptions = true;
98
99 @PluginBuilderAttribute
100 private boolean immediateFail;
101
102
103 private JmsManager jmsManager;
104
105 private Builder() {
106 }
107
108 @SuppressWarnings("resource")
109 @Override
110 public JmsAppender build() {
111 JmsManager actualJmsManager = jmsManager;
112 JmsManagerConfiguration configuration = null;
113 if (actualJmsManager == null) {
114 final Properties jndiProperties = JndiManager.createProperties(factoryName, providerUrl, urlPkgPrefixes,
115 securityPrincipalName, securityCredentials, null);
116 configuration = new JmsManagerConfiguration(jndiProperties, factoryBindingName, destinationBindingName,
117 userName, password, false, reconnectIntervalMillis);
118 actualJmsManager = AbstractManager.getManager(name, JmsManager.FACTORY, configuration);
119 }
120 if (actualJmsManager == null) {
121
122 return null;
123 }
124 if (layout == null) {
125 LOGGER.error("No layout provided for JmsAppender");
126 return null;
127 }
128 try {
129 return new JmsAppender(name, filter, layout, ignoreExceptions, actualJmsManager);
130 } catch (final JMSException e) {
131
132 throw new IllegalStateException(e);
133 }
134 }
135
136 public Builder setDestinationBindingName(final String destinationBindingName) {
137 this.destinationBindingName = destinationBindingName;
138 return this;
139 }
140
141 public Builder setFactoryBindingName(final String factoryBindingName) {
142 this.factoryBindingName = factoryBindingName;
143 return this;
144 }
145
146 public Builder setFactoryName(final String factoryName) {
147 this.factoryName = factoryName;
148 return this;
149 }
150
151 public Builder setFilter(final Filter filter) {
152 this.filter = filter;
153 return this;
154 }
155
156 public Builder setIgnoreExceptions(final boolean ignoreExceptions) {
157 this.ignoreExceptions = ignoreExceptions;
158 return this;
159 }
160
161 public Builder setImmediateFail(final boolean immediateFail) {
162 this.immediateFail = immediateFail;
163 return this;
164 }
165
166 public Builder setJmsManager(final JmsManager jmsManager) {
167 this.jmsManager = jmsManager;
168 return this;
169 }
170
171 public Builder setLayout(final Layout<? extends Serializable> layout) {
172 this.layout = layout;
173 return this;
174 }
175
176 public Builder setName(final String name) {
177 this.name = name;
178 return this;
179 }
180
181 public Builder setPassword(final char[] password) {
182 this.password = password;
183 return this;
184 }
185
186
187
188
189 @Deprecated
190 public Builder setPassword(final String password) {
191 this.password = password == null ? null : password.toCharArray();
192 return this;
193 }
194
195 public Builder setProviderUrl(final String providerUrl) {
196 this.providerUrl = providerUrl;
197 return this;
198 }
199
200 public Builder setReconnectIntervalMillis(final long reconnectIntervalMillis) {
201 this.reconnectIntervalMillis = reconnectIntervalMillis;
202 return this;
203 }
204
205 public Builder setSecurityCredentials(final String securityCredentials) {
206 this.securityCredentials = securityCredentials;
207 return this;
208 }
209
210 public Builder setSecurityPrincipalName(final String securityPrincipalName) {
211 this.securityPrincipalName = securityPrincipalName;
212 return this;
213 }
214
215 public Builder setUrlPkgPrefixes(final String urlPkgPrefixes) {
216 this.urlPkgPrefixes = urlPkgPrefixes;
217 return this;
218 }
219
220
221
222
223 @Deprecated
224 public Builder setUsername(final String username) {
225 this.userName = username;
226 return this;
227 }
228
229 public Builder setUserName(final String userName) {
230 this.userName = userName;
231 return this;
232 }
233
234
235
236
237 @Override
238 public String toString() {
239 return "Builder [name=" + name + ", factoryName=" + factoryName + ", providerUrl=" + providerUrl
240 + ", urlPkgPrefixes=" + urlPkgPrefixes + ", securityPrincipalName=" + securityPrincipalName
241 + ", securityCredentials=" + securityCredentials + ", factoryBindingName=" + factoryBindingName
242 + ", destinationBindingName=" + destinationBindingName + ", username=" + userName + ", layout="
243 + layout + ", filter=" + filter + ", ignoreExceptions=" + ignoreExceptions + ", jmsManager="
244 + jmsManager + "]";
245 }
246
247 }
248
249 @PluginBuilderFactory
250 public static Builder newBuilder() {
251 return new Builder();
252 }
253
254 private volatile JmsManager manager;
255
256
257
258
259
260
261 protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
262 final boolean ignoreExceptions, final JmsManager manager) throws JMSException {
263 super(name, filter, layout, ignoreExceptions);
264 this.manager = manager;
265 }
266
267 @Override
268 public void append(final LogEvent event) {
269 this.manager.send(event, getLayout().toSerializable(event));
270 }
271
272 public JmsManager getManager() {
273 return manager;
274 }
275
276 @Override
277 public boolean stop(final long timeout, final TimeUnit timeUnit) {
278 setStopping();
279 boolean stopped = super.stop(timeout, timeUnit, false);
280 stopped &= this.manager.stop(timeout, timeUnit);
281 setStopped();
282 return stopped;
283 }
284
285 }