I think he is doing it for OSGi. But if it has no third party dependencies I am 
not sure why it is necessary.

Sent from my iPad

> On Sep 6, 2014, at 5:14 AM, Gary Gregory <[email protected]> wrote:
> 
> What is the thought behind splitting JMS out of core?
> 
> Gary
> 
> 
> -------- Original message --------
> From: [email protected]
> Date:09/06/2014 00:58 (GMT-05:00)
> To: [email protected]
> Subject: [02/29] Split out JMS appender and receiver into new log4j module.
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/pom.xml
> ----------------------------------------------------------------------
> diff --git a/log4j-mom/pom.xml b/log4j-mom/pom.xml
> new file mode 100644
> index 0000000..6c3f760
> --- /dev/null
> +++ b/log4j-mom/pom.xml
> @@ -0,0 +1,53 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<project xmlns="http://maven.apache.org/POM/4.0.0";
> +         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> +         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
> http://maven.apache.org/xsd/maven-4.0.0.xsd";>
> +  <parent>
> +    <artifactId>log4j</artifactId>
> +    <groupId>org.apache.logging.log4j</groupId>
> +    <version>2.0-SNAPSHOT</version>
> +  </parent>
> +  <modelVersion>4.0.0</modelVersion>
> +
> +  <artifactId>log4j-mom</artifactId>
> +  <name>Log4j 2 MOM Plugins</name>
> +  <description>Message Oriented Middleware plugins for Log4j 2</description>
> +
> +  <dependencies>
> +    <dependency>
> +      <groupId>org.apache.logging.log4j</groupId>
> +      <artifactId>log4j-api</artifactId>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.apache.logging.log4j</groupId>
> +      <artifactId>log4j-core</artifactId>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.jboss.spec.javax.jms</groupId>
> +      <artifactId>jboss-jms-api_1.1_spec</artifactId>
> +    </dependency>
> +    <dependency>
> +      <groupId>junit</groupId>
> +      <artifactId>junit</artifactId>
> +      <scope>test</scope>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.mockejb</groupId>
> +      <artifactId>mockejb</artifactId>
> +      <scope>test</scope>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.apache.logging.log4j</groupId>
> +      <artifactId>log4j-core</artifactId>
> +      <type>test-jar</type>
> +      <scope>test</scope>
> +    </dependency>
> +    <dependency>
> +      <groupId>org.mockito</groupId>
> +      <artifactId>mockito-all</artifactId>
> +      <version>1.9.5</version>
> +      <scope>test</scope>
> +    </dependency>
> +  </dependencies>
> +
> +</project>
> \ No newline at end of file
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
> new file mode 100644
> index 0000000..284e1f6
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsQueueAppender.java
> @@ -0,0 +1,111 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +package org.apache.logging.log4j.mom.jms.appender;
> +
> +import java.io.Serializable;
> +
> +import org.apache.logging.log4j.core.Filter;
> +import org.apache.logging.log4j.core.Layout;
> +import org.apache.logging.log4j.core.LogEvent;
> +import org.apache.logging.log4j.core.appender.AbstractAppender;
> +import org.apache.logging.log4j.core.appender.AppenderLoggingException;
> +import org.apache.logging.log4j.core.config.plugins.Plugin;
> +import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
> +import org.apache.logging.log4j.core.config.plugins.PluginElement;
> +import org.apache.logging.log4j.core.config.plugins.PluginFactory;
> +import org.apache.logging.log4j.core.layout.SerializedLayout;
> +import org.apache.logging.log4j.mom.jms.receiver.JmsQueueManager;
> +import org.apache.logging.log4j.core.util.Booleans;
> +
> +/**
> + * Appender to write to a JMS Queue.
> + */
> +@Plugin(name = "JMSQueue", category = "Core", elementType = "appender", 
> printObject = true)
> +public final class JmsQueueAppender extends AbstractAppender {
> +
> +    private final JmsQueueManager manager;
> +
> +    private JmsQueueAppender(final String name, final Filter filter, final 
> Layout<? extends Serializable> layout,
> +                             final JmsQueueManager manager, final boolean 
> ignoreExceptions) {
> +        super(name, filter, layout, ignoreExceptions);
> +        this.manager = manager;
> +    }
> +
> +    /**
> +     * Actual writing occurs here.
> +     * 
> +     * @param event The LogEvent.
> +     */
> +    @Override
> +    public void append(final LogEvent event) {
> +        try {
> +            manager.send(getLayout().toSerializable(event));
> +        } catch (final Exception ex) {
> +            throw new AppenderLoggingException(ex);
> +        }
> +    }
> +
> +    /**
> +     * Create a JmsQueueAppender.
> +     * @param name The name of the Appender.
> +     * @param factoryName The fully qualified class name of the 
> InitialContextFactory.
> +     * @param providerURL The URL of the provider to use.
> +     * @param urlPkgPrefixes A colon-separated list of package prefixes for 
> the class name of the factory class that
> +     * will create a URL context factory
> +     * @param securityPrincipalName The name of the identity of the 
> Principal.
> +     * @param securityCredentials The security credentials of the Principal.
> +     * @param factoryBindingName The name to locate in the Context that 
> provides the QueueConnectionFactory.
> +     * @param queueBindingName The name to use to locate the Queue.
> +     * @param userName The user ID to use to create the Queue Connection.
> +     * @param password The password to use to create the Queue Connection.
> +     * @param layout The layout to use (defaults to SerializedLayout).
> +     * @param filter The Filter or null.
> +     * @param ignore If {@code "true"} (default) exceptions encountered when 
> appending events are logged; otherwise
> +     *               they are propagated to the caller.
> +     * @return The JmsQueueAppender.
> +     */
> +    @PluginFactory
> +    public static JmsQueueAppender createAppender(
> +            @PluginAttribute("name") final String name,
> +            @PluginAttribute("factoryName") final String factoryName,
> +            @PluginAttribute("providerURL") final String providerURL,
> +            @PluginAttribute("urlPkgPrefixes") final String urlPkgPrefixes,
> +            @PluginAttribute("securityPrincipalName") final String 
> securityPrincipalName,
> +            @PluginAttribute("securityCredentials") final String 
> securityCredentials,
> +            @PluginAttribute("factoryBindingName") final String 
> factoryBindingName,
> +            @PluginAttribute("queueBindingName") final String 
> queueBindingName,
> +            @PluginAttribute("userName") final String userName,
> +            @PluginAttribute("password") final String password,
> +            @PluginElement("Layout") Layout<? extends Serializable> layout,
> +            @PluginElement("Filter") final Filter filter,
> +            @PluginAttribute("ignoreExceptions") final String ignore) {
> +        if (name == null) {
> +            LOGGER.error("No name provided for JmsQueueAppender");
> +            return null;
> +        }
> +        final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
> +        final JmsQueueManager manager = 
> JmsQueueManager.getJmsQueueManager(factoryName, providerURL, urlPkgPrefixes,
> +            securityPrincipalName, securityCredentials, factoryBindingName, 
> queueBindingName, userName, password);
> +        if (manager == null) {
> +            return null;
> +        }
> +        if (layout == null) {
> +            layout = SerializedLayout.createLayout();
> +        }
> +        return new JmsQueueAppender(name, filter, layout, manager, 
> ignoreExceptions);
> +    }
> +}
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
> new file mode 100644
> index 0000000..9985746
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/JmsTopicAppender.java
> @@ -0,0 +1,112 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +package org.apache.logging.log4j.mom.jms.appender;
> +
> +import java.io.Serializable;
> +
> +import org.apache.logging.log4j.core.Filter;
> +import org.apache.logging.log4j.core.Layout;
> +import org.apache.logging.log4j.core.LogEvent;
> +import org.apache.logging.log4j.core.appender.AbstractAppender;
> +import org.apache.logging.log4j.core.appender.AppenderLoggingException;
> +import org.apache.logging.log4j.core.config.plugins.Plugin;
> +import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
> +import org.apache.logging.log4j.core.config.plugins.PluginElement;
> +import org.apache.logging.log4j.core.config.plugins.PluginFactory;
> +import org.apache.logging.log4j.core.layout.SerializedLayout;
> +import org.apache.logging.log4j.mom.jms.receiver.JmsTopicManager;
> +import org.apache.logging.log4j.core.util.Booleans;
> +
> +/**
> + * Appender to write to a JMS Topic.
> + */
> +@Plugin(name = "JMSTopic", category = "Core", elementType = "appender", 
> printObject = true)
> +public final class JmsTopicAppender extends AbstractAppender {
> +
> +    private final JmsTopicManager manager;
> +
> +    private JmsTopicAppender(final String name, final Filter filter, final 
> Layout<? extends Serializable> layout,
> +                             final JmsTopicManager manager, final boolean 
> ignoreExceptions) {
> +        super(name, filter, layout, ignoreExceptions);
> +        this.manager = manager;
> +    }
> +
> +    /**
> +     * Actual writing occurs here.
> +     * <p/>
> +     * @param event The LogEvent.
> +     */
> +    @Override
> +    public void append(final LogEvent event) {
> +        try {
> +            manager.send(getLayout().toSerializable(event));
> +        } catch (final Exception ex) {
> +            throw new AppenderLoggingException(ex);
> +        }
> +    }
> +
> +    /**
> +     * Create a JmsTopicAppender.
> +     * @param name The name of the Appender.
> +     * @param factoryName The fully qualified class name of the 
> InitialContextFactory.
> +     * @param providerURL The URL of the provider to use.
> +     * @param urlPkgPrefixes A colon-separated list of package prefixes for 
> the class name of the factory class that
> +     * will create a URL context factory
> +     * @param securityPrincipalName The name of the identity of the 
> Principal.
> +     * @param securityCredentials The security credentials of the Principal.
> +     * @param factoryBindingName The name to locate in the Context that 
> provides the TopicConnectionFactory.
> +     * @param topicBindingName The name to use to locate the Topic.
> +     * @param userName The userid to use to create the Topic Connection.
> +     * @param password The password to use to create the Topic Connection.
> +     * @param layout The layout to use (defaults to SerializedLayout).
> +     * @param filter The Filter or null.
> +     * @param ignore If {@code "true"} (default) exceptions encountered when 
> appending events are logged; otherwise
> +     *               they are propagated to the caller.
> +     * @return The JmsTopicAppender.
> +     */
> +    @PluginFactory
> +    public static JmsTopicAppender createAppender(
> +            @PluginAttribute("name") final String name,
> +            @PluginAttribute("factoryName") final String factoryName,
> +            @PluginAttribute("providerURL") final String providerURL,
> +            @PluginAttribute("urlPkgPrefixes") final String urlPkgPrefixes,
> +            @PluginAttribute("securityPrincipalName") final String 
> securityPrincipalName,
> +            @PluginAttribute("securityCredentials") final String 
> securityCredentials,
> +            @PluginAttribute("factoryBindingName") final String 
> factoryBindingName,
> +            @PluginAttribute("topicBindingName") final String 
> topicBindingName,
> +            @PluginAttribute("userName") final String userName,
> +            @PluginAttribute("password") final String password,
> +            @PluginElement("Layout") Layout<? extends Serializable> layout,
> +            @PluginElement("Filters") final Filter filter,
> +            @PluginAttribute("ignoreExceptions") final String ignore) {
> +
> +        if (name == null) {
> +            LOGGER.error("No name provided for JmsQueueAppender");
> +            return null;
> +        }
> +        final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
> +        final JmsTopicManager manager = 
> JmsTopicManager.getJmsTopicManager(factoryName, providerURL, urlPkgPrefixes,
> +            securityPrincipalName, securityCredentials, factoryBindingName, 
> topicBindingName, userName, password);
> +        if (manager == null) {
> +            return null;
> +        }
> +        if (layout == null) {
> +            layout = SerializedLayout.createLayout();
> +        }
> +        return new JmsTopicAppender(name, filter, layout, manager, 
> ignoreExceptions);
> +    }
> +}
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
> new file mode 100644
> index 0000000..0c7a4ff
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/appender/package-info.java
> @@ -0,0 +1,20 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +/**
> + * Appender classes for using JMS. These are directly configured through 
> your log4j2 configuration file.
> + */
> +package org.apache.logging.log4j.mom.jms.appender;
> \ No newline at end of file
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
> new file mode 100644
> index 0000000..d3ae2a3
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsManager.java
> @@ -0,0 +1,155 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +package org.apache.logging.log4j.mom.jms.receiver;
> +
> +import java.io.Serializable;
> +import java.util.Properties;
> +
> +import javax.jms.JMSException;
> +import javax.jms.Message;
> +import javax.jms.MessageProducer;
> +import javax.jms.ObjectMessage;
> +import javax.jms.Session;
> +import javax.jms.TextMessage;
> +import javax.naming.Context;
> +import javax.naming.InitialContext;
> +import javax.naming.NameNotFoundException;
> +import javax.naming.NamingException;
> +
> +import org.apache.logging.log4j.core.appender.AbstractManager;
> +
> +/**
> + * Base Class for Managers of JMS connections.
> + */
> +public abstract class AbstractJmsManager extends AbstractManager {
> +
> +    /**
> +     * The Constructor.
> +     * @param name The name of the Appender.
> +     */
> +    public AbstractJmsManager(final String name) {
> +        super(name);
> +    }
> +
> +    /**
> +     * Create the InitialContext.
> +     * @param factoryName The fully qualified class name of the 
> InitialContextFactory.
> +     * @param providerURL The URL of the provider to use.
> +     * @param urlPkgPrefixes A colon-separated list of package prefixes for 
> the class name of the factory class that
> +     * will create a URL context factory
> +     * @param securityPrincipalName The name of the identity of the 
> Principal.
> +     * @param securityCredentials The security credentials of the Principal.
> +     * @return the InitialContext.
> +     * @throws NamingException if a naming error occurs.
> +     */
> +    protected static Context createContext(final String factoryName, final 
> String providerURL,
> +                                           final String urlPkgPrefixes, 
> final String securityPrincipalName,
> +                                           final String securityCredentials)
> +        throws NamingException {
> +
> +        final Properties props = getEnvironment(factoryName, providerURL, 
> urlPkgPrefixes, securityPrincipalName,
> +                                          securityCredentials);
> +        return new InitialContext(props);
> +    }
> +
> +    /**
> +     * Looks up the name in the context.
> +     * @param ctx The Context.
> +     * @param name The name to locate.
> +     * @return The object to be located.
> +     * @throws NamingException If an error occurs locating the name.
> +     */
> +    protected static Object lookup(final Context ctx, final String name) 
> throws NamingException {
> +        try {
> +            return ctx.lookup(name);
> +        } catch (final NameNotFoundException e) {
> +            LOGGER.warn("Could not find name [{}].", name);
> +            throw e;
> +        }
> +    }
> +
> +    /**
> +     * Sets up the properties to pass to the InitialContext.
> +     * @param factoryName The fully qualified class name of the 
> InitialContextFactory.
> +     * @param providerURL The URL of the provider to use.
> +     * @param urlPkgPrefixes A colon-separated list of package prefixes for 
> the class name of the factory class that
> +     * will create a URL context factory
> +     * @param securityPrincipalName The name of the identity of the 
> Principal.
> +     * @param securityCredentials The security credentials of the Principal.
> +     * @return The Properties.
> +     */
> +    protected static Properties getEnvironment(final String factoryName, 
> final String providerURL,
> +                                               final String urlPkgPrefixes, 
> final String securityPrincipalName,
> +                                               final String 
> securityCredentials) {
> +        final Properties props = new Properties();
> +        if (factoryName != null) {
> +            props.put(Context.INITIAL_CONTEXT_FACTORY, factoryName);
> +            if (providerURL != null) {
> +                props.put(Context.PROVIDER_URL, providerURL);
> +            } else {
> +                LOGGER.warn("The InitialContext factory name has been 
> provided without a ProviderURL. " +
> +                    "This is likely to cause problems");
> +            }
> +            if (urlPkgPrefixes != null) {
> +                props.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
> +            }
> +            if (securityPrincipalName != null) {
> +                props.put(Context.SECURITY_PRINCIPAL, securityPrincipalName);
> +                if (securityCredentials != null) {
> +                    props.put(Context.SECURITY_CREDENTIALS, 
> securityCredentials);
> +                } else {
> +                    LOGGER.warn("SecurityPrincipalName has been set without 
> SecurityCredentials. " +
> +                        "This is likely to cause problems.");
> +                }
> +            }
> +            return props;
> +        }
> +        return null;
> +    }
> +
> +    /**
> +     * Send the message.
> +     * @param object The Object to sent.
> +     * @throws Exception if an error occurs.
> +     */
> +    public abstract void send(Serializable object) throws Exception;
> +
> +    /**
> +     * Send the Object.
> +     * @param object The Object to send.
> +     * @param session The Session.
> +     * @param producer The MessageProducer.
> +     * @throws Exception if an error occurs.
> +     */
> +    public synchronized void send(final Serializable object, final Session 
> session, final MessageProducer producer)
> +        throws Exception {
> +        try {
> +            Message msg;
> +            if (object instanceof String) {
> +                msg = session.createTextMessage();
> +                ((TextMessage) msg).setText((String) object);
> +            } else {
> +                msg = session.createObjectMessage();
> +                ((ObjectMessage) msg).setObject(object);
> +            }
> +            producer.send(msg);
> +        } catch (final JMSException ex) {
> +            LOGGER.error("Could not publish message via JMS {}", getName());
> +            throw ex;
> +        }
> +    }
> +}
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
> new file mode 100644
> index 0000000..bf86c65
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/AbstractJmsReceiver.java
> @@ -0,0 +1,83 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +package org.apache.logging.log4j.mom.jms.receiver;
> +
> +import java.io.Serializable;
> +
> +import javax.jms.JMSException;
> +import javax.jms.ObjectMessage;
> +import javax.naming.Context;
> +import javax.naming.NameNotFoundException;
> +import javax.naming.NamingException;
> +
> +import org.apache.logging.log4j.LogManager;
> +import org.apache.logging.log4j.Logger;
> +import org.apache.logging.log4j.core.LogEvent;
> +import org.apache.logging.log4j.core.LogEventListener;
> +
> +/**
> + * Abstract base class for receiving LogEvents over JMS. This class expects 
> all messages to be serialized log events.
> + */
> +public abstract class AbstractJmsReceiver extends LogEventListener 
> implements javax.jms.MessageListener {
> +
> +    /**
> +     * Logger to capture diagnostics.
> +     */
> +    protected Logger logger = 
> LogManager.getLogger(this.getClass().getName());
> +
> +    /**
> +     * Listener that receives the event.
> +     * @param message The received message.
> +     */
> +    @Override
> +    public void onMessage(final javax.jms.Message message) {
> +        try {
> +            if (message instanceof ObjectMessage) {
> +                final ObjectMessage objectMessage = (ObjectMessage) message;
> +                final Serializable object = objectMessage.getObject();
> +                if (object instanceof LogEvent) {
> +                    log((LogEvent) object);
> +                } else {
> +                    logger.warn("Received message is of type " + 
> object.getClass().getName() + ", was expecting LogEvent.");
> +                }
> +            } else {
> +                logger.warn("Received message is of type " + 
> message.getJMSType()
> +                    + ", was expecting ObjectMessage.");
> +            }
> +        } catch (final JMSException jmse) {
> +            logger.error("Exception thrown while processing incoming 
> message.",
> +                jmse);
> +        }
> +    }
> +
> +    /**
> +     * Looks up an object from the Context.
> +     * @param ctx The Context.
> +     * @param name The name of the object to locate.
> +     * @return The object.
> +     * @throws NamingException if an error occurs.
> +     */
> +    protected Object lookup(final Context ctx, final String name) throws 
> NamingException {
> +        try {
> +            return ctx.lookup(name);
> +        } catch (final NameNotFoundException e) {
> +            logger.error("Could not find name [" + name + "].");
> +            throw e;
> +        }
> +    }
> +
> +}
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
> new file mode 100644
> index 0000000..6825282
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueManager.java
> @@ -0,0 +1,237 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +package org.apache.logging.log4j.mom.jms.receiver;
> +
> +import java.io.Serializable;
> +
> +import javax.jms.JMSException;
> +import javax.jms.Queue;
> +import javax.jms.QueueConnection;
> +import javax.jms.QueueConnectionFactory;
> +import javax.jms.QueueSender;
> +import javax.jms.QueueSession;
> +import javax.jms.Session;
> +import javax.naming.Context;
> +import javax.naming.NamingException;
> +
> +import org.apache.logging.log4j.core.appender.ManagerFactory;
> +
> +/**
> + * Manager for a JMS Queue.
> + */
> +public class JmsQueueManager extends AbstractJmsManager {
> +
> +    private static final JMSQueueManagerFactory FACTORY = new 
> JMSQueueManagerFactory();
> +
> +    private QueueInfo info;
> +    private final String factoryBindingName;
> +    private final String queueBindingName;
> +    private final String userName;
> +    private final String password;
> +    private final Context context;
> +
> +    /**
> +     * The Constructor.
> +     * @param name The unique name of the connection.
> +     * @param context The context.
> +     * @param factoryBindingName The factory binding name.
> +     * @param queueBindingName The queue binding name.
> +     * @param userName The user name.
> +     * @param password The credentials for the user.
> +     * @param info The Queue connection info.
> +     */
> +    protected JmsQueueManager(final String name, final Context context, 
> final String factoryBindingName,
> +                              final String queueBindingName, final String 
> userName, final String password,
> +                              final QueueInfo info) {
> +        super(name);
> +        this.context = context;
> +        this.factoryBindingName = factoryBindingName;
> +        this.queueBindingName = queueBindingName;
> +        this.userName = userName;
> +        this.password = password;
> +        this.info = info;
> +    }
> +
> +    /**
> +     * Obtain a JmsQueueManager.
> +     * @param factoryName The fully qualified class name of the 
> InitialContextFactory.
> +     * @param providerURL The URL of the provider to use.
> +     * @param urlPkgPrefixes A colon-separated list of package prefixes for 
> the class name of the factory class that
> +     * will create a URL context factory
> +     * @param securityPrincipalName The name of the identity of the 
> Principal.
> +     * @param securityCredentials The security credentials of the Principal.
> +     * @param factoryBindingName The name to locate in the Context that 
> provides the QueueConnectionFactory.
> +     * @param queueBindingName The name to use to locate the Queue.
> +     * @param userName The userid to use to create the Queue Connection.
> +     * @param password The password to use to create the Queue Connection.
> +     * @return The JmsQueueManager.
> +     */
> +    public static JmsQueueManager getJmsQueueManager(final String 
> factoryName, final String providerURL,
> +                                                     final String 
> urlPkgPrefixes, final String securityPrincipalName,
> +                                                     final String 
> securityCredentials, final String factoryBindingName,
> +                                                     final String 
> queueBindingName, final String userName,
> +                                                     final String password) {
> +
> +        if (factoryBindingName == null) {
> +            LOGGER.error("No factory name provided for JmsQueueManager");
> +            return null;
> +        }
> +        if (queueBindingName == null) {
> +            LOGGER.error("No topic name provided for JmsQueueManager");
> +            return null;
> +        }
> +
> +        final String name = "JMSQueue:" + factoryBindingName + '.' + 
> queueBindingName;
> +        return getManager(name, FACTORY, new FactoryData(factoryName, 
> providerURL, urlPkgPrefixes,
> +            securityPrincipalName, securityCredentials, factoryBindingName, 
> queueBindingName, userName, password));
> +    }
> +
> +    @Override
> +    public synchronized void send(final Serializable object) throws 
> Exception {
> +        if (info == null) {
> +            info = connect(context, factoryBindingName, queueBindingName, 
> userName, password, false);
> +        }
> +        try {
> +            super.send(object, info.session, info.sender);
> +        } catch (final Exception ex) {
> +            cleanup(true);
> +            throw ex;
> +        }
> +    }
> +
> +    @Override
> +    public void releaseSub() {
> +        if (info != null) {
> +            cleanup(false);
> +        }
> +    }
> +
> +    private void cleanup(final boolean quiet) {
> +        try {
> +            info.session.close();
> +        } catch (final Exception e) {
> +            if (!quiet) {
> +                LOGGER.error("Error closing session for " + getName(), e);
> +            }
> +        }
> +        try {
> +            info.conn.close();
> +        } catch (final Exception e) {
> +            if (!quiet) {
> +                LOGGER.error("Error closing connection for " + getName(), e);
> +            }
> +        }
> +        info = null;
> +    }
> +
> +    /**
> +     * Data for the factory.
> +     */
> +    private static class FactoryData {
> +        private final String factoryName;
> +        private final String providerURL;
> +        private final String urlPkgPrefixes;
> +        private final String securityPrincipalName;
> +        private final String securityCredentials;
> +        private final String factoryBindingName;
> +        private final String queueBindingName;
> +        private final String userName;
> +        private final String password;
> +
> +        public FactoryData(final String factoryName, final String 
> providerURL, final String urlPkgPrefixes,
> +                           final String securityPrincipalName, final String 
> securityCredentials,
> +                           final String factoryBindingName, final String 
> queueBindingName, final String userName,
> +                           final String password) {
> +            this.factoryName = factoryName;
> +            this.providerURL = providerURL;
> +            this.urlPkgPrefixes = urlPkgPrefixes;
> +            this.securityPrincipalName = securityPrincipalName;
> +            this.securityCredentials = securityCredentials;
> +            this.factoryBindingName = factoryBindingName;
> +            this.queueBindingName = queueBindingName;
> +            this.userName = userName;
> +            this.password = password;
> +        }
> +    }
> +
> +    private static QueueInfo connect(final Context context, final String 
> factoryBindingName,
> +                                     final String queueBindingName, final 
> String userName, final String password,
> +                                     final boolean suppress) throws 
> Exception {
> +        try {
> +            final QueueConnectionFactory factory = (QueueConnectionFactory) 
> lookup(context, factoryBindingName);
> +            QueueConnection conn;
> +            if (userName != null) {
> +                conn = factory.createQueueConnection(userName, password);
> +            } else {
> +                conn = factory.createQueueConnection();
> +            }
> +            final QueueSession sess = conn.createQueueSession(false, 
> Session.AUTO_ACKNOWLEDGE);
> +            final Queue queue = (Queue) lookup(context, queueBindingName);
> +            final QueueSender sender = sess.createSender(queue);
> +            conn.start();
> +            return new QueueInfo(conn, sess, sender);
> +        } catch (final NamingException ex) {
> +            LOGGER.warn("Unable to locate connection factory " + 
> factoryBindingName, ex);
> +            if (!suppress) {
> +                throw ex;
> +            }
> +        } catch (final JMSException ex) {
> +            LOGGER.warn("Unable to create connection to queue " + 
> queueBindingName, ex);
> +            if (!suppress) {
> +                throw ex;
> +            }
> +        }
> +        return null;
> +    }
> +
> +    /** Queue connection information */
> +    private static class QueueInfo {
> +        private final QueueConnection conn;
> +        private final QueueSession session;
> +        private final QueueSender sender;
> +
> +        public QueueInfo(final QueueConnection conn, final QueueSession 
> session, final QueueSender sender) {
> +            this.conn = conn;
> +            this.session = session;
> +            this.sender = sender;
> +        }
> +    }
> +
> +    /**
> +     * Factory to create the JmsQueueManager.
> +     */
> +    private static class JMSQueueManagerFactory implements 
> ManagerFactory<JmsQueueManager, FactoryData> {
> +
> +        @Override
> +        public JmsQueueManager createManager(final String name, final 
> FactoryData data) {
> +            try {
> +                final Context ctx = createContext(data.factoryName, 
> data.providerURL, data.urlPkgPrefixes,
> +                                            data.securityPrincipalName, 
> data.securityCredentials);
> +                final QueueInfo info = connect(ctx, data.factoryBindingName, 
> data.queueBindingName, data.userName,
> +                    data.password, true);
> +                return new JmsQueueManager(name, ctx, 
> data.factoryBindingName, data.queueBindingName,
> +                    data.userName, data.password, info);
> +            } catch (final NamingException ex) {
> +                LOGGER.error("Unable to locate resource", ex);
> +            } catch (final Exception ex) {
> +                LOGGER.error("Unable to connect", ex);
> +            }
> +
> +            return null;
> +        }
> +    }
> +}
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
> new file mode 100644
> index 0000000..b231489
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsQueueReceiver.java
> @@ -0,0 +1,107 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +package org.apache.logging.log4j.mom.jms.receiver;
> +
> +import java.io.BufferedReader;
> +import java.io.InputStreamReader;
> +import java.nio.charset.Charset;
> +
> +import javax.jms.JMSException;
> +import javax.jms.Queue;
> +import javax.jms.QueueConnection;
> +import javax.jms.QueueConnectionFactory;
> +import javax.jms.QueueReceiver;
> +import javax.jms.QueueSession;
> +import javax.jms.Session;
> +import javax.naming.Context;
> +import javax.naming.InitialContext;
> +import javax.naming.NamingException;
> +
> +/**
> + * Receives Log Events over a JMS Queue. This implementation expects that 
> all messages will
> + * contain a serialized LogEvent.
> + */
> +public class JmsQueueReceiver extends AbstractJmsReceiver {
> +
> +    /**
> +     * Constructor.
> +     * @param qcfBindingName The QueueConnectionFactory binding name.
> +     * @param queueBindingName The Queue binding name.
> +     * @param username The userid to connect to the queue.
> +     * @param password The password to connect to the queue.
> +     */
> +    public JmsQueueReceiver(final String qcfBindingName, final String 
> queueBindingName, final String username,
> +                            final String password) {
> +
> +        try {
> +            final Context ctx = new InitialContext();
> +            QueueConnectionFactory queueConnectionFactory;
> +            queueConnectionFactory = (QueueConnectionFactory) lookup(ctx, 
> qcfBindingName);
> +            final QueueConnection queueConnection = 
> queueConnectionFactory.createQueueConnection(username, password);
> +            queueConnection.start();
> +            final QueueSession queueSession = 
> queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
> +            final Queue queue = (Queue) ctx.lookup(queueBindingName);
> +            final QueueReceiver queueReceiver = 
> queueSession.createReceiver(queue);
> +            queueReceiver.setMessageListener(this);
> +        } catch (final JMSException e) {
> +            logger.error("Could not read JMS message.", e);
> +        } catch (final NamingException e) {
> +            logger.error("Could not read JMS message.", e);
> +        } catch (final RuntimeException e) {
> +            logger.error("Could not read JMS message.", e);
> +        }
> +    }
> +
> +    /**
> +     * Main startup for the receiver.
> +     * @param args The command line arguments.
> +     * @throws Exception if an error occurs.
> +     */
> +    public static void main(final String[] args) throws Exception {
> +        if (args.length != 4) {
> +            usage("Wrong number of arguments.");
> +        }
> +
> +        final String qcfBindingName = args[0];
> +        final String queueBindingName = args[1];
> +        final String username = args[2];
> +        final String password = args[3];
> +
> +        new JmsQueueReceiver(qcfBindingName, queueBindingName, username, 
> password);
> +
> +        final Charset enc = Charset.defaultCharset();
> +        final BufferedReader stdin = new BufferedReader(new 
> InputStreamReader(System.in, enc));
> +        // Loop until the word "exit" is typed
> +        System.out.println("Type \"exit\" to quit JmsQueueReceiver.");
> +        while (true) {
> +            final String line = stdin.readLine();
> +            if (line == null || line.equalsIgnoreCase("exit")) {
> +                System.out.println("Exiting. Kill the application if it does 
> not exit "
> +                    + "due to daemon threads.");
> +                return;
> +            }
> +        }
> +    }
> +
> +
> +    private static void usage(final String msg) {
> +        System.err.println(msg);
> +        System.err.println("Usage: java " + JmsQueueReceiver.class.getName()
> +            + " QueueConnectionFactoryBindingName QueueBindingName username 
> password");
> +        System.exit(1);
> +    }
> +}
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1274408e/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsTopicManager.java
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsTopicManager.java
>  
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsTopicManager.java
> new file mode 100644
> index 0000000..08d7128
> --- /dev/null
> +++ 
> b/log4j-mom/src/main/java/org/apache/logging/log4j/mom/jms/receiver/JmsTopicManager.java
> @@ -0,0 +1,237 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache license, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the license for the specific language governing permissions and
> + * limitations under the license.
> + */
> +package org.apache.logging.log4j.mom.jms.receiver;
> +
> +import java.io.Serializable;
> +
> +import javax.jms.JMSException;
> +import javax.jms.Session;
> +import javax.jms.Topic;
> +import javax.jms.TopicConnection;
> +import javax.jms.TopicConnectionFactory;
> +import javax.jms.TopicPublisher;
> +import javax.jms.TopicSession;
> +import javax.naming.Context;
> +import javax.naming.NamingException;
> +
> +import org.apache.logging.log4j.core.appender.ManagerFactory;
> +
> +/**
> + * Manager for JMS Topic connections.
> + */
> +public class JmsTopicManager extends AbstractJmsManager {
> +
> +    private static final JMSTopicManagerFactory FACTORY = new 
> JMSTopicManagerFactory();
> +
> +    private TopicInfo info;
> +    private final String factoryBindingName;
> +    private final String topicBindingName;
> +    private final String userName;
> +    private final String password;
> +    private final Context context;
> +    /**
> +     * Constructor.
> +     * @param name The unique name of the connection.
> +     * @param context The context.
> +     * @param factoryBindingName The factory binding name.
> +     * @param topicBindingName The queue binding name.
> +     * @param userName The user name.
> +     * @param password The credentials for the user.
> +     * @param info The Queue connection info.
> +     */
> +    protected JmsTopicManager(final String name, final Context context, 
> final String factoryBindingName,
> +                              final String topicBindingName, final String 
> userName, final String password,
> +                              final TopicInfo info) {
> +        super(name);
> +        this.context = context;
> +        this.factoryBindingName = factoryBindingName;
> +        this.topicBindingName = topicBindingName;
> +        this.userName = userName;
> +        this.password = password;
> +        this.info = info;
> +    }
> +
> +    /**
> +     * Obtain a JSMTopicManager.
> +     * @param factoryName The fully qualified class name of the 
> InitialContextFactory.
> +     * @param providerURL The URL of the provider to use.
> +     * @param urlPkgPrefixes A colon-separated list of package prefixes for 
> the class name of the factory class that
> +     * will create a URL context factory
> +     * @param securityPrincipalName The name of the identity of the 
> Principal.
> +     * @param securityCredentials The security credentials of the Principal.
> +     * @param factoryBindingName The name to locate in the Context that 
> provides the TopicConnectionFactory.
> +     * @param topicBindingName The name to use to locate the Topic.
> +     * @param userName The userid to use to create the Topic Connection.
> +     * @param password The password to use to create the Topic Connection.
> +     * @return A JmsTopicManager.
> +     */
> +    public static JmsTopicManager getJmsTopicManager(final String 
> factoryName, final String providerURL,
> +                                                     final String 
> urlPkgPrefixes, final String securityPrincipalName,
> +                                                     final String 
> securityCredentials, final String factoryBindingName,
> +                                                     final String 
> topicBindingName, final String userName,
> +                                                     final String password) {
> +
> +        if (factoryBindingName == null) {
> +            LOGGER.error("No factory name provided for JmsTopicManager");
> +            return null;
> +        }
> +        if (topicBindingName == null) {
> +            LOGGER.error("No topic name provided for JmsTopicManager");
> +            return null;
> +        }
> +
> +        final String name = "JMSTopic:" + factoryBindingName + '.' + 
> topicBindingName;
> +        return getManager(name, FACTORY, new FactoryData(factoryName, 
> providerURL, urlPkgPrefixes,
> +            securityPrincipalName, securityCredentials, factoryBindingName, 
> topicBindingName, userName, password));
> +    }
> +
> +
> +    @Override
> +    public void send(final Serializable object) throws Exception {
> +        if (info == null) {
> +            info = connect(context, factoryBindingName, topicBindingName, 
> userName, password, false);
> +        }
> +        try {
> +            super.send(object, info.session, info.publisher);
> +        } catch (final Exception ex) {
> +            cleanup(true);
> +            throw ex;
> +        }
> +    }
> +
> +    @Override
> +    public void releaseSub() {
> +        if (info != null) {
> +            cleanup(false);
> +        }
> +    }
> +
> +    private void cleanup(final boolean quiet) {
> +        try {
> +            info.session.close();
> +        } catch (final Exception e) {
> +            if (!quiet) {
> +                LOGGER.error("Error closing session for " + getName(), e);
> +            }
> +        }
> +        try {
> +            info.conn.close();
> +        } catch (final Exception e) {
> +            if (!quiet) {
> +                LOGGER.error("Error closing connection for " + getName(), e);
> +            }
> +        }
> +        info = null;
> +    }
> +
> +    /**
> +     * Data for the factory.
> +     */
> +    private static class FactoryData {
> +        private final String factoryName;
> +        private final String providerURL;
> +        private final String urlPkgPrefixes;
> +        private final String securityPrincipalName;
> +        private final String securityCredentials;
> +        private final String factoryBindingName;
> +        private final String topicBindingName;
> +        private final String userName;
> +        private final String password;
> +
> +        public FactoryData(final String factoryName, final String 
> providerURL, final String urlPkgPrefixes,
> +                           final String securityPrincipalName, final String 
> securityCredentials,
> +                           final String factoryBindingName, final String 
> topicBindingName,
> +                           final String userName, final String password) {
> +            this.factoryName = factoryName;
> +            this.providerURL = providerURL;
> +            this.urlPkgPrefixes = urlPkgPrefixes;
> +            this.securityPrincipalName = securityPrincipalName;
> +            this.securityCredentials = securityCredentials;
> +            this.factoryBindingName = factoryBindingName;
> +            this.topicBindingName = topicBindingName;
> +            this.userName = userName;
> +            this.password = password;
> +        }

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to