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