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 018package org.apache.logging.log4j.core.appender.mom; 019 020import java.io.Serializable; 021import javax.jms.Connection; 022import javax.jms.ConnectionFactory; 023import javax.jms.Destination; 024import javax.jms.JMSException; 025import javax.jms.Message; 026import javax.jms.MessageConsumer; 027import javax.jms.MessageProducer; 028import javax.jms.Session; 029import javax.naming.NamingException; 030 031import org.apache.logging.log4j.Logger; 032import org.apache.logging.log4j.core.appender.AbstractManager; 033import org.apache.logging.log4j.core.appender.ManagerFactory; 034import org.apache.logging.log4j.core.net.JndiManager; 035import 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 */ 041public 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 if (JndiManager.isJndiJmsEnabled()) { 160 try { 161 return new JmsManager(name, data.jndiManager, data.connectionFactoryName, data.destinationName, 162 data.username, data.password); 163 } catch (final Exception e) { 164 LOGGER.error("Error creating JmsManager using ConnectionFactory [{}] and Destination [{}].", 165 data.connectionFactoryName, data.destinationName, e); 166 return null; 167 } 168 } else { 169 LOGGER.error("JNDI must be enabled by setting log4j2.enableJndiJms=true"); 170 return null; 171 } 172 } 173 } 174 175}