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 */ 017package org.apache.activemq.util; 018 019import org.apache.logging.log4j.core.Filter; 020import org.apache.logging.log4j.core.Layout; 021import org.apache.logging.log4j.core.LogEvent; 022import org.apache.logging.log4j.core.appender.AbstractAppender; 023 024import java.io.Serializable; 025import java.util.ArrayList; 026import java.util.Iterator; 027import java.util.List; 028import javax.jms.Connection; 029import javax.jms.Destination; 030import javax.jms.JMSException; 031import javax.jms.Message; 032import javax.jms.MessageProducer; 033import javax.jms.Session; 034import javax.naming.NamingException; 035 036 037/** 038 * An abstract base class for implementation inheritence for a log4j JMS 039 * appender 040 */ 041public abstract class JmsLogAppenderSupport extends AbstractAppender { 042 043 private Connection connection; 044 private Session session; 045 private MessageProducer producer; 046 private boolean allowTextMessages = true; 047 private String subjectPrefix = "log4j."; 048 049 public JmsLogAppenderSupport() { 050 this("jmslog", (Filter) null); 051 } 052 053 protected JmsLogAppenderSupport(String name, Filter filter) { 054 super(name, filter, (Layout) null, true); 055 } 056 057 public Connection getConnection() throws JMSException, NamingException { 058 if (connection == null) { 059 connection = createConnection(); 060 } 061 return connection; 062 } 063 064 public void setConnection(Connection connection) { 065 this.connection = connection; 066 } 067 068 public Session getSession() throws JMSException, NamingException { 069 if (session == null) { 070 session = createSession(); 071 } 072 return session; 073 } 074 075 public void setSession(Session session) { 076 this.session = session; 077 } 078 079 public MessageProducer getProducer() throws JMSException, NamingException { 080 if (producer == null) { 081 producer = createProducer(); 082 } 083 return producer; 084 } 085 086 public void setProducer(MessageProducer producer) { 087 this.producer = producer; 088 } 089 090 public void close() { 091 List<JMSException> errors = new ArrayList<JMSException>(); 092 if (producer != null) { 093 try { 094 producer.close(); 095 } catch (JMSException e) { 096 errors.add(e); 097 } 098 } 099 if (session != null) { 100 try { 101 session.close(); 102 } catch (JMSException e) { 103 errors.add(e); 104 } 105 } 106 if (connection != null) { 107 try { 108 connection.close(); 109 } catch (JMSException e) { 110 errors.add(e); 111 } 112 } 113 for (Iterator<JMSException> iter = errors.iterator(); iter.hasNext();) { 114 JMSException e = iter.next(); 115 getHandler().error("Error closing JMS resources: " + e, e); 116 } 117 } 118 119 public boolean requiresLayout() { 120 return false; 121 } 122 123 public void activateOptions() { 124 try { 125 // lets ensure we're all created 126 getProducer(); 127 } catch (Exception e) { 128 getHandler().error("Could not create JMS resources: " + e, e); 129 } 130 } 131 132 // Implementation methods 133 // ------------------------------------------------------------------------- 134 protected abstract Connection createConnection() throws JMSException, NamingException; 135 136 protected Session createSession() throws JMSException, NamingException { 137 return getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE); 138 } 139 140 protected MessageProducer createProducer() throws JMSException, NamingException { 141 return getSession().createProducer(null); 142 } 143 144 private static final ThreadLocal<Object> APPENDING = new ThreadLocal<Object>(); 145 146 public void append(LogEvent event) { 147 if( APPENDING.get()==null ) { 148 APPENDING.set(true); 149 try { 150 Message message = createMessage(event); 151 Destination destination = getDestination(event); 152 getProducer().send(destination, message); 153 } catch (Exception e) { 154 getHandler().error("Could not send message due to: " + e, event, e); 155 } finally { 156 APPENDING.remove(); 157 } 158 } 159 } 160 161 protected Message createMessage(LogEvent event) throws JMSException, NamingException { 162 Message answer = null; 163 Object value = event.getMessage(); 164 if (allowTextMessages && value instanceof String) { 165 answer = getSession().createTextMessage((String)value); 166 } else { 167 answer = getSession().createObjectMessage((Serializable)value); 168 } 169 answer.setStringProperty("level", event.getLevel().toString()); 170 answer.setIntProperty("levelInt", event.getLevel().intLevel()); 171 answer.setStringProperty("threadName", event.getThreadName()); 172 return answer; 173 } 174 175 protected Destination getDestination(LogEvent event) throws JMSException, NamingException { 176 String name = subjectPrefix + event.getLoggerName(); 177 return getSession().createTopic(name); 178 } 179}