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]
