001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017
018 package org.apache.logging.log4j.core.appender.mom;
019
020 import java.io.Serializable;
021 import javax.jms.Connection;
022 import javax.jms.ConnectionFactory;
023 import javax.jms.Destination;
024 import javax.jms.JMSException;
025 import javax.jms.Message;
026 import javax.jms.MessageConsumer;
027 import javax.jms.MessageProducer;
028 import javax.jms.Session;
029 import javax.naming.NamingException;
030
031 import org.apache.logging.log4j.Logger;
032 import org.apache.logging.log4j.core.appender.AbstractManager;
033 import org.apache.logging.log4j.core.appender.ManagerFactory;
034 import org.apache.logging.log4j.core.net.JndiManager;
035 import org.apache.logging.log4j.status.StatusLogger;
036
037 /**
038 * JMS connection and session manager. Can be used to access MessageProducer, MessageConsumer, and Message objects
039 * involving a configured ConnectionFactory and Destination.
040 */
041 public class JmsManager extends AbstractManager {
042
043 private static final Logger LOGGER = StatusLogger.getLogger();
044
045 private static final JmsManagerFactory FACTORY = new JmsManagerFactory();
046
047 private final JndiManager jndiManager;
048 private final Connection connection;
049 private final Session session;
050 private final Destination destination;
051
052 private JmsManager(final String name, final JndiManager jndiManager, final String connectionFactoryName,
053 final String destinationName, final String username, final String password)
054 throws NamingException, JMSException {
055 super(name);
056 this.jndiManager = jndiManager;
057 final ConnectionFactory connectionFactory = this.jndiManager.lookup(connectionFactoryName);
058 if (username != null && password != null) {
059 this.connection = connectionFactory.createConnection(username, password);
060 } else {
061 this.connection = connectionFactory.createConnection();
062 }
063 this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
064 this.destination = this.jndiManager.lookup(destinationName);
065 this.connection.start();
066 }
067
068 /**
069 * Gets a JmsManager using the specified configuration parameters.
070 *
071 * @param name The name to use for this JmsManager.
072 * @param jndiManager The JndiManager to look up JMS information through.
073 * @param connectionFactoryName The binding name for the {@link javax.jms.ConnectionFactory}.
074 * @param destinationName The binding name for the {@link javax.jms.Destination}.
075 * @param username The username to connect with or {@code null} for no authentication.
076 * @param password The password to use with the given username or {@code null} for no authentication.
077 * @return The JmsManager as configured.
078 */
079 public static JmsManager getJmsManager(final String name, final JndiManager jndiManager,
080 final String connectionFactoryName, final String destinationName,
081 final String username, final String password) {
082 final JmsConfiguration configuration = new JmsConfiguration(jndiManager, connectionFactoryName, destinationName,
083 username, password);
084 return FACTORY.createManager(name, configuration);
085 }
086
087 /**
088 * Creates a MessageConsumer on this Destination using the current Session.
089 *
090 * @return A MessageConsumer on this Destination.
091 * @throws JMSException
092 */
093 public MessageConsumer createMessageConsumer() throws JMSException {
094 return this.session.createConsumer(this.destination);
095 }
096
097 /**
098 * Creates a MessageProducer on this Destination using the current Session.
099 *
100 * @return A MessageProducer on this Destination.
101 * @throws JMSException
102 */
103 public MessageProducer createMessageProducer() throws JMSException {
104 return this.session.createProducer(this.destination);
105 }
106
107 /**
108 * Creates a TextMessage or ObjectMessage from a Serializable object. For instance, when using a text-based
109 * {@link org.apache.logging.log4j.core.Layout} such as {@link org.apache.logging.log4j.core.layout.PatternLayout},
110 * the {@link org.apache.logging.log4j.core.LogEvent} message will be serialized to a String. When using a
111 * layout such as {@link org.apache.logging.log4j.core.layout.SerializedLayout}, the LogEvent message will be
112 * serialized as a Java object.
113 *
114 * @param object The LogEvent or String message to wrap.
115 * @return A new JMS message containing the provided object.
116 * @throws JMSException
117 */
118 public Message createMessage(final Serializable object) throws JMSException {
119 if (object instanceof String) {
120 return this.session.createTextMessage((String) object);
121 }
122 return this.session.createObjectMessage(object);
123 }
124
125 @Override
126 protected void releaseSub() {
127 try {
128 this.session.close();
129 } catch (final JMSException ignored) {
130 }
131 try {
132 this.connection.close();
133 } catch (final JMSException ignored) {
134 }
135 this.jndiManager.release();
136 }
137
138 private static class JmsConfiguration {
139 private final JndiManager jndiManager;
140 private final String connectionFactoryName;
141 private final String destinationName;
142 private final String username;
143 private final String password;
144
145 private JmsConfiguration(final JndiManager jndiManager, final String connectionFactoryName, final String destinationName,
146 final String username, final String password) {
147 this.jndiManager = jndiManager;
148 this.connectionFactoryName = connectionFactoryName;
149 this.destinationName = destinationName;
150 this.username = username;
151 this.password = password;
152 }
153 }
154
155 private static class JmsManagerFactory implements ManagerFactory<JmsManager, JmsConfiguration> {
156
157 @Override
158 public JmsManager createManager(final String name, final JmsConfiguration data) {
159 try {
160 return new JmsManager(name, data.jndiManager, data.connectionFactoryName, data.destinationName,
161 data.username, data.password);
162 } catch (final Exception e) {
163 LOGGER.error("Error creating JmsManager using ConnectionFactory [{}] and Destination [{}].",
164 data.connectionFactoryName, data.destinationName, e);
165 return null;
166 }
167 }
168 }
169
170 }