    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    }