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