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.Property;
35 import org.apache.logging.log4j.core.config.plugins.Plugin;
36 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
37 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
38 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
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<B extends Builder<B>> extends AbstractAppender.Builder<B>
51 implements org.apache.logging.log4j.core.util.Builder<JmsAppender> {
52
53 public static final int DEFAULT_RECONNECT_INTERVAL_MILLIS = 5000;
54
55 @PluginBuilderAttribute
56 private String factoryName;
57
58 @PluginBuilderAttribute
59 private String providerUrl;
60
61 @PluginBuilderAttribute
62 private String urlPkgPrefixes;
63
64 @PluginBuilderAttribute
65 private String securityPrincipalName;
66
67 @PluginBuilderAttribute(sensitive = true)
68 private String securityCredentials;
69
70 @PluginBuilderAttribute
71 @Required(message = "A javax.jms.ConnectionFactory JNDI name must be specified")
72 private String factoryBindingName;
73
74 @PluginBuilderAttribute
75 @PluginAliases({ "queueBindingName", "topicBindingName" })
76 @Required(message = "A javax.jms.Destination JNDI name must be specified")
77 private String destinationBindingName;
78
79 @PluginBuilderAttribute
80 private String userName;
81
82 @PluginBuilderAttribute(sensitive = true)
83 private char[] password;
84
85 @PluginBuilderAttribute
86 private long reconnectIntervalMillis = DEFAULT_RECONNECT_INTERVAL_MILLIS;
87
88 @PluginBuilderAttribute
89 private boolean immediateFail;
90
91
92 private JmsManager jmsManager;
93
94 private Builder() {
95 }
96
97 @SuppressWarnings("resource")
98 @Override
99 public JmsAppender build() {
100 JmsManager actualJmsManager = jmsManager;
101 JmsManagerConfiguration configuration = null;
102 if (actualJmsManager == null) {
103 final Properties jndiProperties = JndiManager.createProperties(factoryName, providerUrl, urlPkgPrefixes,
104 securityPrincipalName, securityCredentials, null);
105 configuration = new JmsManagerConfiguration(jndiProperties, factoryBindingName, destinationBindingName,
106 userName, password, false, reconnectIntervalMillis);
107 actualJmsManager = AbstractManager.getManager(getName(), JmsManager.FACTORY, configuration);
108 }
109 if (actualJmsManager == null) {
110
111 return null;
112 }
113 final Layout<? extends Serializable> layout = getLayout();
114 if (layout == null) {
115 LOGGER.error("No layout provided for JmsAppender");
116 return null;
117 }
118 try {
119 return new JmsAppender(getName(), getFilter(), layout, isIgnoreExceptions(), getPropertyArray(),
120 actualJmsManager);
121 } catch (final JMSException e) {
122
123 throw new IllegalStateException(e);
124 }
125 }
126
127 public Builder setDestinationBindingName(final String destinationBindingName) {
128 this.destinationBindingName = destinationBindingName;
129 return this;
130 }
131
132 public Builder setFactoryBindingName(final String factoryBindingName) {
133 this.factoryBindingName = factoryBindingName;
134 return this;
135 }
136
137 public Builder setFactoryName(final String factoryName) {
138 this.factoryName = factoryName;
139 return this;
140 }
141
142 public Builder setImmediateFail(final boolean immediateFail) {
143 this.immediateFail = immediateFail;
144 return this;
145 }
146
147 public Builder setJmsManager(final JmsManager jmsManager) {
148 this.jmsManager = jmsManager;
149 return this;
150 }
151
152 public Builder setPassword(final char[] password) {
153 this.password = password;
154 return this;
155 }
156
157
158
159
160 @Deprecated
161 public Builder setPassword(final String password) {
162 this.password = password == null ? null : password.toCharArray();
163 return this;
164 }
165
166 public Builder setProviderUrl(final String providerUrl) {
167 this.providerUrl = providerUrl;
168 return this;
169 }
170
171 public Builder setReconnectIntervalMillis(final long reconnectIntervalMillis) {
172 this.reconnectIntervalMillis = reconnectIntervalMillis;
173 return this;
174 }
175
176 public Builder setSecurityCredentials(final String securityCredentials) {
177 this.securityCredentials = securityCredentials;
178 return this;
179 }
180
181 public Builder setSecurityPrincipalName(final String securityPrincipalName) {
182 this.securityPrincipalName = securityPrincipalName;
183 return this;
184 }
185
186 public Builder setUrlPkgPrefixes(final String urlPkgPrefixes) {
187 this.urlPkgPrefixes = urlPkgPrefixes;
188 return this;
189 }
190
191
192
193
194 @Deprecated
195 public Builder setUsername(final String username) {
196 this.userName = username;
197 return this;
198 }
199
200 public Builder setUserName(final String userName) {
201 this.userName = userName;
202 return this;
203 }
204
205
206
207
208 @Override
209 public String toString() {
210 return "Builder [name=" + getName() + ", factoryName=" + factoryName + ", providerUrl=" + providerUrl
211 + ", urlPkgPrefixes=" + urlPkgPrefixes + ", securityPrincipalName=" + securityPrincipalName
212 + ", securityCredentials=" + securityCredentials + ", factoryBindingName=" + factoryBindingName
213 + ", destinationBindingName=" + destinationBindingName + ", username=" + userName + ", layout="
214 + getLayout() + ", filter=" + getFilter() + ", ignoreExceptions=" + isIgnoreExceptions()
215 + ", jmsManager=" + jmsManager + "]";
216 }
217
218 }
219
220 @PluginBuilderFactory
221 public static Builder newBuilder() {
222 return new Builder();
223 }
224
225 private volatile JmsManager manager;
226
227
228
229
230
231 protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
232 final boolean ignoreExceptions, final Property[] properties, final JmsManager manager) throws JMSException {
233 super(name, filter, layout, ignoreExceptions, properties);
234 this.manager = manager;
235 }
236
237
238
239
240
241
242 @Deprecated
243 protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
244 final boolean ignoreExceptions, final JmsManager manager) throws JMSException {
245 super(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY);
246 this.manager = manager;
247 }
248
249 @Override
250 public void append(final LogEvent event) {
251 this.manager.send(event, toSerializable(event));
252 }
253
254 public JmsManager getManager() {
255 return manager;
256 }
257
258 @Override
259 public boolean stop(final long timeout, final TimeUnit timeUnit) {
260 setStopping();
261 boolean stopped = super.stop(timeout, timeUnit, false);
262 stopped &= this.manager.stop(timeout, timeUnit);
263 setStopped();
264 return stopped;
265 }
266
267 }