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.net.server; 019 020import java.util.concurrent.atomic.AtomicReference; 021import javax.jms.JMSException; 022import javax.jms.Message; 023import javax.jms.MessageConsumer; 024import javax.jms.MessageListener; 025import javax.jms.ObjectMessage; 026 027import org.apache.logging.log4j.Logger; 028import org.apache.logging.log4j.LoggingException; 029import org.apache.logging.log4j.core.LifeCycle; 030import org.apache.logging.log4j.core.LogEvent; 031import org.apache.logging.log4j.core.LogEventListener; 032import org.apache.logging.log4j.core.appender.mom.JmsManager; 033import org.apache.logging.log4j.core.net.JndiManager; 034import org.apache.logging.log4j.status.StatusLogger; 035 036/** 037 * LogEventListener server that receives LogEvents over a JMS {@link javax.jms.Destination}. 038 * 039 * @since 2.1 040 */ 041public class JmsServer extends LogEventListener implements MessageListener, LifeCycle { 042 043 private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED); 044 private final JmsManager jmsManager; 045 private MessageConsumer messageConsumer; 046 047 public JmsServer(final String connectionFactoryBindingName, 048 final String destinationBindingName, 049 final String username, 050 final String password) { 051 final String managerName = JmsServer.class.getName() + '@' + JmsServer.class.hashCode(); 052 final JndiManager jndiManager = JndiManager.getDefaultManager(managerName); 053 jmsManager = JmsManager.getJmsManager(managerName, jndiManager, connectionFactoryBindingName, 054 destinationBindingName, username, password); 055 } 056 057 @Override 058 public State getState() { 059 return state.get(); 060 } 061 062 @Override 063 public void onMessage(final Message message) { 064 try { 065 if (message instanceof ObjectMessage) { 066 final Object body = ((ObjectMessage) message).getObject(); 067 if (body instanceof LogEvent) { 068 log((LogEvent) body); 069 } else { 070 LOGGER.warn("Expected ObjectMessage to contain LogEvent. Got type {} instead.", body.getClass()); 071 } 072 } else { 073 LOGGER.warn("Received message of type {} and JMSType {} which cannot be handled.", message.getClass(), 074 message.getJMSType()); 075 } 076 } catch (final JMSException e) { 077 LOGGER.catching(e); 078 } 079 } 080 081 @Override 082 public void initialize() { 083 } 084 085 @Override 086 public void start() { 087 if (state.compareAndSet(State.INITIALIZED, State.STARTING)) { 088 try { 089 messageConsumer = jmsManager.createMessageConsumer(); 090 messageConsumer.setMessageListener(this); 091 } catch (final JMSException e) { 092 throw new LoggingException(e); 093 } 094 } 095 } 096 097 @Override 098 public void stop() { 099 try { 100 messageConsumer.close(); 101 } catch (final JMSException ignored) { 102 } 103 jmsManager.release(); 104 } 105 106 @Override 107 public boolean isStarted() { 108 return state.get() == State.STARTED; 109 } 110 111 @Override 112 public boolean isStopped() { 113 return state.get() == State.STOPPED; 114 } 115 116}