All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.skltp.mb.svc.loghandler.JMSQueueAppender Maven / Gradle / Ivy

There is a newer version: 1.0.0-RC9
Show newest version
package se.skltp.mb.svc.loghandler;
//

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.ConnectionFailedException;
import org.apache.log4j.Appender;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.soitoolkit.commons.logentry.schema.v1.LogEvent;
import org.soitoolkit.commons.logentry.schema.v1.LogLevelType;


public class JMSQueueAppender extends AppenderSkeleton implements Appender {


    private static Logger logger = Logger.getLogger(JMSQueueAppender.class);

    private static final ArrayList infoLevels = new ArrayList(Arrays.asList(LogLevelType.INFO, LogLevelType.DEBUG));
    private static final ArrayList errorLevels = new ArrayList(Arrays.asList(LogLevelType.ERROR, LogLevelType.WARNING));

    private Connection connection;


    /**
     * Used by logging methods in {@link se.skltp.mb.svc.services} for pushing data to this class
     */
    private static final ThreadLocal contextData = new ThreadLocal() {

        protected ContextData initialValue() {
            return new ContextData();
        }

    };
    private ConfigBean config;

    public static void setContextData(ContextData data) {
        if ( contextData != null ) {
            if ( data == null ) {
                contextData.remove();
            } else {
                contextData.set(data);
            }
        }
    }

    @Override
    public void close() {

        try {
            connection.close();
        } catch (JMSException e) {
        }
    }

    @Override
    public boolean requiresLayout() {
        return false;
    }

    private ConfigBean getConfig() {

        if ( config == null ) {
            try {
                Context initCtx = new InitialContext();
                Context envCtx = (Context) initCtx.lookup("java:comp/env");
                config = (ConfigBean) envCtx.lookup("bean/MessageboxJmsConfig");
            } catch (NamingException e) {
                throw new ConfigException(e);
            }
        }
        return config;
    }

    public String getComponentName() {
        return getConfig().getComponentName();
    }

    public String getBrokerURL() {
        return getConfig().getBrokerURL();
    }

    public String getInfoQueueName() {
        return getConfig().getInfoQueueName();
    }

    public String getErrorQueueName() {
        return getConfig().getErrorQueueName();
    }

    /**
     * Append event to queue
     */
    protected void append(LoggingEvent event) {
        try {
            if ( !Boolean.parseBoolean(getConfig().getActive()) ) {
                return;
            }

            // Do not process events that originates from this class
            if ( isLogEventFromThisClass(event) ) {
                return;
            }

            try {
                LogEvent logEvent = LogEventCreator.createLogEvent(event, contextData.get(), getComponentName());
                String queue = getQueueName(logEvent.getLogEntry().getMessageInfo().getLevel());
                if ( queue != null ) {
                    logToQueue(queue, marshall(logEvent));
                }

            } catch (Exception e) {
                logger.warn("Could not log message to queue", e);
            }
        } catch (ConfigException e) {
            System.err.println("Unable to access config, not logging " + event.getRenderedMessage());
        }
    }


    /**
     * Send message to queue
     *
     * @param queue name of the queue that the message should be sent to
     * @param xml   the xml string
     */
    private void logToQueue(String queue, String xml) {

        try {
            Session session = getSessionWithRetry();

            Destination dest;
            dest = session.createQueue(queue);
            MessageProducer producer = session.createProducer(dest);
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

            TextMessage msg = session.createTextMessage(xml);
            producer.send(msg);

            // Close session
            session.close();

        } catch (JMSException e) {
            logger.error("Could not log to " + queue + "!", e);

            // Force a new connection to be made on the next request
            if ( connection != null ) {
                connection = null;
            }
        }
    }

    private Session getSessionWithRetry() throws JMSException {
        Session session = null;
        int numRetries = 1;
        int retryCount = 0;
        while ( session == null && retryCount <= numRetries ) {
            try {
                session = getSession();
            } catch (ConnectionFailedException e) {
                if ( retryCount++ < numRetries ) {
                    // force a reconnect
                    connection = null;
                } else {
                    throw e;
                }
            }
        }
        return session;
    }

    /**
     * Retrieve a session
     *
     * @return a new session
     * @throws JMSException
     */
    private Session getSession() throws JMSException {

        if ( connection == null ) {

            ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(getBrokerURL());

            connection = connectionFactory.createConnection();
            connection.start();
        }

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        return session;
    }

    /**
     * Convert the LogEvent object to a string
     *
     * @param logEvent
     * @return
     * @throws JAXBException
     */
    private String marshall(LogEvent logEvent) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(LogEvent.class);

        StringWriter writer = new StringWriter();
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.marshal(logEvent, writer);

        return writer.toString();
    }


    /**
     * Check whether the (log) event originated from this class.
     *
     * @param event
     * @return true if the event originated from this class
     */
    private boolean isLogEventFromThisClass(LoggingEvent event) {
        if ( this.getClass().getName().equals(event.getLoggerName()) ) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * Get the corresponding queue (name) for this log level, or null.
     *
     * @param level log level
     * @return the queue name or null if the message should not be logged
     */
    private String getQueueName(LogLevelType level) {

        if ( level.compareTo(getConfigThreshold(getConfig().getErrorThreshold())) <= 0 ) {
            return getErrorQueueName();
        } else if ( level.compareTo(getConfigThreshold(getConfig().getInfoThreshold())) <= 0 ) {
            return getInfoQueueName();
        }
        return null;
    }

    private LogLevelType getConfigThreshold(String threshold) {
        try {
            return LogLevelType.valueOf(threshold);
        } catch (IllegalArgumentException e) {
            StringBuilder sb = new StringBuilder();
            for ( LogLevelType value : LogLevelType.values() ) {
                sb.append(value).append(",");
            }
            String msg = "'" + threshold + "' is not a valid threshold log level. Must be one of " + sb.toString();
            throw new IllegalArgumentException(msg);
        }
    }

    private static class ConfigException extends RuntimeException {

        public ConfigException(NamingException e) {
            super(e);
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy