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