001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache license, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License. You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the license for the specific language governing permissions and
015     * limitations under the license.
016     */
017    
018    package org.apache.logging.log4j.core.appender.mom;
019    
020    import java.io.Serializable;
021    import javax.jms.JMSException;
022    import javax.jms.Message;
023    import javax.jms.MessageProducer;
024    
025    import org.apache.logging.log4j.core.Filter;
026    import org.apache.logging.log4j.core.Layout;
027    import org.apache.logging.log4j.core.LogEvent;
028    import org.apache.logging.log4j.core.appender.AbstractAppender;
029    import org.apache.logging.log4j.core.appender.AppenderLoggingException;
030    import org.apache.logging.log4j.core.config.plugins.Plugin;
031    import org.apache.logging.log4j.core.config.plugins.PluginAliases;
032    import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
033    import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
034    import org.apache.logging.log4j.core.config.plugins.PluginElement;
035    import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
036    import org.apache.logging.log4j.core.layout.SerializedLayout;
037    import org.apache.logging.log4j.core.net.JndiManager;
038    
039    /**
040     * Generic JMS Appender plugin for both queues and topics. This Appender replaces the previous split ones. However,
041     * configurations set up for the 2.0 version of the JMS appenders will still work.
042     */
043    @Plugin(name = "JMS", category = "Core", elementType = "appender", printObject = true)
044    @PluginAliases({"JMSQueue", "JMSTopic"})
045    public class JmsAppender extends AbstractAppender {
046    
047        private static final long serialVersionUID = 1L;
048        private final JmsManager manager;
049        private final MessageProducer producer;
050    
051        protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
052                            final boolean ignoreExceptions, final JmsManager manager)
053            throws JMSException {
054            super(name, filter, layout, ignoreExceptions);
055            this.manager = manager;
056            this.producer = this.manager.createMessageProducer();
057        }
058    
059        @Override
060        public void append(final LogEvent event) {
061            try {
062                final Message message = this.manager.createMessage(getLayout().toSerializable(event));
063                message.setJMSTimestamp(event.getTimeMillis());
064                this.producer.send(message);
065            } catch (final JMSException e) {
066                throw new AppenderLoggingException(e);
067            }
068        }
069    
070        @PluginBuilderFactory
071        public static Builder newBuilder() {
072            return new Builder();
073        }
074    
075        public static class Builder implements org.apache.logging.log4j.core.util.Builder<JmsAppender> {
076    
077            @PluginBuilderAttribute
078            @Required(message = "A name for the JmsAppender must be specified")
079            private String name;
080    
081            @PluginBuilderAttribute
082            private String factoryName;
083    
084            @PluginBuilderAttribute
085            private String providerUrl;
086    
087            @PluginBuilderAttribute
088            private String urlPkgPrefixes;
089    
090            @PluginBuilderAttribute
091            private String securityPrincipalName;
092    
093            @PluginBuilderAttribute(sensitive = true)
094            private String securityCredentials;
095    
096            @PluginBuilderAttribute
097            @Required(message = "A javax.jms.ConnectionFactory JNDI name must be specified")
098            private String factoryBindingName;
099    
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    }