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  
18  package org.apache.logging.log4j.core.appender.mom;
19  
20  import java.io.Serializable;
21  import java.util.concurrent.TimeUnit;
22  
23  import javax.jms.JMSException;
24  import javax.jms.Message;
25  import javax.jms.MessageProducer;
26  
27  import org.apache.logging.log4j.core.Appender;
28  import org.apache.logging.log4j.core.Filter;
29  import org.apache.logging.log4j.core.Layout;
30  import org.apache.logging.log4j.core.LogEvent;
31  import org.apache.logging.log4j.core.appender.AbstractAppender;
32  import org.apache.logging.log4j.core.appender.AppenderLoggingException;
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.layout.SerializedLayout;
41  import org.apache.logging.log4j.core.net.JndiManager;
42  
43  /**
44   * Generic JMS Appender plugin for both queues and topics. This Appender replaces the previous split ones. However,
45   * configurations set up for the 2.0 version of the JMS appenders will still work.
46   */
47  @Plugin(name = "JMS", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
48  @PluginAliases({"JMSQueue", "JMSTopic"})
49  public class JmsAppender extends AbstractAppender {
50  
51      private final JmsManager manager;
52      private final MessageProducer producer;
53  
54      protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
55                          final boolean ignoreExceptions, final JmsManager manager)
56          throws JMSException {
57          super(name, filter, layout, ignoreExceptions);
58          this.manager = manager;
59          this.producer = this.manager.createMessageProducer();
60      }
61  
62      @Override
63      public void append(final LogEvent event) {
64          try {
65              final Message message = this.manager.createMessage(getLayout().toSerializable(event));
66              message.setJMSTimestamp(event.getTimeMillis());
67              this.producer.send(message);
68          } catch (final JMSException e) {
69              throw new AppenderLoggingException(e);
70          }
71      }
72  
73      @Override
74      public boolean stop(final long timeout, final TimeUnit timeUnit) {
75          setStopping();
76          boolean stopped = super.stop(timeout, timeUnit, false);
77          stopped &= this.manager.stop(timeout, timeUnit);
78          setStopped();
79          return stopped;
80      }
81  
82      @PluginBuilderFactory
83      public static Builder newBuilder() {
84          return new Builder();
85      }
86  
87      public static class Builder implements org.apache.logging.log4j.core.util.Builder<JmsAppender> {
88  
89          @PluginBuilderAttribute
90          @Required(message = "A name for the JmsAppender must be specified")
91          private String name;
92  
93          @PluginBuilderAttribute
94          private String factoryName;
95  
96          @PluginBuilderAttribute
97          private String providerUrl;
98  
99          @PluginBuilderAttribute
100         private String urlPkgPrefixes;
101 
102         @PluginBuilderAttribute
103         private String securityPrincipalName;
104 
105         @PluginBuilderAttribute(sensitive = true)
106         private String securityCredentials;
107 
108         @PluginBuilderAttribute
109         @Required(message = "A javax.jms.ConnectionFactory JNDI name must be specified")
110         private String factoryBindingName;
111 
112         @PluginBuilderAttribute
113         @PluginAliases({"queueBindingName", "topicBindingName"})
114         @Required(message = "A javax.jms.Destination JNDI name must be specified")
115         private String destinationBindingName;
116 
117         @PluginBuilderAttribute
118         private String username;
119 
120         @PluginBuilderAttribute(sensitive = true)
121         private String password;
122 
123         @PluginElement("Layout")
124         private Layout<? extends Serializable> layout = SerializedLayout.createLayout();
125 
126         @PluginElement("Filter")
127         private Filter filter;
128 
129         @PluginBuilderAttribute
130         private boolean ignoreExceptions = true;
131 
132         private Builder() {
133         }
134 
135         public Builder setName(final String name) {
136             this.name = name;
137             return this;
138         }
139 
140         public Builder setFactoryName(final String factoryName) {
141             this.factoryName = factoryName;
142             return this;
143         }
144 
145         public Builder setProviderUrl(final String providerUrl) {
146             this.providerUrl = providerUrl;
147             return this;
148         }
149 
150         public Builder setUrlPkgPrefixes(final String urlPkgPrefixes) {
151             this.urlPkgPrefixes = urlPkgPrefixes;
152             return this;
153         }
154 
155         public Builder setSecurityPrincipalName(final String securityPrincipalName) {
156             this.securityPrincipalName = securityPrincipalName;
157             return this;
158         }
159 
160         public Builder setSecurityCredentials(final String securityCredentials) {
161             this.securityCredentials = securityCredentials;
162             return this;
163         }
164 
165         public Builder setFactoryBindingName(final String factoryBindingName) {
166             this.factoryBindingName = factoryBindingName;
167             return this;
168         }
169 
170         public Builder setDestinationBindingName(final String destinationBindingName) {
171             this.destinationBindingName = destinationBindingName;
172             return this;
173         }
174 
175         public Builder setUsername(final String username) {
176             this.username = username;
177             return this;
178         }
179 
180         public Builder setPassword(final String password) {
181             this.password = password;
182             return this;
183         }
184 
185         public Builder setLayout(final Layout<? extends Serializable> layout) {
186             this.layout = layout;
187             return this;
188         }
189 
190         public Builder setFilter(final Filter filter) {
191             this.filter = filter;
192             return this;
193         }
194 
195         public Builder setIgnoreExceptions(final boolean ignoreExceptions) {
196             this.ignoreExceptions = ignoreExceptions;
197             return this;
198         }
199 
200         @Override
201         public JmsAppender build() {
202             final JndiManager jndiManager = JndiManager.getJndiManager(factoryName, providerUrl, urlPkgPrefixes,
203                 securityPrincipalName, securityCredentials, null);
204             final JmsManager jmsManager = JmsManager.getJmsManager(name, jndiManager, factoryBindingName,
205                 destinationBindingName, username, password);
206             try {
207                 return new JmsAppender(name, filter, layout, ignoreExceptions, jmsManager);
208             } catch (final JMSException e) {
209                 LOGGER.error("Error creating JmsAppender [{}].", name, e);
210                 return null;
211             }
212         }
213     }
214 
215 }